Bashスクリプト、パート11:対話型ユーティリティの期待と自動化

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には、コマンドラインユーティリティとやり取りできる一連のコマンドが用意されています。 主なコマンドは次のとおりです。





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での自動化が成功することを願っています! そして、もしあなたが期待した経験があるなら、あなたの話を待っています。



All Articles