終了するたびに自動的に再実行するコマンドがあるので、次のように実行しました。
while [ 1 ]; do COMMAND; done;
しかし、ループを止めることができない場合 Ctrl-c ループ全体ではなく、COMMAND
を強制終了するだけです。
どうすれば同様のことを達成できますが、ターミナルを閉じなくても停止できますか?
コマンドの終了ステータスを確認してください。コマンドがシグナルによって終了した場合、終了コードは128 +シグナル番号になります。 bashのGNUのオンラインドキュメント から:
シェルの目的のために、ゼロの終了ステータスで終了するコマンドは成功しました。ゼロ以外の終了ステータスは、失敗を示します。この一見わかりにくいスキームが使用されているため、成功を示す明確に定義された方法と、さまざまな失敗モードを示すさまざまな方法があります。コマンドが番号がNの致命的なシグナルで終了すると、Bashは値128 + Nを終了ステータスとして使用します。
POSIXも指定 シグナルによって終了したコマンドの値は128より大きいが、GNUのように正確な値を指定していないようです:
シグナルを受信したために終了したコマンドの終了ステータスは、128より大きいと報告されます。
たとえば、control-Cを使用してコマンドを中断した場合、SIGINTはUnixシステムのシグナル2であるため、終了コードは130になります。そう:
while [ 1 ]; do COMMAND; test $? -gt 128 && break; done
実行中にジョブを停止してバックグラウンドで実行できます ctrl+z。次に、あなたはあなたの仕事を殺すことができます:
$ kill %1
ここで、[1]はジョブ番号です。
スクリプトに無限ループを入れて、そこで信号を処理するのが最善の方法かもしれません。これが基本的な開始点です。きっとそれに合わせて修正したくなると思います。スクリプトはtrap
を使用してキャッチします ctrl-c (またはSIGTERM
)、コマンドを終了し(ここではsleep
をテストとして使用しました)、終了します。
cleanup ()
{
kill -s SIGTERM $!
exit 0
}
trap cleanup SIGINT SIGTERM
while [ 1 ]
do
sleep 60 &
wait $!
done
私は一般的に押し続けます Ctrl-C。遅かれ早かれ、COMMAND
の間に登録され、while
ループが終了します。多分もっと良い方法があります。
なぜ単純に、
while [ 1 ]; do COMMAND || break; done;
または、スクリプトで使用すると、
#!/bin/bash
while [ 1 ]; do
# ctrl+c terminates COMMAND and exits the while loop
# (assuming COMMAND responds to ctrl+c)
COMMAND || break
done;
-e
を指定してbashを実行すると、エラーが発生すると終了します。
#!/bin/bash -e
false # returns 1
echo This won't be printed
私は別の解決策を好みます:
touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done
ループを終了するには、次のようにします。
rm .runcmd && kill `pidof COMMAND`
while :
は無限ループを作成し、[ 1 ]
の記述を節約します
while :; do COMMAND; done &
これにより、PIDが印刷されます。 ctrl+d
を使用してプロンプトを終了すると、バックグラウンドジョブは終了せず、後でkill PID
を使用してどこからでもジョブを強制終了できます
PIDがわからなくなった場合は、pstree -pa $USER
またはpgrep -fl '.*PROCESS.*'
を使用してPIDを見つけることができます
私にとって合理的にうまくいくのは:
while sleep 1; do COMMAND; done
これは、sleep 1がしばらくの間固執し、ctrl + cを取得した場合にゼロ以外で戻り、ループが終了するため機能します。
trap
を使用-
exit_()
{
exit
}
while true
do
echo 'running..'
trap exit_ int
done