QA@IT

Paramiko で passwd コマンドを実行したい

2592 PV

Python でサーバー管理スクリプトを書いています。

やりたい事:

  • SSH で該当サーバーに接続
  • SSH 経由で passwd のようなインタラクティブコマンドを処理 (expect のような事がしたい)

ライブラリは paramiko を選びました。以下のようなコードを調べつつ書いてみたのですが、タイムアウトしてしまいます。問題点を指摘して頂けると嬉しいです。

#!/usr/bin/env python

import time
import paramiko

class InteractiveCommand(object):

    def __init__(self, host, port, user, password):
        self.transport = paramiko.Transport((host, port))
        self.transport.connect(username=user, password=password)
        self.channel = self.transport.open_session()

    def run(self, command):
        out = ''
        self.channel.setblocking(0)
        self.channel.invoke_shell()
        self.channel.send(command + '\n')
        t_check = 0

        while not self.channel.recv_ready():
            time.sleep(5)
            t_check += 1

            if 3 < t_check:
                print 'time out!'
                return False

        out = self.channel.recv(1024)
        return out

if __name__ == u'__main__':
    shell = InteractiveCommand('exmaple.com', 22, 'user', 'password')
    shell.run('passwd user')

実行結果は以下のようになります:

$ python ./test.py
time out!

paramiko を使用したインタラクティブ処理の実装例など参考になるサイトなど教えて頂けるのでも構いません。

どうぞよろしくお願いします。

回答

passwd コマンドは、標準入出力が端末 (tty) であることを期待してます。それらとプロセス間通信するには、疑似端末 (pty(7)) を作成して接続する必要があります。Python で pty(7) を扱うモジュールを探してみてください。Paramiko だけでも pty を扱えるようなので、これで充分なのかもしれません。

Python ではないですが、passwd と通信して非対話でパスワード変更するコードを C で書いたことがあります。参考になるかわかりませんが紹介しておきます。古いコードなので、最近の OS ではうまく動かない可能性があります。

Red Hat Enterprise Linux (RHEL) やそのクローン OS、Debian, Ubuntu であれば、バッチ処理でパスワードを変更するための chpasswd コマンドがあります。passwd を相手にするより chpasswd を利用するほうが簡単だと思います。使い方はオンラインマニュアルを見てください。

ただし、RHEL の chpasswd は PAM が無効になっているので、ローカルの /etc/shadow のパスワードしか変更できません。また、Debian で LDAP サーバーのユーザーのパスワード変更を試してみましたが、以下のようになり動作しませんでした。原因は追っていません。

# echo 'foobar:password' |chpasswd
chpasswd: (user foobar) pam_chauthtok() failed, error:
User not known to the underlying authentication module
chpasswd: (line 1, user foobar) password not changed
編集 履歴 (2)
ウォッチ

この質問への回答やコメントをメールでお知らせします。