見出し画像

ec2インスタンスにpexpectでアクセスしてコマンドを実行する[Python]

ec2インスタンスにpexpectでアクセスしてコマンドを実行する方法を説明します.

abstract


# ライブラリのインポート なければ pip install pexpect
import pexpect

# ec2にssh
child = pexpect.spawn('ssh -i ~/.ssh/user.pem ec2-user@xxx.xxx.xxx.xxx')

# プロンプトが現れるのを待つ ここが正しくないとその後の処理もうまく行われない
child.expect("\[ec2-user@ip-xxx-xxx-xxx-xxx ~]\$")

# コマンドの準備
ls = 'ls -l'

# コマンド実行
child.sendline(ls)

# コマンド実行後のプロンプトが現るのを待つ
child.expect("\[ec2-user@ip-xxx-xxx-xxx-xxx ~]\$")

# 一つ前のexpectから一行上のexpectまでの出力を取得,バイナリ形式のため文字列に変換
res = child.before
print(res.decode('utf-8'))

# 終了
child.close()

EC2インスタンスの作成

pexpectの実験のために作成するインスタンスなので最小限で作成しています.お好みの設定にして作成してください.

EC2の画面からインスタンスの起動を選択

- 無料利用枠のAmazon Linux 64ビット(x86)を選択

画像1

- 無料利用枠のt2.microを選択

画像2

- セキュリティグループの編集で,sshのソースにマイIPを指定

画像3

画像4

- 作成したインスタンスの概要に書いてあるパブリックIPv4アドレスをコピーしておく

EC2インスタンスにssh

AWSのEC2にmacからSSHする方法の記事を参考にインスタンスにsshができることを確かめてください.
macからのsshからしか試していないため,他のOSの人は各自で調べてください.

pexpectの準備

Python3系がすでにインストールされていることを想定しています.
pexpectをpipでインストールします.

$pip install pexpect

pexpectでコマンドを実行

以下のサンプルプログラムはssh先のインスタンスでtouchコマンドでファイルを作成して,ls -lコマンドでその結果を取得しています.(ipアドレスはマスクしているため,適宜自分の環境に合わせてください)

child.sendline()でコマンドを実行し,child.expect()で一区切り,child.beforeで出力結果を取得するという流れです

ハマりどころは以下です.
- 実行結果が空文字の場合は,expectがうまく設定できていない
- expectに指定する文字列で正規表現がつかえない
  - いくつかのサイトでは expect(".*") のように指定していましたが,そのような指定ではうまく行かなかったため,プロンプトの文字列をそのまま書いています.
- [ はエスケープが必要なので \[ にする
- 文字列がバイナリで帰ってくるので,strにdecodeする

import pexpect

child = pexpect.spawn('ssh -i ~/.ssh/user.pem ec2-user@xxx.xxx.xxx.xxx')
child.expect("\[ec2-user@ip-xxx-xxx-xxx-xxx ~]\$")

touch = 'touch test.txt'
child.sendline(touch)
child.expect("\[ec2-user@ip-xxx-xxx-xxx-xxx ~]\$")
res = child.before
print(res.decode('utf-8'))

ls = 'ls -l'
child.sendline(ls)
child.expect("\[ec2-user@ip-xxx-xxx-xxx-xxx ~]\$")
res = child.before
print(res.decode('utf-8'))

child.close()

以下がその実行結果です.

$python3 test.py
touch test.txt
^[kec2-user@ip-xxx-xxx-xxx-xxx:~^[\
ls -l
合計 0
-rw-rw-r-- 1 ec2-user ec2-user 0  712 13:45 test.txt
^[kec2-user@ip-xxx-xxx-xxx-xxx:~^[\

この記事が気に入ったらサポートをしてみませんか?