sttyを使用してttyを正しく復元してください。

sttyを使用してttyを正しく復元してください。

私はいくつかのユーザー入力(パスワード要求など)を読み取るために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が正しく復元されるようです。

ベストアンサー1

おすすめ記事