Python pexpectモジュール及びshellスクリプトexcept原理解析
expectスクリプト
expectは何ですか
expectは無料のプログラミングツールで、人為的な干渉なしに自動的なインタラクティブタスクを実現します。はっきり言って、expectは自動的なインタラクティブ機能を実現するためのソフトウェアです。
実際の作業では、コマンド、スクリプト、またはプログラムを実行するとき、これらのコマンド、スクリプトまたはプログラムは端末からいくつかの継続的な実行命令を入力する必要がありますが、これらの入力は人工的な手動で行う必要があります。expectを利用すれば、プログラムの提示によって、アナログ標準入力がプログラムに提供され、自動化インタラクティブ実行が可能になります。
Linuxのコマンドのいくつかは、スクリプトの自動化動作にあまり適していません。例えば、fdisk、telnet、ftp接続のダウンロードなどです。だから、exceptを使って交換問題を解決しなければなりません。
exceptの基礎
次の4つのコマンドを含みます。
コマンド
作用
send
プロセスに文字列を送信するために使用します。
except
プロセスから文字列を受信
spwan
新しいプロセスを開始
インターアクト
ユーザーのインタラクションを許可する sendコマンドは、文字列パラメータを受信し、このパラメータをプロセスに送信する。 expectコマンドとsendコマンドは反対に、expectは通常、プロセスのフィードバックを待って、対応するインタラクティブコマンドを送信します。 spawnコマンドは、新しいプロセスを開始するために使用され、spawn後のsendとexpectコマンドは、spawnを使用して開くプロセスと相互作用します。 interact命令用はそんなに多くないです。普通はspawn、sendとexpect命令を使って私達の任務をよく完成できます。しかし、いくつかの特殊な場合にはインターアクトコマンドを使用する必要があります。インターアクトコマンドは主に自動化を解除し、人工的なインタラクションに入るために使用されます。例えば、spawn、send、expectコマンドを使って、ftpをホストに登録して、ダウンロードファイルのタスクを実行しましたが、ファイルのダウンロードが終わったら、ftpコマンドラインの状態に留まり、手動で後続命令を実行します。
コードの例
ヽusr/bin/expect:expectを用いてスクリプトを説明します。
set timeout 30:タイムアウト時間を設定し、単位は秒で、デフォルトでは10秒です。
set host「101.241.109」:変数を設定します。
spawn ssh@username@host:spawnはexpect環境に入ってから実行できるexpect内部コマンドです。もしexpectを入れていないなら、またはデフォルトのSHELLで直接実行してもspawnコマンドは見つけられません。主な機能は、ssh実行プロセスにシェルを追加して、インタラクティブ命令を伝達することです。
expect「password」:ここのexpectもexpectの内部コマンドです。このコマンドは前回の出力結果に「password」という文字列が含まれているかどうかを判断し、あればすぐに戻ります。しばらく待ってから戻ってきます。ここで待つと30秒前に設定されています。
send「$password\r」:対応する出力結果に一致すると、開いているsshプロセスにパスワードを送信し、インタラクティブ動作を実行する。
インターアクト:実行が完了したら、インタラクティブな状態を維持して、コントロールをコンソールに任せてください。この時は手作業で操作できます。これがないとリモート端末に残してはいけません。
これは上記の簡単なシナリオの分析であり、上記の例では、expectの中の非常に重要な概念であるモード−動作に関するものである。つまり上記のexpect「password」というコードの意味です。
モード→動作
expectの「password」というコードを結び付けて、「モード-動作」と言います。簡単に言えば、一つのモードにマッチして、対応する動作を実行します。password文字列にマッチしたらパスワードを入力します。
以下の通りです
参を回す
多くの場合、私たちはパラメータを台本に送りたいです。今は下記のコードを通じて、expectでパラメータを使う方法を見てみます。
FTPダウンロードexpectスクリプト
yumを使ってexpectをインストールします。
yum install expect
次のようにexpectスクリプトを作成します。
pexpectモジュール
pexpectはlinux下のexpectのpythonパッケージとして理解でき、pexpectを通じてssh、ftp、passwd、telnetなどのコマンドの自動的なインタラクションが可能です。
pip install pexpectをインストールします。
簡単なssh自動登録の例は以下の通りです。
spawn類
spawnはpexpectの主な入り口で、機能はサブアプリケーションを起動して制御するので、以下はその構造関数です。
class pexpect.spwan(command、args=[]、timeout=30、maxread=2000、search windowsize=None、logfile=None、cwd=None、env=None、ignore_sighup=True)
ここで、commandパラメータは、任意の既知のシステム命令であってもよい。
注意したいのは、pexpextはshellコマンドの中のメタ文字を解析しません。リダイレクトパイプやワイルドカードを含みます。この時、3つの特殊要素文字のコマンドを/bin/bashのパラメータとして呼び出すことができます。
child=expect.spwan('/bin/bash-c"ls-l grep LOG'logs.txt")
child.expect(pexpect.EOF)
コマンドのパラメータをPYTHONリストに置き換えることで、文法がより明確になります。以下のコードは上のコードと同じです。
shell_cmd='ls-l grep LOG'logs.txt'
child=pexpext.spwan('/bin/bash','-c,shell_cmd)
child.expect(pexpect.EOF)
デバッグコードの場合は、pexpectの入力と出力情報を取得して、マッチングの状況を把握したいです。一つはログに記入し、もう一つは標準出力に出力します。
日記に書く
チdl-pexpect.spwan('some_command
fout=file('mylogs.txt,'w')
child.logfile=fout
標準出力に出力する方法
child=pexpect.swpan('some_command
chuld.logfile=sys.stdout
SSHリモート登録の例を示します。登録が成功したらホームディレクトリのファイルを表示し、入力と出力を記録します。
expectはサブルーチン出力の整合規則を定義しています。
方法定義:expect(pattern、timeout=-1、search windowsize=-1)
ここで、パラメータpatternは文字列、pexpext.EOF(バッファ領域を指し、マッチング項目がない)、pexpect、TIMEOUT(タイムアウト待ちと一致する)、正規表現またはリストを表します。
パラメータtimeoutはマッチング結果を待つタイムアウト時間を指定しました。単位は秒で、タイムアウトがトリガされると、expectはpexpext.TIMEOUT、パラメータsearch windowsizeがマッチングするバッファ文字列の位置にマッチします。デフォルトでは開始位置からマッチします。
read関連方法
以下の方法の役割は、サブプログラムに応答コマンドを送信することです。
send(self,s)ハ送命令,回車しない
sendline(self,s=')は、菗が命令を送り、車を返す。
snedcontrol(self.chal)菗送信制御文字
sendeof()菗送eof
run関数
runの場合は、pexpextを使用してパッケージの外部コマンドを呼び出す関数です。
from pexpect import*
run('scp foo)[email protected]:',events='(i)password':mypassword』)
pxssh類
sshセッション操作に対してもう一回パッケージを作ります。
class pexpext.pxssh.pxssh(timeout=30、maxread=2000、search winddwosize=None、logfile=None、cwd=None、env=None)
一般的な方法 login()ssh接続 を確立する。 logout()切断 promp()は、命令の実行終了を待つためにシステムプロンプトを待っています。
自動インタラクティブ登録FTP操作を実現する。
expectは何ですか
expectは無料のプログラミングツールで、人為的な干渉なしに自動的なインタラクティブタスクを実現します。はっきり言って、expectは自動的なインタラクティブ機能を実現するためのソフトウェアです。
実際の作業では、コマンド、スクリプト、またはプログラムを実行するとき、これらのコマンド、スクリプトまたはプログラムは端末からいくつかの継続的な実行命令を入力する必要がありますが、これらの入力は人工的な手動で行う必要があります。expectを利用すれば、プログラムの提示によって、アナログ標準入力がプログラムに提供され、自動化インタラクティブ実行が可能になります。
Linuxのコマンドのいくつかは、スクリプトの自動化動作にあまり適していません。例えば、fdisk、telnet、ftp接続のダウンロードなどです。だから、exceptを使って交換問題を解決しなければなりません。
exceptの基礎
次の4つのコマンドを含みます。
コマンド
作用
send
プロセスに文字列を送信するために使用します。
except
プロセスから文字列を受信
spwan
新しいプロセスを開始
インターアクト
ユーザーのインタラクションを許可する
#!/usr/bin/expect
set timeout 30
set host "101.200.241.109"
set username "root"
set password "123456"
spawn ssh $username@$host
expect "*password*" {send "$password\r"}
interact
これは非常に簡単なコードです。基本的な使い方を示しています。ヽusr/bin/expect:expectを用いてスクリプトを説明します。
set timeout 30:タイムアウト時間を設定し、単位は秒で、デフォルトでは10秒です。
set host「101.241.109」:変数を設定します。
spawn ssh@username@host:spawnはexpect環境に入ってから実行できるexpect内部コマンドです。もしexpectを入れていないなら、またはデフォルトのSHELLで直接実行してもspawnコマンドは見つけられません。主な機能は、ssh実行プロセスにシェルを追加して、インタラクティブ命令を伝達することです。
expect「password」:ここのexpectもexpectの内部コマンドです。このコマンドは前回の出力結果に「password」という文字列が含まれているかどうかを判断し、あればすぐに戻ります。しばらく待ってから戻ってきます。ここで待つと30秒前に設定されています。
send「$password\r」:対応する出力結果に一致すると、開いているsshプロセスにパスワードを送信し、インタラクティブ動作を実行する。
インターアクト:実行が完了したら、インタラクティブな状態を維持して、コントロールをコンソールに任せてください。この時は手作業で操作できます。これがないとリモート端末に残してはいけません。
これは上記の簡単なシナリオの分析であり、上記の例では、expectの中の非常に重要な概念であるモード−動作に関するものである。つまり上記のexpect「password」というコードの意味です。
モード→動作
expectの「password」というコードを結び付けて、「モード-動作」と言います。簡単に言えば、一つのモードにマッチして、対応する動作を実行します。password文字列にマッチしたらパスワードを入力します。
以下の通りです
expect {
"password" {
send "$password\r"
exp_continue
}
eof
{
send "eof"
}
}
その中でもexp_continueは循環式のマッチングを表しています。普通はマッチングしてから文を終了しますが、もしexp_があれば。continueは絶えずマッチングして、複数のコマンドを入力して、書き方を簡略化します。参を回す
多くの場合、私たちはパラメータを台本に送りたいです。今は下記のコードを通じて、expectでパラメータを使う方法を見てみます。
#!/usr/bin/expect
if {$argc < 3} {
puts "Usage:cmd <host> <username> <password>"
exit 1
}
set timeout -1
set host [lindex $argv 0]
set username [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $username@$host
expect "*password*" {send "$password\r"}
interact
expectでは、\$argcはパラメータの個数を表していますが、参照値は$argvに保存されています。例えば、最初のパラメータを取ると、「lindex$argv 0」となります。FTPダウンロードexpectスクリプト
yumを使ってexpectをインストールします。
yum install expect
次のようにexpectスクリプトを作成します。
#!/usr/bin/expect -f
set ip [lindex $argv 0] # , IP
set file [lindex $argv 1] # ,
set timeout 10 # 10
spawn ftp $ip # ftp $ip
expect "Name*" # Name
send "anonymous \r" # anoymous( )
expect "Password:*" # Password
send "\r" #
expect "ftp>*" # ftp>
send "get $file\r" # get $file
expect {
"*Failed*" { send_user " Download failed\r";send "quit\r"} # Failed, ,send_user Download failed
"*send*" { send_user " Download ok\r";send "quit\r"} # send, ,send_user Download ok
}
expect eof #
スクリプトに実行可能権限chmod+x expect_を追加します。ftp_at.exppexpectモジュール
pexpectはlinux下のexpectのpythonパッケージとして理解でき、pexpectを通じてssh、ftp、passwd、telnetなどのコマンドの自動的なインタラクションが可能です。
pip install pexpectをインストールします。
簡単なssh自動登録の例は以下の通りです。
import pexpect
child = pexpect.spwan('scp foo user#expample.com:.') #spwan scp
child.expect('Password:') #expect ,
#‘Password:'
child.sendline(mypassword) #
コアコンポーネントspawn類
spawnはpexpectの主な入り口で、機能はサブアプリケーションを起動して制御するので、以下はその構造関数です。
class pexpect.spwan(command、args=[]、timeout=30、maxread=2000、search windowsize=None、logfile=None、cwd=None、env=None、ignore_sighup=True)
ここで、commandパラメータは、任意の既知のシステム命令であってもよい。
child=pexpect.spawn('user/bin/ftp')
サブプログラムにパラメータが必要な場合は、パラメータの代わりにpythonリストを使用することもできます。child = pexpect.spwan('user/bin/ssh [email protected]')
パラメータtimeoutは結果待ちのタイムアウト時間であり、maxreadは端末コンソールから一度に読み取られる最大バイト数であり、search windowsizeパラメータは整合するバッファ領域文字列の位置であり、デフォルトでは開始位置からマッチングする。注意したいのは、pexpextはshellコマンドの中のメタ文字を解析しません。リダイレクトパイプやワイルドカードを含みます。この時、3つの特殊要素文字のコマンドを/bin/bashのパラメータとして呼び出すことができます。
child=expect.spwan('/bin/bash-c"ls-l grep LOG'logs.txt")
child.expect(pexpect.EOF)
コマンドのパラメータをPYTHONリストに置き換えることで、文法がより明確になります。以下のコードは上のコードと同じです。
shell_cmd='ls-l grep LOG'logs.txt'
child=pexpext.spwan('/bin/bash','-c,shell_cmd)
child.expect(pexpect.EOF)
デバッグコードの場合は、pexpectの入力と出力情報を取得して、マッチングの状況を把握したいです。一つはログに記入し、もう一つは標準出力に出力します。
日記に書く
チdl-pexpect.spwan('some_command
fout=file('mylogs.txt,'w')
child.logfile=fout
標準出力に出力する方法
child=pexpect.swpan('some_command
chuld.logfile=sys.stdout
SSHリモート登録の例を示します。登録が成功したらホームディレクトリのファイルを表示し、入力と出力を記録します。
import pexpect
import sys
child=pexpect.spawn('ssh [email protected]')
fout=open('mylog.txt','w')
child.logfile=fout
#child.logfile=sys.stdout
child.expect('password:')
child.sendline('abc@123')
child.expect('#')
child.sendline('ls /home')
child.expect('#')
expectの方法expectはサブルーチン出力の整合規則を定義しています。
方法定義:expect(pattern、timeout=-1、search windowsize=-1)
ここで、パラメータpatternは文字列、pexpext.EOF(バッファ領域を指し、マッチング項目がない)、pexpect、TIMEOUT(タイムアウト待ちと一致する)、正規表現またはリストを表します。
パラメータtimeoutはマッチング結果を待つタイムアウト時間を指定しました。単位は秒で、タイムアウトがトリガされると、expectはpexpext.TIMEOUT、パラメータsearch windowsizeがマッチングするバッファ文字列の位置にマッチします。デフォルトでは開始位置からマッチします。
read関連方法
以下の方法の役割は、サブプログラムに応答コマンドを送信することです。
send(self,s)ハ送命令,回車しない
sendline(self,s=')は、菗が命令を送り、車を返す。
snedcontrol(self.chal)菗送信制御文字
sendeof()菗送eof
run関数
runの場合は、pexpextを使用してパッケージの外部コマンドを呼び出す関数です。
from pexpect import*
run('scp foo)[email protected]:',events='(i)password':mypassword』)
pxssh類
sshセッション操作に対してもう一回パッケージを作ります。
class pexpext.pxssh.pxssh(timeout=30、maxread=2000、search winddwosize=None、logfile=None、cwd=None、env=None)
一般的な方法
import pxssh
import getpass
try:
s = pxssh.pxssh() # s
hostname = raw_input('hostname: ')
username = raw_input('username: ')
password = getpass.getpass('password: ') #
s.login (hostname, username, password) # ssh
s.sendline ('uptime') # uptime
s.prompt() #
print s.before #
s.sendline ('ls -l')
s.prompt()
print s.before
s.sendline ('df')
s.prompt()
print s.before
s.logout()
except pxssh.ExceptionPxssh, e:
print "pxssh failed on login."
print str(e)
FTP自動操作自動インタラクティブ登録FTP操作を実現する。
import pexpect
import sys
child = pexpect.spawnu('ftp ftp.openbsd.org') # ftp
child.expect('(?i)name .*: ') #(?!)
child.sendline('anonymous') # ftp
child.expect('(?i)password') #
child.sendline('[email protected]')
child.expect('ftp> ')
child.sendline('bin') #
child.expect('ftp> ')
child.sendline('get robots.txt')
child.expect('ftp> ')
sys.stdout.write (child.before) # "ftp"
print("Escape character is '^]'.
")
sys.stdout.write (child.after)
sys.stdout.flush()
child.interact() # Escape character defaults to ^] # , , "^]"
child.sendline('bye')
child.close()
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。