私はいくつかのユーザー入力(パスワード要求など)を読み取るためにbashスクリプトを作成しており、結果をキャプチャして標準出力を介して渡したいと思います。 (私は最新のソフトウェアを使ってGNU / Linux環境で作業しています。)
以下は、問題を再現する簡単なバージョンのスクリプトです。
....
# read_input.sh
#
# Issue B : redirection of "3>&1" here causes stty error when
# this script is executed via a command subsitution context subshell
exec 3>&1 </dev/tty >/dev/tty
tty_settings=`stty -g`
# Issue A : uncommented version doesn't restore tty properly.
#trap 'stty "$tty_settings";' EXIT
#trap 'echo "...interrupting"; exit 1' INT ABRT HUP QUIT TERM
trap 'echo "...interrupting"; stty "$tty_settings"; exit 1' INT ABRT HUP QUIT TERM
stty -echo
echo "Enter input: "
input=""
while IFS= read -r -n1 char; do
# nb: stripped out proper char handling code here,
# (except return), for simplicity
if [[ $char = "" ]]; then
break
fi
input+=$char
echo -n "*"
done
echo ""
stty "$tty_settings"
#trap - EXIT INT ABRT HUP QUIT TERM
trap - INT ABRT HUP QUIT TERM
echo "$input" >&3
目的は、結果入力をfd 3(呼び出し時にこのスクリプトのstdoutがパイプに接続されている場合)に記録し、対話中にttyを維持することです。次に、sttyを使用してttyを変更してエコーなどを制御し、トラップ処理によってすべての修正を元に戻します。
二つの問題に直面した。
質問A
制御端子に戻った後はエコーが抑制されます。注釈付けされていないアクティブな1行ハンドラケースの代わりに2行トラップハンドラケース(注釈付き)を使用する必要があります。
1行の場合 - INTと言うとttyを復元し、ハンドラを介して終了を呼び出します。 EXIT自体をキャプチャするものではありません。なぜこれを行うべきですか?
質問B
これは、サブシェルのコンテキストでexecの "3>&1"リダイレクトに関連しています。
何らかの理由で、サブシェルでこのスクリプト( "read_input.sh")を実行し、コマンドの置き換えで別のスクリプトから出力を取得したいとします。
....
# read_input_caller.sh
input=$(sh read_input.sh)
echo "$input"
呼び出しスクリプトを中断したときに、トラップハンドラーのstty呼び出しが次の(^ Cで示される)文句を言うことがわかりました。
stty:「標準入力」:入力/出力エラー
このエラーメッセージは、exec行の「3>&1」リダイレクトが原因で発生します。 "3>&1"なしでexec行を呼び出すとsttyエラーはありません(ただし、入力をstdoutに渡すのにはあまり役に立ちません)。なぜこれが起こるのかわかりませんか?
呼び出しスクリプトでは、他のサブシェルは次のように呼び出します。
....
sh read_input.sh | cat
このエラーは生成されません。
興味深いことに、問題Bが発生すると、問題Aの問題のキャプチャ/修復にもかかわらず、端末を制御するttyが正しく復元されるようです。