GNU/Linux >> Linux の 問題 >  >> Linux

bash シェル スクリプトを別のコマンド ライン プログラムと対話させることは可能ですか?

コマンドが入力速度を気にせず、対話する必要がない場合 それを使用すると、ヒアドキュメントを使用できます。

例:

#!/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 コマンドを単純にダンプしているのではないことに注意してください。各応答コードをチェックして、問題がないことを確認します。この場合、事態はうまくいかず、スクリプトは保釈されます。


Linux
  1. コマンドライン引数をBashスクリプトに渡しますか?

  2. 関数とパラメータを変数として持つシェルスクリプト?

  3. BashスクリプトのRmコマンドは変数では機能しませんか?

  1. Bashシェルスクリプトで改行をエコーする方法

  2. 15 の便利な Bash シェル組み込みコマンド (例付き)

  3. bash の改行でテキストをエコーする

  1. Bashでプログラミングする方法:構文とツール

  2. どのシェルインタープリターがシバンなしでスクリプトを実行しますか?

  3. コマンドライン引数をシェルスクリプトに渡す方法は?