Linux 如何设置shell脚本的进程组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6549663/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set process group of a shell script
提问by Jacob
How to set process group of a shell script ? Also I want all the child process to be in the same process group
如何设置shell脚本的进程组?另外我希望所有子进程都在同一个进程组中
I expect something similar to setpgid() in C.
我期待类似于 C 中的 setpgid() 的东西。
回答by Rob Davis
I don't think Bourne, bash, or zsh will let you do that, but you could do it in perl using the built-in setpgrp
(note the slight name difference from POSIX). Pass zero as the PID to modify the group of the perl process itself:
我不认为 Bourne、bash 或 zsh 会让你这样做,但你可以使用内置的 perl 来做setpgrp
(注意与 POSIX 的轻微名称差异)。传递零作为 PID 来修改 perl 进程本身的组:
setpgrp(0, 12345) || die "$!"
You might think you could use perl from, say, bash to set the bash process's group (by passing $$
to a perl script, for example), but I don't think the perl process would be able to modify the group of a process that it didn't fork.
您可能认为您可以使用 bash 中的 perl 来设置 bash 进程的组($$
例如,通过传递给 perl 脚本),但我认为 perl 进程无法修改该进程的组它没有分叉。
Depending on what you're trying to do, the job control features in various shells may give you what you need, in a different way, like if you just want to detach from the terminal.
根据您尝试执行的操作,各种 shell 中的作业控制功能可能会以不同的方式为您提供所需的功能,例如您只想与终端分离。
UPDATE:I think it's strange that this answer has received a couple of down-votes without clear explanation why. My guess is that the downvoters are misunderstanding the question, which is asking how to changethe process group of the currentshell. Or perhaps they know how to do a setpgrp from the shell but are keeping the secret to themselves.
更新:我认为这个答案在没有明确解释原因的情况下收到了几个反对票,这很奇怪。我的猜测是downvoters误解了这个问题,即询问如何更改当前shell的进程组。或者也许他们知道如何从 shell 执行 setpgrp 但对自己保密。
回答by Gilles 'SO- stop being evil'
As PSkocik points out, it is possible to run a process in its own process group, in most shells, by activating job control (“monitor mode”).
正如PSkocik 指出的那样,在大多数 shell 中,通过激活作业控制(“监控模式”),可以在自己的进程组中运行进程。
(set -m; exec process_in_its_own_group)
Linux has a setsid
utility, which runs the command passed as argument in its own session(using the eponymous system call). This is stronger than running it in its own process groupà la setpgrp
, but that may be ok for your purpose.
Linux 有一个setsid
实用程序,它运行在其自己的会话中作为参数传递的命令(使用同名系统调用)。这比在自己的进程组à la 中运行它更强大setpgrp
,但这可能适合您的目的。
If you want to place the process in an existing group rather than in its own group (i.e. if you want the full power of setpgid
), there's no common shell utility. You have to use C/Perl/…
如果您想将进程放在现有组中而不是它自己的组中(即,如果您想要 的全部功能setpgid
),则没有通用的 shell 实用程序。你必须使用 C/ Perl/...
回答by NHDaly
As @Rob Davis pointed out in his answer, setting process group is not what you want for shells.
正如@Rob Davis 在他的回答中指出的那样,设置进程组不是您想要的 shell。
Instead you want to use their process control mechanisms. This answercovers doing this for sh
on linuxand borne. In short:
相反,您想使用他们的过程控制机制。该答案涵盖了sh
在linux和borne上执行此操作。简而言之:
#! /bin/sh
# Kill all opened jobs on exit.
trap 'kill $(jobs -p)' EXIT
This will kill any jobs opened in the backrground (e.g. with &
).
这将终止在后台打开的所有作业(例如使用&
)。
回答by vaab
I'll answer part of what I understand:
我就我理解的部分回答:
How to force current bash shell script to be it self process group:
如何强制当前的 bash shell 脚本成为它自己的进程组:
I put this in the beginning of my bash script:
我把它放在我的 bash 脚本的开头:
pgid_from_pid() {
local pid=
ps -o pgid= "$pid" 2>/dev/null | egrep -o "[0-9]+"
}
pid="$$"
if [ "$pid" != "$(pgid_from_pid $pid)" ]; then
exec setsid "$(readlink -f "if [ $$ = $(ps -o pgid -hp $$) ]; then
echo already a process group leader;
else
set -m
# First, obtain the current PGID, by parsing the output of "ps".
pgid=$(($(ps -o pgid= -p "$$")))
# Check if we're already the process group leader; if not, re-launch ourselves.
# Use setsid instead of set -m (...) to avoid having another subshell in between. This helps that the trap gets executed when the script is killed.
[ $$ -eq $pgid ] || exec setsid "${BASH_SOURCE[0]}" "$@"
# Kill any subshell processes when the script exits.
trap "kill -- -$pgid" EXIT
# Note: If the script only starts background jobs, and that's all you care about, you can replace all of the above with this simple trap:
#trap "jobs -p | xargs kill --" EXIT # Kill remaining jobs when the script exits.
"$@" #optionally with &
set +m
fi
")" "$@"
fi
Why do I would need this ?
为什么我需要这个?
When launching a program from an interactivebash session, it gets its own new process group. But this is not the case if your program is called from a bash script (non-interactive). If your program relies on being the process group owner in both condition you'll need this.
从交互式bash 会话启动程序时,它会获得自己的新进程组。但是,如果您的程序是从 bash 脚本(非交互式)调用的,则情况并非如此。如果您的程序在这两种情况下都依赖于进程组所有者,那么您将需要它。
回答by PSkocik
If you turn set -m
on, new processes will be spawned in a new process group, and if they're backgrounded, they won't have SIGINT and SIGQUIT ignored.
如果打开set -m
,新进程将在新进程组中生成,如果它们是后台进程,则不会忽略 SIGINT 和 SIGQUIT。
The new processes group of programs run after set -m
takes over as the foreground process group of the terminal, unless they're run in the background.
新进程组程序运行后set -m
接管作为终端的前台进程组,除非它们在后台运行。
The set -m
is apparently semi-standard, required by POSIX if the implementation supports "User Portability Utilities".
In practice it works on bash
, dash
, ksh
, pdksh
, sh
, yash
, and zsh
. posh
doesn't have it.
该set -m
显然是半标准,通过POSIX如果实现支持“用户可携性工具”要求。在实践中它的工作原理上bash
,dash
,ksh
,pdksh
,sh
,yash
,和zsh
。posh
没有它。
回答by Ingo Karkat
Here's a late synthesis, taken from several other good answers here, if your intention is to cleanup any spawned subshell processes (even if the script itself is not directly launched from an interactive shell, but from another process, and therefore doesn't automatically becomes its own process group leader), relaunching the current script as a new process group leader if necessary.
这是一个较晚的综合,取自这里的其他几个好的答案,如果您的目的是清理任何产生的子 shell 进程(即使脚本本身不是直接从交互式 shell 启动,而是从另一个进程启动,因此不会自动变为它自己的进程组负责人),如有必要,将当前脚本重新启动为新的进程组负责人。
##代码##