5

ループ内で並列処理を行うbashスクリプトがあります。並列プロセスでCPUを急上昇させたくないので、sleepコマンドを使用します。これが簡略化されたバージョンです。

(本当の間;眠る99999;完了)&

したがって、bashプロンプトから上記の行を実行すると、次のようになります。 [1] 12345

ここ[1]で、はジョブ番号であり、12345はwhileループのプロセスID(pid)です。私はしkill 12345て取得します:

[1] +終了しました(trueの間、実行します)
    睡眠99999;
終わり )

スクリプト全体が終了したようです。しかし、私はaを実行しps aux|grep sleep、sleepコマンドはまだ強力ですが、独自のpidを使用していることがわかりました。私は殺すことができsleep、すべてがうまくいくようです。ただし、最初にスリープを強制終了した場合、whileループは新しいsleeppidを開始します。睡眠はwhileループと平行ではないので、これは私にとって非常に驚きです。ループ自体は単一の実行パスです。

だから私は2つの質問があります:

  1. sleepコマンドが独自のプロセスIDを取得したのはなぜですか?
  2. whileループとスリープを簡単に強制終了するにはどうすればよいですか?
4

6 に答える 6

5
  1. PIDスリープは、実行中のプロセスであり、待機しているだけなので、独自のものになります。それがどこにあるか見てみwhich sleepてください。
  2. を使用ps -ufして、システムのプロセスツリーを表示できます。そこからPPID、スリープのシェル(ループを実行しているもの)の(親PID)が何であるかを判別できます。
于 2010-12-15T16:42:43.387 に答える
2
  1. 「スリープ」はプロセスであり、組み込み関数などではありません。

  2. 次のことができます。

    (while true;do sleep 99999;done)&
    whilepid=$!
    kill -- -$whilepid
    

上記のコードは、PIDが負の数(たとえば、123ではなく-123)として指定されているため、プロセスグループを強制終了します。さらに、$!最後に実行されたプロセスのPIDを格納する変数を使用します。

注:インタラクティブモードでバックグラウンドで(つまり、コマンドラインプロンプトを使用して)プロセスを実行すると、新しいプロセスグループが作成されます。これがあなたに起こっていることです。そうすれば、プロセスグループ全体を強制終了するだけでよいため、「すべてを強制終了」するのは比較的簡単です。ただし、スクリプト内で同じことを行うと、バックグラウンドで実行された場合でも、すべての新しいプロセスがスクリプトPIDに属するため、新しいグループは作成されません(ジョブ制御はデフォルトで無効になっています)。スクリプトでジョブ制御を有効にするには、スクリプトの先頭に次のように入力する必要があります。

#!/bin/bash

set -m
于 2016-08-17T18:51:11.730 に答える
1

やってみましたか?コマンドをバックグラウンドで起動した後に得られる数字はkill %1どこですか?1

起動してすぐに実行しましたが(while true;do sleep 99999;done)&、正しく終了しました。

于 2010-12-15T16:37:35.530 に答える
1

「ps--ppid」は、指定された親pidを持つすべてのプロセスを選択します。例:

$ (while true;do sleep 99999;done)&
[1] 12345

$ ppid=12345 ; kill -9 $ppid $(ps --ppid $ppid -o pid --no-heading)
于 2010-12-15T16:42:40.947 に答える
1

プロセスグループを強制終了できます。

プロセス実行のプロセスグループを見つけるには:

ps --no-headers -o "%r" -p 15864

次に、以下を使用してプロセスグループを強制終了します。

kill -- -[PGID]

すべてを1つのコマンドで実行できます。試してみましょう:

$ (while true;do sleep 99999;done)&
[1] 16151

$ kill -- -$(ps --no-headers -o "%r" -p 16151)
[1]+  Terminated              ( while true; do
    sleep 99999;
done )
于 2010-12-15T16:59:49.937 に答える
0

whileループとsleep使用を強制終了するには、サブシェル内でシグナルハンドラーを$!使用することもできます。trap

(trap 'kill ${!}; exit' TERM; while true; do sleep 99999 & wait ${!}; done)&
kill -TERM ${!}
于 2013-03-11T16:10:23.473 に答える