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)とすることで画面に出力とログへの吐き出しをしてくれる。
これでシェル依存から脱却できるかしら。。。