コマンドが入力速度を気にせず、対話する必要がない場合 それを使用すると、ヒアドキュメントを使用できます。
例:
#!/bin/bash
prog <<EOD
cmdx
save filex
cmdy
save filey
q
EOD
プログラムの出力に基づいて分岐する必要がある場合、またはプログラムがコマンドのタイミングにまったく敏感な場合は、Expect が必要です。
Expect を使用することをお勧めします。このツールは、インタラクティブなシェル アプリケーションを自動化するように設計されています。
必要なところに道はある!プロセス管理と IPC がどのように機能するかを理解するための良い bash レッスンだと思います。もちろん、最善の解決策は Expect です。しかし、本当の理由は、パイプが扱いにくく、多くのコマンドがデータを待機するように設計されているためです。つまり、予測が困難な理由でプロセスがゾンビ化する可能性があります。しかし、その方法と理由を学ぶことで、ボンネットの下で何が起こっているかを思い出すことができます。
2 つのプロセスが対話を行っている場合、一方または両方が決して到着しないデータを読み込もうとする危険性があります。エンゲージメントのルールは非常に明確でなければなりません。 CRLF や文字エンコーディングのようなものは、パーティーを台無しにする可能性があります。幸いなことに、bash スクリプトとその子プロセスのような 2 つの密接なパートナーは、比較的簡単に一致させることができます。見逃しやすいのは、bash が実行するほぼすべての処理に対して子プロセスを起動することです。それを bash で動作させることができれば、自分が何をしているかを完全に理解していることになります。
ポイントは、別のプロセスと対話したいということです。ここにサーバーがあります:
# a really bad SMTP server
# a hint at courtesy to the client
shopt -s nocasematch
echo "220 $HOSTNAME SMTP [$$]"
while true
do
read
[[ "$REPLY" =~ ^helo\ [^\ ] ]] && break
[[ "$REPLY" =~ ^quit ]] && echo "Later" && exit
echo 503 5.5.1 Nice guys say hello.
done
NAME=`echo "$REPLY" | sed -r -e 's/^helo //i'`
echo 250 Hello there, $NAME
while read
do
[[ "$REPLY" =~ ^mail\ from: ]] && { echo 250 2.1.0 Good guess...; continue; }
[[ "$REPLY" =~ ^rcpt\ to: ]] && { echo 250 2.1.0 Keep trying...; continue; }
[[ "$REPLY" =~ ^quit ]] && { echo Later, $NAME; exit; }
echo 502 5.5.2 Please just QUIT
done
echo Pipe closed, exiting
さて、うまくいけば魔法のようなスクリプトです。
# Talk to a subprocess using named pipes
rm -fr A B # don't use old pipes
mkfifo A B
# server will listen to A and send to B
./smtp.sh < A > B &
# If we write to A, the pipe will be closed.
# That doesn't happen when writing to a file handle.
exec 3>A
read < B
echo "$REPLY"
# send an email, so long as response codes look good
while read L
do
echo "> $L"
echo $L > A
read < B
echo $REPLY
[[ "$REPLY" =~ ^2 ]] || break
done <<EOF
HELO me
MAIL FROM: me
RCPT TO: you
DATA
Subject: Nothing
Message
.
EOF
# This is tricky, and the reason sane people use Expect. If we
# send QUIT and then wait on B (ie. cat B) we may have trouble.
# If the server exits, the "Later" response in the pipe might
# disappear, leaving the cat command (and us) waiting for data.
# So, let cat have our STDOUT and move on.
cat B &
# Now, we should wait for the cat process to get going before we
# send the QUIT command. If we don't, the server will exit, the
# pipe will empty and cat will miss its chance to show the
# server's final words.
echo -n > B # also, 'sleep 1' will probably work.
echo "> quit"
echo "quit" > A
# close the file handle
exec 3>&-
rm A B
サーバー上の SMTP コマンドを単純にダンプしているのではないことに注意してください。各応答コードをチェックして、問題がないことを確認します。この場合、事態はうまくいかず、スクリプトは保釈されます。