在shell脚本中,我看到使用setsid,我们可以创建一个新的进程组。 创建后,我找不到可靠的方法来获取组ID。 我的要求很简单,启动一个进程,完成后,清理任何后代(如果有的话(。 我不想杀死主进程,因此我必须等待主进程结束。 之后,如果我以某种方式获得了组 id,我可以杀死剩余的子进程。 这可以通过杀死-- -pgid来完成。 缺少的部分是如何获取组 ID?
这个脚本是我最终想到的。 希望这对某人有所帮助。$!将给出 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
我设法用coproc和睡眠来做到这一点,以确保我们有足够的时间回读pid。当然,这是特定于 bash 的,避免在 coproc 中使用黑客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(以及父文件在子写入之前死亡并删除它的风险(,我再次打开fh 3
以便孩子可以将其pgid写入它。
#!/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