Python School 2.0.0 documentation

SSH を使う

«  シェルコマンドを実行する   ::   Contents   ::   fabric を使う  »

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.txtparamiko を追加し、 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 モジュールを使っています。 パスワードの入力が必要な場合には覚えておきましょう。

«  シェルコマンドを実行する   ::   Contents   ::   fabric を使う  »