概要
Paramikoと今回やることについて、書きます。
paramikoとは
公式サイトの説明はこんな感じです。要するに、SSHをするためのPythonのライブラリです。
Paramiko is a Python (2.7, 3.4+) implementation of the SSHv2 protocol [1], providing both client and server functionality. While it leverages a Python C extension for low level cryptography (Cryptography), Paramiko itself is a pure Python interface around SSH networking concepts.Welcome to Paramiko! — Paramiko documentation
paramikoの使い方は、公式ドキュメントを参照ください。
PythonとSSHと聞くと、真っ先に思い浮かぶのはAnsibleですが、このparamikoはAnsibleにも使われています。
私は数年前に初めてAnsible使ったのですが、その時以下のエラーが出たため、名前はよく覚えていました。
fatal: [iosao1]: FAILED! => {“msg”: “paramiko is not installed: No module named ‘paramiko'”}
Ansibleについては、前に少し書きました。我ながらくそ記事なので、読まなくてよいです。
今回やること
paramikoを使ってスクリプトを書いていたのですが、対話形式の(インタラクティブな)コマンドを実行するのに少し苦労したので、まとめておきます。
全体の環境は以下の通りです。図を書くまでもないですが…
- SSH元: 自宅のMacbookから
- SSH先: AWSのEC2(Amazon Linuxに対して、コマンドを実行
実行するのは、fdisk
です。ディスクのパーティションを切ったりするコマンドで、対話形式で動作します。動作例は、以下を参照。
ちなみにparted
コマンドなら、非インタラクティブにディスク操作できます。
Pythonとparamikoのバージョンは以下の通りです。
- Python 3.6.6
- paramiko 2.6.0
実装内容
全体では、以下のような構成です。
1 2 3 4 5 6 |
$ tree . . ├── credentials.py <- (認証情報を外だし) ├── paramiko_interactive.py <- (今回実装したコード) └── [pemファイル] |
credentials.py
SSH接続するための情報は、credentials.py
に入れています。例えばこんな感じです。
paramiko-interactive.py
ここからは、paramiko-interactive.py
を見ていきます。今回はクラスとして実装しました。
まず、paramiko
とcredentials.py
に書いた変数をimport
します。SSHして実行するコマンドは、sudo fdisk /dev/sda
とします。
1 2 3 4 5 6 7 8 9 |
class Interactive: import credentials import paramiko def __init__(self): self.PORT = self.credentials.PORT self.USER = self.credentials.USER self.PEM = self.credentials.PEM self.FDISK_CMD = 'sudo fdisk /dev/sda' |
fdisk_test
関数で、SSH接続しコマンドを実行します。
対象EC2インスタンスのパブリックIP又はパブリックDNSのリストを渡して実行すると、対象ホストと実行時の標準出力の組をdict
として返します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
def fdisk_test(self, hosts): rd = {} for host in hosts: ssh = self.paramiko.SSHClient() ssh.set_missing_host_key_policy(self.paramiko.AutoAddPolicy()) ssh.connect(host, self.PORT, self.USER, key_filename=self.PEM) stdin, stdout, _ = ssh.exec_command(self.FDISK_CMD) stdin.write('m\n') stdin.flush() stdin.write('q\n') stdin.flush() output = stdout.readlines() rd[host] = output return rd |
実行するコマンドの流れは、こんな感じです。
* まず、sudo fdisk /dev/sda
を実行
* シェルがコマンド (m でヘルプ):
と聞いてくるので、m
を入力しEnter(\n
)を押す
* マミュアルが表示される
* シェルが再びコマンド (m でヘルプ):
と聞いてくるので、q
を入力しEnter(\n
)を押す
* コマンドが終了する
実行例
当たり前ですが、以下のように使えます。
1 2 3 4 5 |
import paramiko_interactive i = paramiko_interactive.Interactive() hosts = ['YOUR HOST A', 'YOUR HOST B'] i.fdisk_test(hosts) |
返ってくるのは、例えばこんな感じ。value
の部分は、\n
を消す等して、もう少し見やすくするべきかもしれません。
1 2 3 4 5 |
{ 'YOUR HOST A': ['\n', 'Welcome to fdisk (util-linux 2.30.2).\n', 'Changes will remain in memory only, until you decide to write them.\n', 'Be careful before using the write command.\n', '\n', '\n', 'Command (m for help): \n', 'Help:\n', '\n', ' Generic\n', ' d delete a partition\n', ' F list free unpartitioned space\n', ' l list known partition types\n', ' n add a new partition\n', ' p print the partition table\n', ' t change a partition type\n', ' v verify the partition table\n', ' i print information about a partition\n', '\n', ' Misc\n', ' m print this menu\n', ' x extra functionality (experts only)\n', '\n', ' Script\n', ' I load disk layout from sfdisk script file\n', ' O dump disk layout to sfdisk script file\n', '\n', ' Save & Exit\n', ' w write table to disk and exit\n', ' q quit without saving changes\n', '\n', ' Create a new label\n', ' g create a new empty GPT partition table\n', ' G create a new empty SGI (IRIX) partition table\n', ' o create a new empty DOS partition table\n', ' s create a new empty Sun partition table\n', '\n', '\n', 'Command (m for help): \n'], 'YOUR HOST B': ['\n', 'Welcome to fdisk (util-linux 2.30.2).\n', 'Changes will remain in memory only, until you decide to write them.\n', 'Be careful before using the write command.\n', '\n', '\n', 'Command (m for help): \n', 'Help:\n', '\n', ' Generic\n', ' d delete a partition\n', ' F list free unpartitioned space\n', ' l list known partition types\n', ' n add a new partition\n', ' p print the partition table\n', ' t change a partition type\n', ' v verify the partition table\n', ' i print information about a partition\n', '\n', ' Misc\n', ' m print this menu\n', ' x extra functionality (experts only)\n', '\n', ' Script\n', ' I load disk layout from sfdisk script file\n', ' O dump disk layout to sfdisk script file\n', '\n', ' Save & Exit\n', ' w write table to disk and exit\n', ' q quit without saving changes\n', '\n', ' Create a new label\n', ' g create a new empty GPT partition table\n', ' G create a new empty SGI (IRIX) partition table\n', ' o create a new empty DOS partition table\n', ' s create a new empty Sun partition table\n', '\n', '\n', 'Command (m for help): \n'] } |
さいごに
paramiko、簡単に使えて便利ですね。Ansibleを使えばよくね?という話もありますが、Ansible使うほどでもないとか、Ansibleのメンテしたくないとか、WindowsマシンからLinuxマシンにSSHで接続したいという時には便利かもしれないですね。
今回のコードは、GitHubにあげました。よければどうぞ。
以上.
コメント