Bashスクリプト:開始
Bashスクリプト、パート2:ループ
Bashスクリプト、パート3:オプションとコマンドラインスイッチ
Bashスクリプト、パート4:入力と出力
Bashスクリプト、パート5:シグナル、バックグラウンドタスク、スクリプト管理
Bashスクリプト、パート6:関数とライブラリーの開発
Bashスクリプト、パート7:sedとワープロ
Bashスクリプト、パート8:awkデータ処理言語
Bashスクリプトパート9:正規表現
Bashスクリプト、パート10:ケーススタディ
Bashスクリプト、パート11:対話型ユーティリティの期待と自動化
前回、bashスクリプト開発の方法論について話しました。 前の10の資料で分析したすべてを要約すると、bashについて何も知らずにそれらを読み始めた場合、今では非常に多くの有用なことができます。
この一連の資料の最終版である今日のトピックは、実行中にユーザーと対話するスクリプトなどの対話型ユーティリティを使用した作業の自動化に専念します。 TclベースのツールであるExpectは、この問題に役立ちます。
Expectを使用すると、他のプログラムからの質問を期待して回答を与えるプログラムを作成できます。 Expectは、コマンドラインスクリプトと対話するときにユーザーを置き換えることができるロボットと比較できます。
基本を期待する
システムにexpectがインストールされていない場合は、たとえばUbuntuで次のように修正できます。
$ apt-get install expect
CentOsのようなものでは、次のコマンドでインストールが行われます。
$ yum install expect
Expectには、コマンドラインユーティリティとやり取りできる一連のコマンドが用意されています。 主なコマンドは次のとおりです。
-
spawn —
プロセスまたはプログラムを開始します。 たとえば、コマンドシェル、 FTP 、Telnet、ssh、scpなどです。
-
expect —
プログラムによるデータ出力を待機しています。 スクリプトを作成するとき、どの種類の出力が待機しているか、どのように応答する必要があるかを指定できます。
-
send —
応答を送信します。 このコマンドを使用するExpectスクリプトは、自動化されたプログラムに入力を送信できます。 通常のbashスクリプトでおなじみのecho
コマンドのように見えます。
-
interact —
「手動」プログラム制御モードに切り替えることができます。
Bashスクリプトの自動化
ユーザーと対話し、expectを使用して自動化するスクリプトを作成します。
questions
bashスクリプトコードは次のとおりです。
#!/bin/bash echo "Hello, who are you?" read $REPLY echo "Can I ask you some questions?" read $REPLY echo "What is your favorite topic?" read $REPLY
ここで、
questions
スクリプトを実行し、その質問に答えるexpect-scriptを作成します。
#!/usr/bin/expect -f set timeout -1 spawn ./questions expect "Hello, who are you?\r" send -- "Im Adam\r" expect "Can I ask you some questions?\r" send -- "Sure\r" expect "What is your favorite topic?\r" send -- "Technology\r" expect eof
answerbot
という名前を付けてスクリプトを保存します。
スクリプトの最初に識別行があります。この場合、expectはスクリプトを解釈するため、expectへのパスが含まれています。
2行目では、expect
timeout
変数を-1に設定して、タイムアウトをオフにします。 残りのコードは、bashスクリプトでの作業の自動化です。
まず、
spawn
コマンドを使用して、bashスクリプトを実行します。 当然、他のコマンドラインユーティリティをここで呼び出すことができます。 以下は、bashスクリプトからの一連の質問と、それらに期待される回答です。 サブプロセスから質問を受け取ったexpectは、与えられた答えを与え、次の質問を期待します。
最後のコマンドでは、ファイルの終わりの兆候が予想され、スクリプトはこのコマンドに到達して終了します。
それでは、すべてを試してみましょう。
answerbot
実行可能ファイルにします。
$ chmod +x ./answerbot
そしてそれを呼び出す:
$./answerbot
スクリプトがbashスクリプトの質問に答えることを期待する
ご覧のとおり、expect-scriptはbash-scriptの質問に正しく回答しました。 この段階で、expectedの誤った場所が原因でエラーが発生した場合、次のようにアドレスを確認できます。
$ which expect
answerbot
スクリプトを実行した後
answerbot
すべてが完全自動モードで行われることに注意してください。 同じことは、どのコマンドラインユーティリティでも実行できます。 bashスクリプトは非常に単純であり、表示するデータを正確に把握しているため、それとやり取りするためにexpectスクリプトを記述することは難しくありません。 他の開発者が作成したプログラムを使用する場合、タスクは複雑です。 ただし、expectスクリプトの自動作成用のツールがここにあります。
Autoexpect-Expectスクリプトの自動作成
Autoexpectを使用すると、自動化する必要があるプログラムを実行できます。その後、プログラムが出力する内容と質問に答えるときにユーザーが入力する内容を記録します。 autoexpectを呼び出し、このユーティリティにスクリプトの名前を渡します。
$ autoexpect ./questions
このモードでは、bashスクリプトとのやり取りは通常のものと変わりません。私たち自身が彼の質問に対する答えを入力します。
autoexpectを使用してbashスクリプトを実行する
bashスクリプトでの作業が完了すると、autoexpectは収集されたデータが
script.exp
ファイルに書き込まれたことを報告します。 このファイルを見てください。
Script.expファイル
一般に、いくつかの詳細を除き、独自に作成したのと同じスクリプトがあります。 このスクリプトを実行すると、結果は同じになります。
自動的に作成された期待スクリプトを実行する
FTPクライアントなどの一部のプログラムとの対話セッションを記録する場合、出力データまたは特定の長いアクションを実行するプロセスを反映する出力データで操作の時間に関する情報を使用するという事実に遭遇する場合があります。 一般に、各起動時のプログラムの出力は、人によって正しく認識され、同じ答えの入力を引き起こすという事実について、同じ条件下で、期待して新しいように見えるという事実について話している。
expect-scriptで、そのようなプログラムから期待される行が修正されると、そのようなスクリプトは正常に動作できなくなります。 これに対処するには、プログラムを起動するたびに新しく見えるexpect-scriptデータから削除するか、テンプレートを使用します。テンプレートを使用すると、expectはプログラムが何を望んでいるかを正しく理解できます。
ご覧のとおり、autoexpectは非常に便利なツールですが、欠点がないわけではなく、手動でのみ修正できます。 したがって、expect-scriptsの言語を習得し続けます。
変数とコマンドラインパラメーターを操作する
expectスクリプトで変数を宣言するには、
set
コマンドを使用します。 たとえば、変数
VAR1
値5を割り当てるには、次の構成が使用されます。
set VAR1 5
変数の値にアクセスするには、名前の前にドル記号-
$
追加します。 この例では、
$VAR1
ようになります。
expectスクリプトが呼び出されるコマンドライン引数にアクセスするには、次のようにします。
set VAR [lindex $argv 0]
ここでは、
VAR
変数を宣言し、コマンドラインの最初の引数
$argv 0
へのポインターを書き込み
$argv 0
。
更新されたexpectスクリプトの目的のために、プログラムで使用されるユーザー名である最初の引数の値を変数
my_name
に書き込みます。 ユーザーが好きなものを象徴する2番目の引数は、
my_favorite
変数に
my_favorite
ます。 その結果、変数宣言は次のようになります。
set my_name [lindex $argv 0] set my_favorite [lindex $argv 1]
answerbot
スクリプトを
answerbot
ようにします。
#!/usr/bin/expect -f set my_name [lindex $argv 0] set my_favorite [lindex $argv 1] set timeout -1 spawn ./questions expect "Hello, who are you?\r" send -- "Im $my_name\r" expect "Can I ask you some questions?\r" send -- "Sure\r" expect "What is your favorite topic?\r" send -- "$my_favorite\r" expect eof
それを実行し、最初のパラメーターとして
SomeName
を渡し、2番目のパラメーターとして
Programming
を渡します。
$ ./answerbot SomeName Programming
変数とコマンドラインオプションを使用したスクリプトを期待する
ご覧のとおり、すべてが期待どおりに機能します。 ここで、expect-scriptは、渡されたコマンドラインパラメーターを使用してbash-scriptの質問に答えます。
同じ場所に表示される可能性のあるさまざまな質問への回答
自動プログラムが1つの状況で1つの行を生成し、同じ場所で別の行を生成できる場合、中括弧で囲まれ、プログラムから受信したさまざまなデータのスクリプト応答オプションを含むブロックを使用できることを期待してください。 次のようになります。
expect { "something" { send -- "send this\r" } "*another" { send -- "send another\r" } }
ここで、expectスクリプトが「何か」という行を見ると、「これを送信」という応答を送信します。 「別の」で終わる特定の行の場合、「別の送信」という回答を送信します。
新しいスクリプトを作成して、
questions
ファイルに書き込み、同じ場所で異なる質問をランダムに尋ねましょう。
#!/bin/bash let number=$RANDOM if [ $number -gt 25000 ] then echo "What is your favorite topic?" else echo "What is your favorite movie?" fi read $REPLY
ここでは、スクリプトが実行されるたびに乱数を生成し、それを分析した後、2つの質問のうちの1つを推測します。
このようなスクリプトを自動化するには、上記の設計が役立ちます。
#!/usr/bin/expect -f set timeout -1 spawn ./questions expect { "*topic?" { send -- "Programming\r" } "*movie?" { send -- "Star wars\r" } }
同じ場所に表示されるさまざまな質問への回答
ご覧のとおり、自動スクリプトが「topic?」で終わる行を表示すると、expect-scriptは「Programming」という行を渡します。 同じ場所で、プログラムの別の立ち上げで、「映画?」で終わる質問を受け取った後、予想スクリプトは答えます:「スターウォーズ」。 これは非常に便利なテクニックです。
条件文
Expectは、
if-else
条件ステートメントおよびその他の制御構造をサポートしています。 条件文を使用した例を次に示します。
#!/usr/bin/expect -f set TOTAL 1 if { $TOTAL < 5 } { puts "\nTOTAL is less than 5\n" } elseif { $TOTAL > 5 } { puts "\nTOTAL greater than 5\n" } else { puts "\nTOTAL is equal to 5\n" } expect eof
条件演算子が期待されています
ここで、
TOTAL
変数に特定の番号を割り当て、それをチェックして、チェックの結果に依存するテキストを表示します。
中括弧の構成に注意してください。 次の開始ブラケットは、前の構造と同じ行に配置する必要があります。
whileループ
期待される
while
ループは、通常のbashスクリプトで使用されるループと非常に似ていますが、ここでも中括弧が使用されます。
#!/usr/bin/expect -f set COUNT 0 while { $COUNT <= 5 } { puts "\nCOUNT is currently at $COUNT" set COUNT [ expr $COUNT + 1 ] } puts ""
whileループが期待される
forループ
expectの
for
ループは非常に特別です。 サイクルの開始時に、中括弧の独立したペアで、カウンター変数、サイクルを終了する条件、およびカウンターを変更するためのルールを指定する必要があります。 次に、再び中括弧で囲んで、ループの本体に移動します。
#!/usr/bin/expect -f for {set COUNT 0} {$COUNT <= 5} {incr COUNT} { puts "\nCOUNT is at $COUNT" } puts ""
Forループが期待される
関数の宣言と使用
Expectを使用すると、プログラマは
proc
キーワードを使用して関数を宣言できます。
proc myfunc { MY_COUNT } { set MY_COUNT [expr $MY_COUNT + 1] return "$MY_COUNT" }
以下は、スクリプト内で宣言された関数が使用される期待スクリプトの例です。
#!/usr/bin/expect -f proc myfunc { MY_COUNT } { set MY_COUNT [expr $MY_COUNT + 1] return "$MY_COUNT" } set COUNT 0 while {$COUNT <= 5} { puts "\nCOUNT is currently at $COUNT" set COUNT [myfunc $COUNT] } puts ""
期待される機能
チームインタラクション
expectで自動化されたプログラムでは、パスワードなどの機密データの入力が必要になることがありますが、これはスクリプトコードにプレーンテキストで保存することは望ましくありません。 このような状況では、プログラムとのやり取りの一部を自動化して、たとえばパスワードを自分で入力し、再び期待どおりに制御を移すことができる
interact
コマンドを使用できます。
このコマンドが実行されると、expect-scriptは、以前に書き込まれたデータを渡すのではなく、キーボードからプログラムの質問に対する回答を読み取るように切り替わります。
一般に、以前に検討したものとまったく同じbashスクリプトを次に示しますが、現在は質問の1つに対するパスワードの入力を待機しています。
#!/bin/bash echo "Hello, who are you?" read $REPLY echo "What is you password?" read $REPLY echo "What is your favorite topic?" read $REPLY
期待値スクリプトを作成します。これは、パスワードを提供するように提案された場合、制御を当社に転送します。
#!/usr/bin/expect -f set timeout -1 spawn ./questions expect "Hello, who are you?\r" send -- "Hi Im Adam\r" expect "*password?\r" interact ++ return send "\r" expect "*topic?\r" send -- "Technology\r" expect eof
expectスクリプトの対話コマンド
interact
コマンドに遭遇する
interact
、expect-scriptが停止し、パスワードを入力する機会が与えられます。 パスワードを入力した後、「++」を入力する必要があり、expect-scriptは引き続き機能し、再び制御を受け取ります。
まとめ
Expect機能は、適切なライブラリのおかげで、さまざまなプログラミング言語で作成されたプログラムで使用できます。 これらの言語には、C#、Java、Perl、Python、Rubyなどがあります。 さまざまな開発環境でexpectを使用できるという事実は、偶然とはほど遠いものです。 問題は、これが多くの問題を解決するために使用される本当に重要で便利なツールであることです。 ここでは、ソフトウェアの品質を確認したり、さまざまなネットワーク管理タスクを実行したり、ファイル転送を自動化したり、更新を自動的にインストールしたりできます。
この資料をマスターした後、expectの基本概念を理解し、autoexpectツールを使用してスクリプトを自動生成することを学びました。 これで、追加のソースを使用して、期待どおりの学習を続けることができます。 トレーニングおよび参考資料のコレクションを以下に示します。 ここに注目すべき3つの記事のシリーズ( 1、2、3 )があります。 そして、ここに公式の expect ページがあり、プログラムのソースコードへのリンクと出版物のリストを見つけることができます。
これで、一連のbashスクリプトが終了しました。 コマンドラインスクリプトの書き方を学びたいと思っている人たちが、11の部分とそれらへの無数のコメントが、目標を達成するのに役立つことを願っています。
親愛なる読者! 私たちと一緒にいたすべての人に感謝します。 Linuxでの自動化が成功することを願っています! そして、もしあなたが期待した経験があるなら、あなたの話を待っています。