如何设置一个shell脚本的进程组

如何设置一个shell脚本的进程组? 另外我希望所有的subprocess都在同一个进程组中

我期望在C中与setpgid()类似。

PSkocik指出 ,通过激活作业控制(“监视模式”),可以在大多数shell中在其自己的进程组中运行一个进程。

(set -m; exec process_in_its_own_group) 

Linux有一个setsid工具,它在自己的会话中使用作为参数传递的命令(使用同名的系统调用 )。 这比在它自己的setpgrp 过程组中运行它更强大,但是对于您的目的而言也许是可以的。

如果你想把进程放在一个现有的组中,而不是在它自己的组中(也就是说,如果你想要setpgid的全部功能),那么就没有常用的shell工具。 你必须使用C / Perl / …

我不认为Bourne,bash或者zsh会让你这样做,但是你可以在perl中使用内置的setpgrp (注意与POSIX略有不同)。 传递零作为PID来修改perl进程本身的组:

 setpgrp(0, 12345) || die "$!" 

你可能会认为你可以用bash来设置bash进程的组(例如,通过将$$传递给perl脚本),但是我不认为perl进程能够修改过程,它没有分叉。

根据你想要做的事情,各种shell中的作业控制功能可能会以不同的方式给你所需要的东西,比如你只是想从终端上分离出来。

更新:我觉得奇怪的是,这个答案已经收到了一些没有明确解释为什么的票。 我的猜测是,downvoters误解了这个问题,就是如何改变 当前 shell的进程组。 或者也许他们知道如何从shell中执行setpgrp,但保留自己的秘密。

我会回答我所理解的部分内容:

如何强制当前的bash shell脚本是它自己的进程组:

我把这个放在我的bash脚本的开头:

 pgid_from_pid() { local pid=$1 ps -o pgid= "$pid" 2>/dev/null | egrep -o "[0-9]+" } pid="$$" if [ "$pid" != "$(pgid_from_pid $pid)" ]; then exec setsid "$(readlink -f "$0")" "$@" fi 

为什么我需要这个?

交互式 bash会话启动程序时,它将获得自己的新进程组。 但是,如果您的程序是从bash脚本(非交互式)调用的,则不是这种情况。 如果你的程序依赖于在这两种情况下的过程组所有者,你将需要这个。

如果将set -m on,则将在新的进程组中生成新进程,如果它们是后台进程,则不会忽略SIGINT和SIGQUIT。

 if [ $$ = $(ps -o pgid -hp $$) ]; then echo already a process group leader; else set -m $0 "$@" #optionally with & set +m fi 

set -m之后运行的程序的新进程组将作为终端的前台进程组接管,除非它们在后台运行。

如果实现支持“用户可移植性实用程序”, set -m显然是半标准的,POSIX要求。 在实践中,它在bashdashkshpdkshshyashzshposh没有它。

正如@Rob Davis在他的回答中指出的,设置进程组并不是你想要的shell。

相反,你想使用他们的过程控制机制。 这个答案涵盖了在Linux上执行此操作,并承担 。 简而言之:

 #! /bin/sh # Kill all opened jobs on exit. trap 'kill $(jobs -p)' EXIT 

这将杀死任何在backrground中打开的作业(例如用& )。