web-dev-qa-db-ja.com

バックグラウンドでループが実行されている間にbashを停止する方法は?

次のようにwhileループを開始しました。

while true; do {command}; sleep 180; done &

&に注意してください。

ターミナルを殺すと、このwhileループが停止すると思いました。しかし、まだ進行中です。ターミナルセッションを終了してから数時間かかりました。

Whileループを停止するにはどうすればよいですか?

23
Saqib Ali

始めた

while true; do yad; sleep 60; done &

そして、それをテストするために端末を閉じましたが、今は同じ問題が発生しました。

既に端末を閉じている場合は、ループを開始しました

ps fjxを使用して実行中のプロセスの概要を取得しましょう。私のマシンの最後の行は

 2226 11606 11606 19337 ?           -1 S     1000   0:00  \_ /bin/bash
11606 22485 11606 19337 ?           -1 S     1000   0:00  |   \_ sleep 10
 2226  9411  9411  8383 ?           -1 S     1000   0:00  \_ /bin/bash
 9411 17674  9411  8383 ?           -1 Sl    1000   0:00      \_ yad
    1  2215  2215  2215 ?           -1 Ss    1000   0:00 /lib/systemd/systemd --user
 2215  2216  2215  2215 ?           -1 S     1000   0:00  \_ (sd-pam)

yad/bin/bashのサブプロセスとして見ることができます。yadを閉じると、psの出力でsleep 60に変わります。ツリービューがわかりにくい場合は、次のように出力を検索することもできます1

ps fjx | grep "[y]ad"  # or respectively
ps fjx | grep "[s]leep 60"

出力行は2つの番号で始まります。最初の番号はPPID(親プロセスのプロセスID)で、2番目の番号はPID(プロセス自体のID)です。これは、9411が両方の行に表示されるためです。

2226  9411  9411  8383 ?           -1 S     1000   0:00  \_ /bin/bash
9411 17674  9411  8383 ?           -1 Sl    1000   0:00      \_ yad

それが、私たちが殺したいbashサブシェルであり、PIDを見つけたので、残っているものはすべてシンプルです

kill 9411  # replace 9411 with the PID you found out!

迷惑なサブシェルは永久に消えてしまいました。

1:単にgrep "[y]ad"の代わりにgrep yadとしての表記により、grepプロセス自体が結果リストに表示されなくなります。


端末がまだ開いている場合

bashは、変数$!を提供します。これは、「最後にバックグラウンドに置かれたジョブのプロセスIDに展開される」ため、次のようにバックグラウンドで最新のプロセスを強制終了します。

kill $!

not最新プロセスの場合、jobsビルトインを使用して実行中のジョブのリストを取得できます。出力例:

[1]-  Running                 while true; do
    yad; sleep 60;
done &
[2]+  Stopped                 sleep 10

ジョブリストには2つのジョブがあり、そのうちの1つを削除するには、ジョブ番号またはショートカット%%+(「現在のジョブ」)および%-(「前の仕事」)、たとえばバックグラウンドで実行されているループを強制終了するには

kill %1  # or
kill %-

中断されたsleep 10ジョブを強制終了するには:

kill %2  # or
kill %+  # or
kill %
38
dessert

そのコマンドを入力したターミナルを閉じると、サブコマンドも一緒に停止することに注意してください。これを再現しようとすると、この動作が示されました。

さて、あなたが実際にこれが起こらなかった状況にあると仮定すると、コマンドの最後の&によって引き起こされた、バックグラウンドで実行しているプログラムを強制終了する方法の1つは、次のように:

  1. 新しいシェルを開いてecho $$を実行し、現在のPID(プロセスID)を記録して、自分のセッションを強制終了しないようにします。
  2. まだ実行していると思われるプログラムのPIDを特定します。 ps -ef | grep $Shellコマンドを使用してこれを実行し、シェルを実行しているプログラムを見つけることができます。
  3. 左から2番目の列に注目し、上記のecho $$の結果からdiffersとなる数値に注目してください。これは、殺したいPIDです。
  4. kill -SIGTERM <pid>コマンドを実行します。<pid>は、ステップ#3で特定した数値です。
  5. 手順2を繰り返して、プログラムが実行されていないことを確認します

セッションまたはコンピューターを再起動することもできますが、上記の方法で回避できます。

5
code_dredd