web-dev-qa-db-ja.com

bashシェルスクリプトでサブプロセスのPIDを親プロセスに取得する方法は?

私のシェルスクリプトは次のとおりです。

#!/bin/bash
./process1 #It will create a sub process: sub_process1
while [ condition ]; do
    break
done
kill -9 process1 and sub_process1

私のスクリプトでは、プロセスを作成します:process1。 process1はサブプロセスを作成します:sub_process1。
スクリプトが終了する前に、process1とsub_process1を強制終了する必要があります。
PIDをファイルに書き込むため、process1を簡単に強制終了できます。しかし、sub_process1はしません。 sub_process1はサードパーティのコンポーネントなので、ソースコードを変更することはできません。
sub_process1のPIDを取得できるソリューションがあります:

  1. コマンドps aux;を使用してすべてのプロセスを列挙します。
  2. コマンドps -f [PID]を使用して、各プロセスのPPID(親プロセスID)を取得します。 PPIDがprocess1のPIDと等しい場合、プロセスはsub_process1である必要があります。
    上記の解決策は少し複雑です。サブプロセスIDを取得できる簡単なソリューションはありますか?
    どうもありがとう。
4
yw5643

これをLinuxとしてタグ付けしたので:pgrep/pkillが救助に:

PID_OF_SUB_PROCESS1=$( pgrep -P $PID_OF_PROCESS1 )
pkill -P $PID_OF_PROCESS1
2
lcd047

pkillはプロセスを強制終了できます名前で

pkill process1 && pkill sub_process1

仕事をする必要があります。

0
user1717828

バックグラウンドプロセスとして実行することにより、processのプロセスIDを取得できます。

./process1 &
pid1=$!
wait "$pid1"

waitコマンドは、元のスクリプトと同様に、process1が終了するのを待ちます(ただし、そのサブプロセスは待ちません)。元のスクリプトでは、最後に強制終了するprocess1がないことに注意してください。./process1コマンドは、process1が終了したときにのみ終了します。同じ名前のそのプロセスの子プロセスが存在する可能性があります(つまり、プログラムが fork を呼び出したが、 execve を呼び出さなかった可能性があります)。 process1自体が開始されたらすぐにスクリプトの実行を継続する場合は、wait行を省略してください。

pkill コマンドがある場合は、プロセスのすべての子を強制終了するのに便利な方法です。プロセスはまだ実行中であるか、 zombie である必要があることに注意してください。そうしないと、子の親プロセスIDが1にリセットされ、この方法で追跡できなくなります。スクリプトでwaitを呼び出さない限り、バックグラウンドプロセスIDは有効なままです。

./process1 &
pid1=$!
…
pkill -9 -P "$pid1"
kill -9 "$pid1"

プロセス、その子、およびその子を再帰的に追跡する別の方法は、 プロセスグループ を追跡することです。プロセスの子は、明示的に変更しない限り、同じプロセスグループを持ちます。 Linuxでは、 setsid コマンドを使用して、独自のプロセスグループでプログラムを実行できます。プロセスグループは、元のプロセスのプロセスIDによって識別されます。プロセスグループ内のすべてのプロセスを強制終了するには、プロセスグループIDの負の値をkillに渡します。

setsid ./process1 &
pgid1=$!
…
kill -9 "-$pgid1"

プロセスを追跡するさらに別の方法は、プロセスにファイルを開かせることです。これは、プロセスがファイルを閉じない限り機能するため、デーモンとして実行することを目的としたプログラムでは機能しない可能性があります。コマンド fuser を使用して、ファイルを開いているプロセスを強制終了します。

tmpfile=$(mktemp)
process1 <"$tmpfile"
…
fuser -k -9 "$tmpfile"

あなたにできることはkill -TERM you プロセスグループです。スクリプトがシェルから呼び出された場合、スクリプトのPIDと等しい独自のプロセスグループがあります。

kill -TERM -$$

それ以外の方法で呼び出された場合、そのプロセスグループIDはそのPIDと等しくない可能性があります。

kill -TERM -`ps -o pgid $$ | tail -1`

スクリプトにkill -9を使用しないでください。ただし、kill -TERMを使用してプログラムに公平な機会を与える場合を除きます。

find pid and kill itの実行は、競合状態の影響を受けます(ただし、ボックスがクレイジーなプロセスを生成しない限り、頻繁に実行されるわけではありません)。 pidsは動くターゲットであり、あなたが殺しているpidがあなたの子供であり、まだそれを待たないことによってpidがリサイクルされないことを保証していない限り(bashではほとんどできないことです)私は知っています)、あなたが正しいプロセスを殺していることを100%確信することはできません(pidを見つけて殺すまでの間に、プロセスが死んで、別のプロセスがpidを取っているかもしれません)。

0
PSkocik