1. 概要

bashスクリプトを作成するときは、プロセスを自動化するため、またはスクリプトを無人で実行するために、呼び出すプログラムの1つからの対話型プロンプトに応答したい場合があります。

このチュートリアルでは、さまざまな方法を使用して、bashスクリプトでインタラクティブなプロンプトに応答する方法を説明します。

一般的なコマンドラインアプリケーションのように、はい/いいえの質問に答える簡単なスクリプトから始めます。 次に、カスタムロジックに基づいてプロンプトに応答できるよりスマートなスクリプトに移ります。

2. yesを使用してYes/Noプロンプトに回答する

yes は、多くのLinuxディストリビューションに組み込まれているシンプルなコマンドラインアプリケーションです。 プロンプトが表示された場合にyesを使用して同じ回答を何度も出力できるため、プログラムがyes / noの質問をしたときに、入力を待ってスクリプトが中断されることはありません。[X190Xを使用するには]はい、その出力を、使用するプログラムの標準入力にパイプする必要があります。

2.1. はい/いいえの質問をするサンプルコマンド

はい/いいえの回答を求めるコマンドの例を見てみましょう。 実行した場合:

touch test.txt
rm -i *.txt

はい/いいえのプロンプトが表示されます。

/bin/rm: remove regular empty file 'test.txt'?

これを手動で行う場合は、次のように入力するだけです。 y このプロンプトを渡します。 ただし、自動化されたスクリプトを作成している場合は、このプロンプトでスクリプトの実行が途中で停止することは望ましくありません。

通常、この状況では、rmコマンドの-fフラグを使用してプロンプトを無効にすることをお勧めします。 ただし、この記事では、 rm コマンドを使用して、 yes を使用して、すべてのプロンプトにyesまたはnoと応答することにより、yes/noプロンプトに応答する方法を説明します。

2.2. はいを使用する

ターミナルでyesコマンドを実行してみましょう。

<em>y
y
y
...</em>

出力yを繰り返し生成するだけです。

したがって、スクリプトを自動化するために、 yes プログラムの標準出力ストリームを、次のプロンプトに応答するコマンドの標準入力ストリームにパイプすることができます。

touch test.txt
yes | rm -i *.txt

したがって、コマンドによってプロンプトが生成され、実行中にブロックされない場合、スクリプトはyと応答します。

2.3. 引数でyesを使用する

yesコマンドの出力を決定することもできます。 たとえば、すべてのプロンプトにnと応答するようにパラメーターを渡すことができます。

yes n | rm -i *.txt

3. printfを使用して複数の質問に回答する

たとえば、ソフトウェアのインストールや暗号化キーの生成を自動化するために、複数のプロンプトに応答するスクリプトを作成する必要がある場合があります。

スクリプトに複数の入力が必要な場合は、 printf を使用して、指定された順序でそれらに応答できます。

3.1. 複数の入力を必要とするサンプルスクリプト

ユーザーに3つの簡単な質問をするbashスクリプトを考えてみましょう。

#!/usr/bin/env bash

echo "Hello, please introduce yourself."

echo -n "Your name: "
read -r name

echo "Are you human?"

echo -n "y/n: "
read -r human

echo "What is your favorite programming language?"

echo -n "Your answer: "
read -r lang

echo
echo "Answers:"
echo "1. $name"
echo "2. $human"
echo "3. $lang"

スクリプトをquestions.shという名前のファイルに保存して、実行してみましょう。

$ chmod +x questions.sh
$ ./questions.sh
Hello, please introduce yourself.
Your name: Ziggy
Are you human?
y/n: y
What is your favorite programming language?
Your answer: Java

Answers:
1. Ziggy
2. y
3. Java

上記の出力からわかるように、スクリプトは3つの質問をし、後で回答を出力します。 それでは、スクリプト内のすべてのプロンプトに自動的に答えてみましょう。

3.2. printfをスクリプトにパイプする

