获取子进程的pid

Posted

技术标签:

【中文标题】获取子进程的pid【英文标题】:getting the pid of a sub-process 【发布时间】:2021-08-08 14:43:22 【问题描述】:

我有一个这样的脚本:

sh child1.sh &
child=$!
sh child2.sh
kill "$child"

我为另一个进程运行一个后台进程child1child2 使用,当child2 完成时,我杀死child1

现在无论出于什么原因,我现在想在子进程中运行child1.sh,即像这样运行它:

(sh child1.sh)

如何将子进程的 id 传递给父进程,以便像以前一样杀死它?

我试过了:

(sh child1.sh &)

(sh child1.sh ) &

但似乎都不起作用。

【问题讨论】:

hmm 我使用() 的原因是:***.com/questions/786376/… 我想避免不得不 cd 回到原始目录。也许我没有使用正确的术语? 我会说这样做的方法是(sh child1.sh ) &。之后发出child=$! 时,您将不会获得child1.sh 的PID,而是child1.sh 正在运行的shell 的PID。在我看来,这不是问题,因为在正常情况下杀掉 shell 会杀掉所有的子进程,只要你没有用nohup 启动这些子进程。 @PierreFrançois 要杀死的进程是一个节点应用程序,当我按照我的建议进行操作时。我得到这个记录: 终止。但是随后该进程仍在后台运行,并且我以后再次尝试运行父脚本的尝试失败了,因为端口仍然很忙。 @Mathsnoob:child1.sh 是或运行节点应用程序这一事实大大改变了问题。也许它在被杀死时不会优雅地退出。您应该提及 node app 作为关键字,并提供有关 node 应用程序在多种类型的信号被杀死时如何退出的更多信息。 @PierreFrançois 嗯。当我在没有子进程的情况下杀死它时,节点应用程序会优雅地死掉。所以我不认为这是child1 固有的任何东西,而是更多关于我们如何杀死它? :思考 【参考方案1】:

来自 cmets,我猜你正在寻找那个来杀死“正确”的外壳:

child=$(
sh "child1.sh" 1>&2 &
echo $! )
echo "main pid $child"
sh child2.sh
kill "$child"

如果您不想混合 child1 的 stdout 和 stderr 输出。

编辑: 但我想最好杀死 child1 的子进程。如果您安装了/proc,则可以这样做:

EDIT2:按顺序获取所有孩子的 PID,以便 显示,注意kill 将向每个孩子发送SIGTERM并且不要打扰订单。并注意 cmd 名称中带有括号或空格的进程。

child=$(
sh "child1.sh" 1>&2 &
echo $! )
echo "main pid $child"
sh child2.sh
child_proc=$(cat /proc/*/stat | sed 's/([^\)]*)*\( [TRS]\)/proc\1/' | sort -k4n,1n | awk -v parent=$child -F' '  '
BEGIN pids[0]=parent;
fnd=-1;for(i=0;i<=npids;i++)  if (pids[i]==$4) fnd=i; 
 if (fnd!=-1)  pids[npids++]=$1;;

END  for(i=npids-1; i>=0; i--) print pids[i]; ')
echo "childs of child1 : $child_proc"
kill $child_proc

child1 和 child2 shell 都会正常退出,只有 child1 的子进程应该被杀死。

EDIT3:如果您的ps 客户端支持格式化输出,那么避免sedsort 的更简单、更安全的方法是:

child=$(
sh "child1.sh" 1>&2 &
echo $! )
echo "main pid $child"
sh child2.sh
child_proc=$(ps -o pid= -o ppid= -A | awk -v parent=$child -F' '  '
BEGIN pids[0]=parent;
fnd=-1;for(i=0;i<=npids;i++)  if (pids[i]==$2) fnd=i; 
 if (fnd!=-1)  pids[npids++]=$1;;

END  for(i=npids-1; i>=0; i--) print pids[i]; ')
echo "childs of child1 : $child_proc"
kill $child_proc

【讨论】:

以上是关于获取子进程的pid的主要内容,如果未能解决你的问题,请参考以下文章

fork子进程之间传输信息的方法(包含子进程与子进程之间区分的问题的解决)

.NET (C#):只有进程句柄或 PID 时获取子窗口?

使用libproc获取子进程

如何获取子进程的输出

多任务-进程之PID

如何在脚本中获取进程ID