web-dev-qa-db-ja.com

無限ループを終了する

終了するたびに自動的に再実行するコマンドがあるので、次のように実行しました。

while [ 1 ]; do COMMAND; done;

しかし、ループを止めることができない場合 Ctrl-c ループ全体ではなく、COMMANDを強制終了するだけです。

どうすれば同様のことを達成できますが、ターミナルを閉じなくても停止できますか?

57
howardh

コマンドの終了ステータスを確認してください。コマンドがシグナルによって終了した場合、終了コードは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
40
Kyle Jones

実行中にジョブを停止してバックグラウンドで実行できます ctrl+z。次に、あなたはあなたの仕事を殺すことができます:

$ kill %1

ここで、[1]はジョブ番号です。

51
Jem

スクリプトに無限ループを入れて、そこで信号を処理するのが最善の方法かもしれません。これが基本的な開始点です。きっとそれに合わせて修正したくなると思います。スクリプトはtrapを使用してキャッチします ctrl-c (またはSIGTERM)、コマンドを終了し(ここではsleepをテストとして使用しました)、終了します。

cleanup ()
{
kill -s SIGTERM $!
exit 0
}

trap cleanup SIGINT SIGTERM

while [ 1 ]
do
    sleep 60 &
    wait $!
done
21
ephsmith

私は一般的に押し続けます Ctrl-C。遅かれ早かれ、COMMANDの間に登録され、whileループが終了します。多分もっと良い方法があります。

15
jw013

なぜ単純に、

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;
10
Dale Anderson

-eを指定してbashを実行すると、エラーが発生すると終了します。

#!/bin/bash -e
false # returns 1
echo This won't be printed
9
Brendan Long

私は別の解決策を好みます:

touch .runcmd; while [ -f ".runcmd" ]; do COMMAND; sleep 1; done

ループを終了するには、次のようにします。

rm .runcmd && kill `pidof COMMAND`
3
M4tze
  1. PIDを使用していつでもプロセスを強制終了できます。ターミナルを閉じる必要はありません。
  2. デーモンのような無限ループで何かを実行したい場合は、バックグラウンドで実行するのが最適です。
  3. while :は無限ループを作成し、[ 1 ]の記述を節約します

    while :; do COMMAND; done &
    

これにより、PIDが印刷されます。 ctrl+dを使用してプロンプトを終了すると、バックグラウンドジョブは終了せず、後でkill PIDを使用してどこからでもジョブを強制終了できます

PIDがわからなくなった場合は、pstree -pa $USERまたはpgrep -fl '.*PROCESS.*'を使用してPIDを見つけることができます

2
errant.info

私にとって合理的にうまくいくのは:

while sleep 1; do COMMAND; done

これは、sleep 1がしばらくの間固執し、ctrl + cを取得した場合にゼロ以外で戻り、ループが終了するため機能します。

1
Iwan Aucamp

trapを使用-

exit_()
{
    exit
}

while true
do
    echo 'running..'
    trap exit_ int
done
0
markroxor