作成中のスクリプトにkornシェルを使用する必要があり、入れ子になった子プロセスを管理する際に問題が発生しました。以下のサンプルコードは私の問題を示しています。 x秒間一時ファイルを作成して削除すると、ジョブが実際に実行され続けていることを確認できます。内部の背景サブシェル「ドライバスクリプト」の内部と外部からPIDSのリストを取得します。pgrep
両方のプロセスが正しい親プロセスPIDを表示しても、外部から呼び出すときは見つかりません。私が理解していないものは何ですか?jobs -pr
pgrepが機能しない場合は、サブシェルの外部で実行されているジョブ(bash)のPIDのみを取得することをどのように保証できますか?
#!/bin/ksh
# create a file for x seconds and then remove it
testfunc() {
timesec=$1
touch "${HOME}/testfunc/testfunc_${timesec}.file"
sleep $timesec && rm -f "${HOME}/testfunc/testfunc_${timesec}.file"
}
# subshell to manage jobs
(
driver_script_pid="$(exec sh -c 'echo $PPID')"
for num in 10 35 40 5; do
testfunc $num &
echo "child id: $!"
done
echo "\$\$ $$"
echo "subshell: $driver_script_pid"
echo "children of parent: $(pgrep -P $$)"
echo "children of subshell: $(pgrep -P $driver_script_pid | tr "\n" " ")"
for ids in $(jobs -p ); do
echo "pid: $ids PPID: $(ps -p "$ids" -o ppid=) DONE"
done
) &
driver_pid=$!
# we still have 10 sec, 35 sec, and 40 sec job still running as verified by the files
# existing
sleep 6
echo after 6 seconds
echo "spawned driver pid: \"$driver_pid\""
echo child processes:
echo "$(pgrep -P "$driver_pid" | tr "\n" " ")"
これが出力です。 「生成されたドライバpid」は「subshell pid」と一致しますが、同じpgrepはバックグラウンドプロセスの外で実行されると空白として表示されます。しかし、10番目、35番目、45番目のジョブに該当するファイルはそのまま残っていますが、一定時間が経過すると削除されるとみて、そのジョブが実行中であることがわかります。
child id: 27195
child id: 27196
child id: 27197
child id: 27199
$$ 27192
subshell: 27193
children of parent: 27193
children of subshell: 27195 27196 27197 27199 27205
pid: 27199 PPID: 27193 DONE
pid: 27197 PPID: 27193 DONE
pid: 27196 PPID: 27193 DONE
pid: 27195 PPID: 27193 DONE
after 6 seconds
spawned driver pid: "27193"
child processes:
答え1
私の問題はpgrepとは関係ありません。問題は、ドライバスクリプトが子の前に終了するため、すべての接続が逆参照されることです。ドライバに待ち時間を追加すると問題が解決しました。