無限ループの終了

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

while [ 1 ]; do COMMAND; done; 

ただし、 Ctrl-c でループを停止できない場合は、COMMANDループ全体ではありません。

同様のことを実現するにはどうすればよいですか。ただし、ターミナルを閉じなくても停止できますか?

コメント

  • bashで' mの場合は、Ctrl-Zを使用してジョブを停止し、" kill%1 "それを殺す。
  • ちょっと待ってください… Linusは次のように言っていると言われています:「Linuxが素晴らしいことは誰もが知っています…無限ループを実行します5秒で。」-本当に…あと数秒待つだけで完了します。
  • @PaulCagerも私のために機能しました!Ctrl-Cが機能するのになぜ機能するのですか?そうではありませんか?
  • @cirosantilliそれは外側の仕事を殺します(bash " wrapper ")。たとえば、'すぐに"コマンド"を強制終了しない場合もあります。 、バックグラウンドにすると、'の親が死んでいても、生きたままこっそり通り過ぎてしまう可能性があります。しかし、ループは終了しており、'が重要な部分です。

回答

コマンドの終了ステータスを確認してください。コマンドがシグナルによって終了した場合、終了コードは128+シグナル番号になります。 bashのGNUオンラインドキュメントから

シェルの目的で、コマンドゼロ終了ステータスで終了するものは成功しました。ゼロ以外の終了ステータスは、失敗を示します。この一見直感に反するスキームが使用されているため、成功を示す明確に定義された方法が1つと、さまざまな失敗モードを示すさまざまな方法があります。番号がNの致命的なシグナルでコマンドが終了すると、Bashは値128 + Nを終了ステータスとして使用します。

POSIXは、シグナルで終了したコマンドの値が128より大きいことも指定していますが、GNUのように正確な値を指定していないようです。

シグナルを受信したために終了したコマンドの終了ステータスは、128より大きいものとして報告されます。

たとえば、control-Cを使用してコマンドを中断した場合、UNIXシステムではSIGINTがシグナル2であるため、終了コードは130になります。したがって:

while [ 1 ]; do COMMAND; test $? -gt 128 && break; done 

コメント

  • これは実際には保証されていないことに注意してください。多くのアプリケーションはこれを行いません。
  • @KyleJones:それについて言及しているPOSIX / GNUドキュメントにリンクできますか?
  • @cirosantilli完了。
  • @ KyleJonesありがとう!まだ実際にはCOMMAND = paplay alert.oggでは機能しません。おそらく、paplayが信号を処理するためですか?
  • @cirosantilliはい、その'が理由です。プロセスがシグナルを処理して終了した場合、その'は、未処理のシグナルによって終了されたプロセスとは異なります。

回答

ctrl + z を使用して、ジョブの実行中にジョブを停止してバックグラウンドに置くことができます。次の方法でジョブを強制終了できます:

$ kill %1 

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

コメント

  • 説明などについては、この回答も参照してください。
  • この比較的最近の回答は、単に機能するだけです。賛成+1
  • あなたは私を大いに助けてくれました。これが私がこの質問で検索したものです:)

回答

無限ループをスクリプトに入れて、そこでシグナルを処理するのが最善かもしれません。ここに「基本的な出発点」があります。それに合わせて変更したいと思うでしょう。スクリプトはtrapを使用して ctrl c (またはSIGTERM)をキャッチします。コマンドを強制終了し(ここではテストとしてsleepを使用しました)、終了します。

cleanup () { kill -s SIGTERM $! exit 0 } trap cleanup SIGINT SIGTERM while [ 1 ] do sleep 60 & wait $! done 

コメント

  • いいですね。'は、このヒントを使用して自動再起動ネットキャットラッパーを作成した方法です:trap "exit 0" SIGINT SIGTERM; while true; do netcat -l -p 3000; done
  • このtrapアプローチを、無限ループを強制終了する同じ(bash)スクリプトに追加する場合は、iv id = “637ecd8079を使用します。 $!の代わりに “>

こちらを参照)

回答

通常は Ctrl-C を押したままにします。遅かれ早かれ”を実行して、whileループを終了します。もっと良い方法があるかもしれません。

コメント

  • 理由はわかりませんが、1sファイルのpaplayなどの特定のコマンドでは失敗します。
  • それは私にとってはうまくいきました
  • それは'ここにあるすべてのソリューションの総当たり攻撃です。 :/

回答

-eでbashを実行する場合エラー状態が発生すると終了します:

#!/bin/bash -e false # returns 1 echo This won"t be printed 

コメント

  • ここの最初の行ははるかに'あまり時間をかけたくない些細なスクリプトの最も簡単な解決策!

回答

単純ではない

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; 

コメント

  • 非常にエレガントなソリューション。しかし、'これは、COMMANDが常に成功の終了ステータスを返す場合にのみ機能しませんか?
  • はい@howardh、その'正解です。

回答

  1. PIDを使用してプロセスをいつでも強制終了できます。 ” ■端末を閉じる必要はありません
  2. デーモンのように無限ループで何かを実行したい場合は、バックグラウンドに置くのが最善です
  3. while :は無限ループを作成し、[ 1 ]

    while :; do COMMAND; done & 

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

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

回答

別の解決策が好きです:

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

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

rm .runcmd && kill `pidof COMMAND` 

回答

合理的に機能するもの

 while sleep 1; do COMMAND; done  

これは、スリープ1が一方、ctrl + cを取得すると、ゼロ以外で戻り、ループが終了します。

コメント

  • +1の場合、スリープ時間も0.5または0.1に縮小:while sleep 0.1; do COMMAND; done

回答

trapを使用-

 exit_() { exit } while true do echo "running.." trap exit_ int done  

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です