printf コマンドを使用して、改行文字を間に挟んで正しい順序で回答を出力し、スクリプトにパイプする必要があります。

printf "bot\nn\nJava" | ./questions.sh

このコマンドを実行すると、質問への応答がそれぞれ「bot」、「n」、および「Java」であることがわかります。 各回答の間に改行文字を入れて、3つの異なるプロンプトに個別に入力することに注意してください。

4. expectを使用する

場合によっては、より複雑な方法でプログラムを操作する必要があります。 その場合、expectは、プログラムと対話するカスタムロジックをスクリプト化するために使用できるコマンドラインアプリケーションです。 e xpect は、bashなどのスクリプトインタープリターとして機能し、独自の構文を持っています。

4.1. 簡単なexpectスクリプトの作成

プロンプトを待って応答するには、expectedスクリプトを使用できます。

#!/usr/bin/expect -f

set timeout -1
spawn ../4/questions.sh

expect "Your name: "
send -- "expect\n"

expect "Are you human?\r
y/n: "
send -- "n\r"

expect "What is your favorite programming language?\r
Your answer: "
send -- "Java\r"

expect eof

expected がシステムにインストールされていない場合、それを機能させるには、パッケージマネージャーを介してインストールする必要がある場合があります。 たとえば、DebianまたはUbuntuシステムでは、次を使用します。

apt install expect

このスクリプトをexpect-script.expという名前のファイルに保存して、実行してみましょう。

chmod +x expect-script.exp
./expect-script.exp

入力「expect」、「n」、「Java」がこの順序で登録されていることがわかります。

この例でexpectスクリプトが何をするか見てみましょう。

  1. 最初の行で定義されているシバン(#!)のため、シェルはパス / usr / bin /expectedにあるインタープリターを使用してスクリプトを実行しようとします。
  2. expected がインストールされ、この場所で見つかった場合、スクリプトの処理が開始されます。
  3. bashなどのスクリプトインタープリターのように、スクリプトファイルに表示される順序で命令を実行します。 この場合、指示は特定のテキストを待ち、これらの特定のテキストを受信した後、expectedsendコマンドを使用してプロンプトに応答することです。

4.2. autoexpectを使用する

autoexpect は、expectスクリプトを自動的に生成する優れた方法です。これは、元のアプリケーションの実行を通じて回答を記録し、記録をexpectに変換することによって行われます。脚本。 プログラムのプロンプトに応答するexpectスクリプトを生成するには、次を使用できます。

autoexpect questions.sh

これにより、 questions.sh が実行され、アクションの記録が開始されます。 プロンプトへの回答を手動で入力した後、プログラムの実行が終了すると、script.expというスクリプトが生成されます。

生成されたスクリプトを確認してみましょう。

#!/usr/bin/expect -f
#
# This Expect script was generated by autoexpect on Wed Aug 26 05:47:00 2020
# ...

set force_conservative 0  ;# set to 1 to force conservative mode even if
			  ;# script wasn't run conservatively originally
if {$force_conservative} {
    set send_slow {1 .1}
    proc send {ignore arg} {
	sleep .1
	exp_send -s -- $arg
    }
}
set timeout -1
spawn ../4/questions.sh
match_max 100000
expect -exact "Hello, please introduce yourself.\r
Your name: "
send -- "Ziggy\r"
expect -exact "Ziggy\r
Are you human?\r
y/n: "
send -- "y\r"
expect -exact "y\r
What is your favorite programming language?\r
Your answer: "
send -- "Java\r"
expect eof

ご覧のとおり、autoexpectexpectコマンドを生成し、プロンプトに応答する前に待機する出力を検出しようとします。

5. 結論

このチュートリアルでは、 printf yes expected などのさまざまなメソッドとツールを使用して、bashスクリプトでインタラクティブなプロンプトに応答する方法を説明しました。 また、 autoexpect を使用して、プロンプトに手動で応答したときに記録されるアクションに基づいてexpectスクリプトを生成する方法も確認しました。