1

在一个 shell 脚本中,我看到使用 setsid,我们可以创建一个新的进程组。创建后我无法找到可靠的方法来获取组 ID。我的要求很简单,启动一个进程,完成后,清理任何后代(如果有的话)。我不想杀死主进程,因此我必须等待主进程结束。之后,如果我以某种方式获得了组 ID,我可以杀死剩余的子进程。这可以通过 kill -- -pgid 来完成。缺少的部分是我如何获得组 id ?

4

2 回答 2

2

这个脚本是我最后想出来的。希望这可以帮助某人。美元!将给出 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 
于 2019-04-14T01:33:41.623 回答
0

我设法用 coproc 和 sleep 来确保我们有足够的时间读回 pid。这当然是特定于 bash 的,避免sleep在 coproc 中使用 hackish 的唯一方法是写入临时文件并等待命令终止(然后不需要 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

使用临时文件

为了避免必须将临时文件传递给子外壳(以及父级在子级写入之前死亡并删除它的风险),我再次打开 fh3以便子级可以将其 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
于 2021-03-13T18:54:02.447 回答