一時停止後、whileループが停止するのはなぜですか?


10

bashを使用してwhileループを一時停止すると、ループが再開後に停止するのはなぜですか?以下の短い例。

$ while true; do echo .; sleep 1; done
.
.
^Z
[1]+  Stopped                 sleep 1
$ fg
sleep 1
$

私はシグナルに精通しており、これはここではbashの自然な動作であると推測していますが、この特定の方法で動作する理由をよりよく理解したいと思います。


なぜなら、それは割り込みを処理する$?必要trueがあり、戻り時にそれを正確に反映する必要があるためであり、そうではありませんtrue。多分。おもう。
mikeserv 2015年

1
このコメントにフラグが付けられないことを願っていますが、別の質問、Unix koan-styleを使用して質問に回答します。答えは、彼はもはや遊び場にいないので、戦いを始めることができるからです。したがって、問題の動作は単に停止されました。
rubynorails 2015年

コマンドを停止すると、ループが壊れます。次に、ループではなく、単一のスリープ1コマンドを再開します。
123

回答:


10

これはいくつかのシェルのバグのように見え、ksh93およびzshで期待どおりに動作します。

バックグラウンド:

ほとんどのシェルは、メインシェル内でwhileループを実行し、

ログインシェル以外で^ Zを入力すると、Bourne Shellシェル全体を一時停止します

bashが中断するのsleepは、whileループのみを終了して、新しいシェルプロンプトを出力する場合

ダッシュはこのコマンドを中断できないようにします

ksh93、物事は非常に異なる動作します。

ksh93も同じように動作しますが、コマンドは最初に開始されますsleepが、ksh93のbuitinと同様に、ksh93には、whileループがメインシェルから分岐し、^ Zを入力したときに一時停止するハンドラーがあります。

あなたの中にいる場合は、ksh93以降のタイプfg、まだループを実行することをフォークした子が継続されます。

bashとksh93からのジョブ制御メッセージを比較すると、主な違いがわかります。

bashレポート:

[1]+ Stopped sleep 1

しかしksh93は報告します:

^Z[1] + Stopped while true; do echo .; sleep 1; done

zshksh93と同様に動作します

どちらのシェルでも、^ Zを入力しない限り、1つのプロセス(メインシェル)と、^ Zを入力した後の2つのシェルプロセスがあります。


いないdash実際にループが終了したとき、信号を処理する羽目になる?で[d]?ashソースコードこれらのマクロのすべてのために存在するINTONINTOFF全体に分散、およびにしながら、典型的には、受信した信号INTOFFの状態実際に処理される(または付近) INTON。とにかく、私はあなたがもっとよく知っていると思うので、興味があるだけです-それは素晴らしい答えです。ありがとうございました。
mikeserv 2015年

私はめったにダッシュを使用せず、最近bash、ksh93、および私のBourne Shellとのパフォーマンス比較のためにフェッチしてコンパイルしました。これらのテストを行っているときに、マルチバイト文字のサポートが含まれていないため、ダッシュが主に高速であるように見えました。シングルsleep 100はで一時停止および再開できるdashためdash、このコマンドの問題を認識しており、ジョブ制御を選択的に無効にしているようです。
schily 2015年

したがって、テストでは、dashマルチバイト処理を削除することにより、他のシェルでのパフォーマンスに匹敵することができましたか?はい、dashジョブ制御をサポートしますが、標準では、対話型シェルはTSTPを無視する必要があると規定されており、対話型端末で現在のシェルでwhileループを実行することは、他の対話型シェルと同じです。
mikeserv 2015年

私はこれを正確にテストしませんでしたが、ダッシュはksh93またはBourneシェルよりも多くのシステムCPU時間を消費しますが(主にそれがより多くのfork()呼び出しを発行するため)、使用するユーザーCPU時間は少なく、これにより合計は同様になります。私のバージョンのBourne Shellと比較したCPU時間。Bourne ShellでユーザーのCPU時間を削減しようとしたことから、この時間のほとんどはマルチバイト変換に費やされていることがわかります。
schily 2015年

4

私はこの問題についてBashの共著者の1人を書きました、そしてここに彼の返事があります:

これは実際にはバグではありませんが、確かに警告です。

ここでの考え方は、プロセスを一時停止することです。これは、シェルコマンドとは異なる粒度の単位です。プロセスが一時停止されると、シェルに戻ります(ゼロ以外のステータス、つまり、ループテストであるプロセスを停止したときに結果が発生します)。これには選択肢があります。ループから抜けるか、ループを継続することができます。 、停止したプロセスを残します。Bashは、ジョブが停止したときにループから抜け出すことを選択し、常に選択しています。ループを継続することはめったにありません。

他のいくつかのシェルは、SIGTSTPによってプロセスが中断されたときにシェルのコピーをフォークし、そのプロセスを停止するなどの処理を行います。Bashがこれを行ったことはありません-メリットの保証よりも複雑に思えます-が、誰かがそのコードをパッチとして提出したい場合は、変更を組み込むことを検討します。

したがって、誰かがパッチを提出したい場合は、マニュアルページにある電子メールアドレスを使用してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.