私はblah.sh
これを端末で実行しています。その後、別の端末で一時停止して後で再起動するスクリプトを実行していますblah.sh
。
...
script_id=`pidof -x blah.sh`
kill -s SIGSTOP $script_id
...
script_id=`pidof -x blah.sh`
kill -s SIGCONT $script_id
その後はバックグラウンドにプッシュされます。これを停止するには、-を入力する必要がblah.sh
あります。fg
CtrlC
blah.sh
送信後、端末の前景に自動的に表示する方法はありますかSIGCONT
?
答え1
blah.sh
送信後、端末の前景に自動的に表示する方法はありますかSIGCONT
?
まず、必要なものに応じて、必要なものを得ることSIGSTOP
もできない場合もあります。
分析する
あなたの場合は、次のことが起こっていると思います。
ジョブ制御は、実行しているシェルで有効になります
blah.sh
。シェルは別のプロセスグループからプロセスを開始し、プロセスグループがフォアグラウンドプロセスグループであることを端末に通知します。このようにしてプロセスが前景で実行されている間、シェルは自分自身を背景にします。プロセスを実行すると
kill -s STOP
(他の端末に入力して)プロセスが停止し、シェルがSIGCHLD
自動的に起動します。このシグナルは、「あなたの子供の少なくとも1人がブロックまたは終了しました。今、子供を確認して対応する必要がある時です。」という意味です。シェルは応答して
SIGCHLD
子プロセスが停止したことを確認し、自分のプロセスグループを端末のフォアグラウンドプロセスグループに設定して自分をフォアグラウンドにインポートします。送信ではなく送信する場合、SIGTSTP
これはシェルを前景にインポートする正確なメカニズムですSIGSTOP
。たとえば、プロセスが実行されている端末で+を押すと、Ctrlフォアグラウンドプロセスグループが受信されます。これはシェルが反応するのではなく、プロセスを意味します。ZSIGTSTP
SIGCHLD
これでシェルは前景にあり、プロンプトを印刷して入力を待っています。
実行するとプロセスが続行されます
kill -s CONT
。SIGCHLD
シェルに反応させる同様のメカニズムはありません。シェルは端末の前景プロセスグループを知らず、変更しません。実際、シェルはまだ正式にフォアグラウンドにあり、プロセスはまだ正式にバックグラウンドにあります。
プロンプトを無視してシェルとの対話を中断するだけで十分だと思うかもしれません。一般的に言えば:いいえ。バックグラウンドプロセスがSIGTTIN
端末(通常は標準入力)から読み取ろうとすると、メッセージが表示されます。ターミナル()の設定によっては、stty tostop
バックグラウンドプロセスがターミナルSIGTTOU
(ほとんどの場合stdoutとstderr)に書き込もうとすると、それを受信することもできない場合もあります。SIGTTIN
またはの基本的な作業はSIGTTOU
プロセスを停止することです。また、読み取りを試みている間にプロセスが停止しなくても、シェルは同じ端末で読み取られているため、シェルが入力を「盗む」ため、プロセスと対話することは困難です。
Ctrl+端末ドライバをフォアグラウンドプロセスグループにC送信できるようにします。SIGINT
問題のプロセスがバックグラウンドにある場合は、信号を受信できません。
入力(他の端末から送信するfg
代わりに)はシェルに組み込まれているため、実際にこれを処理するシェルであるため、うまく機能します。シェルはプロセスを前面にインポートすることを知り、独自の動作を変更します。 (端末の読み取りでプロセスを停止し)、プロセスのプロセスグループに送信する前に、それに応じてフォアグラウンドプロセスグループを設定します。SIGCONT
fg
fg
SIGCONT
プロセスを停止した理由がシェルと対話するためのものである場合は、シェルと対話(つまりシェル呼び出し)してプロセスを再開する必要がありますfg
。
考えられる解決策
しかし、もしプロセスを停止した理由はシェルとは関係ありません(たとえば、プロセスがコンピューティングを停止したい場合など)。プロセスの開始方法を変更する必要があります。シェルでジョブ制御を無効にする。次のことが起こります。
あなたは実行します
set +m; blah.sh
。set +m
ジョブ制御を無効にします。シェルが起動すると、blah.sh
プロセスはシェルのプロセスグループに配置されます。このプロセスグループは、今後も常にフォアグラウンドプロセスグループになります。プロセスを実行すると
kill -s STOP
(他の端末に入力して)プロセスが停止し、シェルがSIGCHLD
自動的に起動します。シェルペアが反応します
SIGCHLD
。子プロセスが終了したのか、ユーザーとのやり取りを再開するのかを知りたいのです。シェルは子プロセスが終了せず、停止していると報告され、ジョブ制御が無効になっているため、この場合、シェルはユーザーとの対話を再開しません。シェルとプロセスの両方がフォアグラウンドにあります。シェルは読み取りまたは書き込みを試みず、プロセスが停止します。彼らはただそこにとどまります。
実行すると、プロセスは続行されます
kill -s CONT
。シェルはわかりませんが、プロセスが最終的に終了するのを待ち、他に何もしないので問題ありません。
ノート
blah.sh
技術的には、このソリューションは「端末で自動的に前景を表示する方法」ではありません。blah.sh
常に前景にあるので「自動前景」する必要はありません。常に前景にあるため、
blah.sh
その時点で停止してもCtrl+Cが送信されます。SIGTERM
Stoppedは受信した場合blah.sh
にのみ反応します。単独で送信することは子として送信することを意味せず、すぐに反応する可能性が高いです。SIGTERM
SIGCONT
SIGSTOP
blah.sh
SIGSTOP
CtrlCSIGSTOP
単独で送信することは子として送信することblah.sh
を意味しないため、プロセスグループ全体が常駐するプロセスグループに送信することを検討できます。何らかの理由で意図的に他のプロセスグループに含まれていない限り、各サブアイテムもそのグループに属します。 「負のPID値を使用してプロセスグループ全体を選択できます」を参照してください。SIGSTOP
SIGSTOP
SIGCONT
blah.sh
man 1 kill
通常、(シェルでジョブ制御が有効になっている場合)、その子孫は
blah.sh
PIDと同じPGIDを持つプロセスグループにあると予想する必要がありますblah.sh
。私たちのソリューションでは、(タスク制御が無効になっている場合)、その子孫がシェルと同じプロセスグループにあると予想する必要があり、blah.sh
PGIDはシェルのPIDと同じかもしれません。set +m; blah.sh; set -m
シャットダウン後にジョブ制御を自動的に再度有効にしたい場合はblah.sh
有望に見えますが、Ctrl実行中に+を使用してそれを中断すると機能しません。この状況を確実に処理するためのいくつかのトラップがありますが、詳しくは説明しません。Cblah.sh
set -m
ジョブ制御が無効になると、シェルはそれを無視します
SIGTSTP
。シェルによって開始されたプロセス(例えばblah.sh
)もこれを無視します。 (一部のプロセスが意図的に無視されないように選択しない限り)これは、Ctrl+が機能すると期待してはいけませんZ。
答え2
これを行う方法はありません。シェルのみがフォアグラウンドアプリケーションを管理できます。シェルにバックグラウンドで実行されている複数のアプリケーションがあり、他のSIGCONT
端末からそれらの複数のアプリケーションに転送する状況を考えてみましょう。何が起こると予想していますか?
唯一の目的がステップを削除することである場合は、最初に実行してからkill -s SIGCONT $script_id
実行するのではなく、ステップを実行するだけです。すでにバックグラウンドプロセスに送信されているので、コマンドを使用して信号を明示的に送信する必要はありません。fg
fg
fg
SIGCONT
kill