シームレスなシャットダウンのためにctrl + Cを検出するには、カスタムコマンドラインソフトウェア(loopHelloWorldなど)を使用することをお勧めします。答えを失うことなくどのようにパイプすることができますかCtrl+C
?
$ loopHelloWorld
- Ctrl+C to nicely shutdown
ただし、パイプを使用すると、パイプが正しく閉じられずにソフトウェアがシャットダウンします。
$ loopHelloWorld |
while IFS= read -r line; do
echo "$line"
done
はい
ping example.com |
while IFS= read -r line; do
echo "$line"
done
答え1
Ctrl+Cこれはパイプ内のすべてのプロセスにSIGINTが送信されます(すべて対話型シェルのフォアグラウンドタスクに対応する同じプロセスグループで実行されるため)。
だから:
loopHelloWorld |
while IFS= read -r line; do
echo "$line"
done
実行中のプロセスloopHelloWorld
とループのサブシェルを実行するプロセスの両方がwhile
得られますSIGINT
。
メッセージが標準出力loopHelloWorld
に書き込まれると、Ctrl+C to nicely shutdown
パイプにも書き込まれます。もしそうなら後ろにもう一方の端にあるサブシェルが死んloopHelloWorld
だ場合返品SIGPIPEが受信され、それを処理する必要があります。
ここではコマンドの一般的な出力ではないため、stderrにメッセージを作成する必要があります(ただし、このping
例では該当しません)。そうすればパイプを通過できなくなります。
あるいは、whileループを実行しているサブシェルにSIGINTを無視して、loopHelloWorld
SIGINT以降の出力を読み続けるようにすることもできます。
loopHelloWorld | (
trap '' INT
while IFS= read -r line; do
printf '%s\n' "$line"
done
)
ただし、これを押すとパイプの終了状態がゼロになりますCtrl+C。
この特定の例の別のオプションは、代わりにzsh
またはを使用することです。これらのシェルでは、ループはデフォルトのシェルプロセスで実行されるため、SIGINTの影響を受けません。ksh93
bash
while
loopHelloWorld | cat
これは、フォアグラウンドプロセスグループで実行されてもcat
役に立ちません。loopHelloWorld
答え2
トラップを使用してください:
#! /bin/bash
trap handleInt SIGINT
interrupted=0
function handleInt {
echo "Interrupted..."
interrupted=1
}
while true
do
[[ interrupted -ne 0 ]] && { echo "Ctrl-C caught, exiting..." ; exit ; }
echo "Sleeping..."
sleep 1
read -r line
echo "$line"
done