zaki work log

作業ログやら生活ログやらなんやら

[コードメモ] Paramikoを使ってPythonでsshする (公開鍵認証)

いきなりサンプルコード。

import paramiko

# 接続
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect("192.168.0.20", username='zaki', key_filename="/home/zaki/.ssh/id_rsa_nopass")

stdin, stdout, stderr = client.exec_command("hostname")
for line in stdout:
    print(line)

client.close()

192.168.0.20にある対向サーバーはCentOS 7の標準のsshdサーバーで、ユーザーzakiで公開鍵認証設定が行われている状態。
秘密鍵ファイルは/home/zaki/.ssh/id_rsa_nopassにあって、パスフレーズは無し。

これで

client.load_system_host_keys()
client.connect()

で接続。

stdin, stdout, stderr = client.exec_command("hostname")

で、sshのコネクション先でコマンド実行。

(paramiko) [zaki@cloud-dev paramiko]$ python sample.py 
manager-dev

ちなみにip aだとコマンドが見つからないというエラーになったため、hostnameのある/usr/binにはパスが通っているが、ipのある/usr/sbinにはパスが設定されていない模様。

client.exec_command("echo $PATH")

試しにこれを実行すると

(paramiko) [zaki@cloud-dev paramiko]$ python sample.py 
/usr/local/bin:/usr/bin

Exception ignored in: <object repr() failed>
Traceback (most recent call last):
  File "/home/zaki/ansible/paramiko/lib/python3.6/site-packages/paramiko/file.py", line 66, in __del__
  File "/home/zaki/ansible/paramiko/lib/python3.6/site-packages/paramiko/channel.py", line 1392, in close
  File "/home/zaki/ansible/paramiko/lib/python3.6/site-packages/paramiko/channel.py", line 991, in shutdown_write
  File "/home/zaki/ansible/paramiko/lib/python3.6/site-packages/paramiko/channel.py", line 963, in shutdown
  File "/home/zaki/ansible/paramiko/lib/python3.6/site-packages/paramiko/channel.py", line 1246, in _send_eof
  File "/home/zaki/ansible/paramiko/lib/python3.6/site-packages/paramiko/message.py", line 232, in add_int
TypeError: 'NoneType' object is not callable

となったため、なぜエラーが発生したかはともかく、PATHは通常のsshを使ったログインとは少し異なるようだ。
インタラクティブじゃないからとかその辺かなぁ。(未確認)

client.exec_command("/usr/sbin/ip a")

フルパスであればもちろん動く。


(paramiko) [zaki@cloud-dev paramiko]$ ssh 192.168.0.20 -i ~/.ssh/id_rsa_nopass 'echo $PATH'
/usr/local/bin:/usr/bin
(paramiko) [zaki@cloud-dev paramiko]$ ssh 192.168.0.20 -i ~/.ssh/id_rsa_nopass -t 'echo $PATH'
/usr/local/bin:/usr/bin
Connection to 192.168.0.20 closed.
(paramiko) [zaki@cloud-dev paramiko]$ ssh 192.168.0.20 -i ~/.ssh/id_rsa_nopass -tt 'echo $PATH'
/usr/local/bin:/usr/bin
Connection to 192.168.0.20 closed.

違うか。別の理由かな


書き忘れてたけど、使用にはparamikoが必要なのでpipでインストールしておく。

$ pip3 install paramiko

無いとエラーになる

(paramiko) [zaki@cloud-dev paramiko]$ python sample.py 
Traceback (most recent call last):
  File "sample.py", line 1, in <module>
    import paramiko
ModuleNotFoundError: No module named 'paramiko'

ちなみに、ssh処理をするコードを書きたくて前情報無しの状態で一番最初に見るのはParamikoのドキュメントよりも、Demoコードが載っているGitHubのReadmeが良いかもしれない。

github.com

docs.paramiko.org

www.paramiko.org