LoginSignup
3
3

More than 5 years have passed since last update.

【備忘録】pexpectのsshをメソッド化

Last updated at Posted at 2018-10-04

pythonでsshできるようにしたく、送ったコマンドの実行結果をprintしてファイルに吐かせたかったものの結構手こずりました。
sshは鍵認証とパスワード認証があり、いちいち書くのが面倒なのでメソッド化しちゃえと思った次第です。

読み込むファイル

list.txt
user host pass
例:

tarou 172.16.1.1 password
hanako 172.1.2 -

#tarouさんはパスワード認証です
#hanakoさんはすでに鍵交換されています

pexpectのインポート

ssh.py
def ssh_connect(user, hostname, password, command):
    FIRST_MESSAGE = "Are you sure you want to continue connecting"
    #パスワードが'-'の場合は鍵認証とします。
    if password == '-':
        ssh = pexpect.run('ssh %s@%s %s' % (user, hostname, command))
        #改行コードの削除
        res = ssh.strip()
        #byte形式なのでstr型に変換
        res = res.decode('utf-8')
    else:  #それ以外はパスワード認証です
        ssh = pexpect.spawn('ssh %s@%s %s' % (user, hostname, command))
        #初回アクセス時の対応です
        ret = ssh.expect([FIRST_MESSAGE, 'assword:*', pexpect.EOF, pexpect.TIMEOUT])
        if ret == 0:
            ssh.sendline("yes")
            ssh.expect('assword:*')
            ssh.sendline(password)
        if ret == 1:
            ssh.sendline(password)
        ssh.expect(pexpect.EOF)
        res = ssh.before
        res = res.strip()
        res = res.decode('utf-8')
    return res

ハマったところ

パスワード認証で結果が返ってこなかった。

原因:出力メッセージの取得法をわかっていなかったよう。
当初やったこと

1st.py
ssh.sendline(password)
res = ssh.before

結果

b'(assword)'

返ってきた結果に対して終わりを示すexpect(pexpect.EOF)を入れないとだめらしい。
ってことで

2nd.py
ssh.sendline(password)
ssh.expect(pexpect.EOF)
res = ssh.before

とすることで実行結果を取得できる。

結果には改行コードがもれなくついてくるのでstrip()で除去、
その上で、型式がbyte型なので.decode()でstring型に変換する。

これをprint(res, file=log_file)とすることで画面に出力とログへの吐き出しをしてくれる。

これでシェル依存から脱却できるかしら。。。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3