bashシェルスクリプトで子プロセスのPIDを親プロセスにインポートする方法は?

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を終了する必要があります。
process1を終了するのはPIDをファイルに書き込むので簡単です。しかし、sub_process1はそうではありません。 sub_process1はサードパーティのコンポーネントなので、ソースコードに触れることはできません。
sub_process1のPIDを取得するソリューションがあります。

  1. すべてのプロセスを列挙するには、このコマンドを使用しますps aux
  2. コマンドを使用して、各プロセスのPPID(親プロセスID)を取得しますps -f [PID]。 PPIDがprocess1のPIDと等しい場合、プロセスはsub_process1でなければなりません。
    上記の解決策は少し複雑です。子プロセスIDを取得する簡単なソリューションはありますか?
    ありがとうございます。

答え1

pgrepLinux:/とマークしたので、pkill次のようにします。

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

答え2

processバックグラウンドプロセスとして実行してプロセスIDを取得できます。

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

コマンドは元のスクリプトと同様に終了をwait待ちます(子プロセスではありません)。process1元のスクリプトにprocess1最後に終了するものはありません。./process1コマンドはprocess1終了時にのみ完了します。プロセスには同じ名前の子プロセスがあります(つまり、プログラムforkしかし、execve)。process1スクリプトの開始直後にスクリプトを実行し続ける場合は、この行waitを省略してください。

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

./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"

答え3

君ができるのはkill -TERM君だけだプロセスグループ。スクリプトがシェルから呼び出されると、スクリプトのPIDと同じ独自のプロセスグループがあります。

kill -TERM -$$

別の方法で呼び出されると、プロセスグループIDがPIDと等しくない可能性があります。

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

kill -9プログラムに公正な機会を提供しない限り、スクリプトやプログラムに参加してはいけませんkill -TERM

aを実行するfind pid and kill itことは競合状態の影響を受けます(ただし、ボックスがクレイジーなプロセスを作成しない限り頻繁には見えませんが)。pidあなたが殺すpidがあなたの子供であり、pidが待っていないことによってリサイクルされないことを保証しない限り、sは移動目標です。 (私が知っている限り、bashではほとんどできません)それ以外の場合は、正しいプロセスを終了していないことを100%確信しています(pidを見つけて終了する間にプロセスが終了し、他のプロセスがpidを取得した可能性があります) )。

答え4

setsid ./process1 & pgid=$!以下を使用して別々のプロセスグループを使用または作成する必要があります。職業管理set -m; ./process1 & pgid=$!; set +m次の手順でプロセスグループ全体を終了しますkill -- -$pgid。追加情報ここ

関連情報