在shell脚本中,我看到使用setsid可以创建一个新的进程组。创建后,我无法找到一种可靠的方式来获取组ID。我的要求很简单,启动一个流程,完成后,清理所有后代(如果有)。我不想杀死主要进程,因此我必须等待主要进程结束。之后,如果我以某种方式获得了组ID,则可以杀死剩余的子进程。可以用kill--pgid完成。缺少的部分是如何获取组ID?
答案 0 :(得分:0)
这个脚本是我最终想到的。希望这对某人有帮助。 $!将提供pid,并且必须使用ps来找到它的gid。 使用ps时前面有一个多余的空间,下一行可变扩展将删除前导空间。 最后,在等待主要过程后,它杀死了该小组。
#!/bin/sh -x
setsid "$@" &
pid=$!
gidspace=$(ps -o pgid= $pid)
gid="${gidspace## }"
echo "gid $gid"
echo "waiting"
wait $pid
ps -s $gid -o pid,ppid,pgid,command
kill -- -$gid
答案 1 :(得分:0)
我设法用 coproc 和 sleep 来完成,以确保我们有足够的时间读回 pid。这当然是 bash 特定的,避免在 coproc 中使用 hackish sleep
的唯一方法是写入临时文件并等待命令终止(然后不需要 coproc)。
请注意,我打开文件句柄 3
将 pgid 写回父 shell 并在执行命令之前关闭它。
#!/bin/bash -x
coproc setsid bash -c 'ps -o pgid= $BASHPID >&3; exec 3>&-; exec "$@" & sleep 1' -- "$@" 3>&1
read -u ${COPROC[0]} gid
echo "gid $gid"
ps -s $gid -o pid,ppid,pgid,command
kill -- -$gid
为了避免将临时文件传递给子shell(以及在子shell写入之前父级死亡并删除它的风险),我再次打开 fh 3
以便子级可以将其 pgid 写入它。< /p>
#!/bin/bash -x
t=$(mktemp)
trap 'rm -f "$t"' EXIT
exec {fh}>"$t"
setsid bash -c 'ps -o pgid= $BASHPID >&3; exec 3>&-; exec "$@" &' -- "$@" 3>&${fh}
read gid <$t
echo "gid $gid"
ps -s $gid -o pid,ppid,pgid,command
kill -- -$gid