SSH を使う¶
SSH を使ってリモートのサーバを操作してみます。 今回と次回は Linux もしくは Mac OSX での実装を想定しています。 Windows しか使わない / 使えない場合はスキップしてください。
リモートサーバの操作¶
ssh コマンドを subprocess.call() に渡します。
>>> import subprocess
>>> subprocess.call(["ssh", "localhost"])
ssh: connect to host localhost port 22: Connection refused
255
localhost で sshd を立ち上げていない場合は、上記のように接続を拒否されます。 sshd を起動してから再度実行します。
>>> subprocess.call(["ssh", "localhost"])
Password:
Last login: Mon Dec 12 23:28:03 2011 from localhost
SK-MackBook-Pro:~ shigeru$
ssh の引数でコマンドを渡すと、ログインした先で実行されます。
>>> subprocess.call(["ssh", "localhost", "uname", "-v"])
Password:
Could not open a connection to your authentication agent.
Darwin Kernel Version 11.2.0: Tue Aug 9 20:54:00 PDT 2011; root:xnu-1699.24.8~1/RELEASE_X86_64
0
あとはコマンドを羅列していけば任意の処理を実現できます。 しかし、シェルスクリプトをベースにした戻り値の確認はややこしいですし、コネクションを毎回張るのも煩雑なので、 Python のモジュールを利用していきましょう。
paramiko を使う¶
SSH プロトコルを扱うモジュールとして paramiko があります。 コマンドを単に羅列するよりもプラグラマブルに管理できます。
requirements.txt に paramiko を追加し、 pip でインストールします。
$ echo "paramiko" >> requirements.txt
$ pip install -r requirements.txt
paramiko はバージョン 1.13 以降から Python 3.x 系に対応しましたので、 まずはモジュールが読み込めることを確認します。 すべてを表示すると多すぎるので、大文字の “SSH” から始まるものを抜粋しましょう。
>>> import paramiko
>>> ", ".join(filter(lambda s: s.startswith("SSH"), dir(paramiko)))
'SSHClient, SSHConfig, SSHException'
サーバにログインして uptime コマンドを実行します。
cmdline-5.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import getpass
import paramiko
server = "localhost"
username = password = None
try:
u = getpass.getuser()
username = input("Username: (Default=%s) " % (u,))
if not username:
username = u
password = getpass.getpass("Password: ")
except KeyboardInterrupt:
raise SystemExit("Cancel")
if not password:
raise SystemExit("No password is given.")
t = paramiko.Transport((server, 22))
try:
t.connect(username=username, password=password, hostkey=None)
except:
t.close()
raise SystemExit("Bad username or password.")
ch = t.open_channel(kind="session")
ch.exec_command("uptime")
if ch.recv_ready:
print(server + ": " + ch.recv(1000))
t.close()
paramiko.Transport を使っていますが paramiko.SSHClient でも実現できます。 興味があれば、様々な API を使ってみてください。
また、上記のスクリプトは input() と getpass モジュールを使っています。 パスワードの入力が必要な場合には覚えておきましょう。
- 16.10. getpass — Portable password input (公式ドキュメント)