我需要使用 korn shell 来编写我正在编写的脚本,并遇到了管理嵌套子进程的问题。下面的示例代码演示了我的问题。我在其中创建了一个临时文件 x 秒,然后将其删除,以便我可以查看作业是否仍在实际运行。我得到了后台子 shell“驱动程序脚本”内部和外部的 PIDS 列表;在内部,pgrep
可以找到子进程,但在外部调用时却找不到,即使两者都显示正确的父进程 PID。我不明白什么?jobs -pr
如果 pgrep 不起作用,如何保证从子 shell 外部仅获取正在运行的作业的 PID(在 bash 中)?
#!/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" " ")"
这是输出。 “spawned driver 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 无关。问题是驱动程序脚本在子级之前结束,因此所有关联都被取消引用。向驱动程序添加等待解决了我的问题。