从 bash 脚本启动一个新的进程组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30758424/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 13:10:05  来源:igfitidea点击:

starting a new process group from bash script

bashunixprocesssignalsfreebsd

提问by Thirupathi Thangavel

I basically want to run a script (which calls more scripts) in a new process group so that I can send signal to all the processes called by the script.

我基本上想在新的进程组中运行一个脚本(调用更多脚本),以便我可以向脚本调用的所有进程发送信号。

In Linux, I found out setsid helps me in doing that, but this is not available on FreeBSD.

在 Linux 中,我发现 setid 可以帮助我做到这一点,但在 FreeBSD 上不可用。

Syntax for setsid (provided by util-linux-ng).

setsid 的语法(由 util-linux-ng 提供)。

setsid /path/to/myscript

I, however learnt that session and process group are not the same. But starting a new session also solves my problem.

然而,我了解到会话和进程组不一样。但是开始一个新的会话也解决了我的问题。

回答by Filipe Gon?alves

Sessions and groups are not the same thing. Let's make things clean:

会话和组不是一回事。让我们把事情弄干净:

A session consists of one or more process groups, and can have a controlling terminal. When the session has a controlling terminal, the session has, at any moment, exactly one foreground process group and one or more background process groups. In such a scenario, all terminal-generated signals and input is seen by every process in the foreground process group.

一个会话由一个或多个进程组组成,并且可以有一个控制终端。当会话有一个控制终端时,该会话在任何时候都有一个前台进程组和一个或多个后台进程组。在这种情况下,前台进程组中的每个进程都可以看到所有终端生成的信号和输入。

Also, when a session has a controlling terminal, the shell process is usually the session leader, dictating which process group is the foreground process group (implicitly making the other groups background process groups). Processes in a group are usually put there by a linear pipeline. For example, ls -l | grep a | sortwill typically create a new process group where ls, grepand sortlive.

此外,当会话具有控制终端时,shell 进程通常是会话领导者,决定哪个进程组是前台进程组(暗示其他组成为后台进程组)。组中的进程通常通过线性管道放置在那里。例如,ls -l | grep a | sort通常会创建一个新的过程,其中组lsgrepsort现场。

Shells that support job control (which also requires support by the kernel and the terminal driver), as in the case of bash, create a new process group for each command invoked -- and if you invoke it to run in the background (with the &notation), that process group is not given the control of the terminal, and the shell makes it a background process group (and the foreground process group remains the shell).

支持作业控制的 Shell(也需要内核和终端驱动程序的支持),就像 bash 一样,为每个调用的命令创建一个新的进程组——如果你调用它在后台运行(使用&表示法),该进程组未获得终端的控制权,并且外壳将其设为后台进程组(而前台进程组仍然是外壳)。

So, as you can see, you almost certainly don't want to create a session in this case. A typical situation where you'd want to create a session is if you were daemonizing a process, but other than that, there is usually not much use in creating a new session.

因此,如您所见,您几乎肯定不想在这种情况下创建会话。您想要创建会话的典型情况是,如果您正在守护进程,但除此之外,创建新会话通常没有太大用处。

You can run the script as a background job, as I mentioned, this will create a new process group. Since fork()inherits the process group ID, every process executed by the script will be in the same group. For example, consider this simple script:

您可以将脚本作为后台作业运行,正如我所提到的,这将创建一个新的进程组。由于fork()继承了进程组ID,脚本执行的每个进程都会在同一个组中。例如,考虑这个简单的脚本:

#!/bin/bash

ps -o pid,ppid,pgid,comm | grep ".*"

This prints something like:

这会打印如下内容:

  PID  PPID  PGID COMMAND
11888 11885 11888 bash
12343 11888 12343 execute.sh
12344 12343 12343 ps
12345 12343 12343 grep

As you can see, execute.sh, psand grepare all on the same process group (the value in PGID).

正如你所看到的,execute.shps并且grep都在同一进程群(中值PGID)。

So all you want is:

所以你想要的只是:

/path/to/myscript &

Then you can check the process group ID of myscriptwith ps -o pid,ppid,pgid,comm | grep myscript. To send a signal to the group, send it to the group leader (PGIDis the PIDof the leader of the group). A signal sent to a group is delivered to every process in that group.

然后你可以检查myscriptwith的进程组 ID ps -o pid,ppid,pgid,comm | grep myscript。要向组发送信号,请将其发送给组长(PGIDPID组长的 )。发送到组的信号会传递到该组中的每个进程。

回答by taroj

Using FreeBSD you may try using the scriptcommand that will internally execute the setsidcommand.

使用 FreeBSD,您可以尝试使用script将在内部执行该setsid命令的命令。

stty -echo -onlcr   # avoid added \r in output
script -q /dev/null /path/to/myscript
stty echo onlcr
# sync  # ... if terminal prompt does not return

回答by DenisKolodin

This is not exactly answer, but is an alternative approach based on names.

这不是确切的答案,而是基于名称的替代方法。

You can have a common part of name for all process. For example we have my_proc_group_29387172part for all the following processes:

您可以为所有进程使用名称的公共部分。例如,我们有my_proc_group_29387172部分用于以下所有进程:

-rwxrwxr-x.   my_proc_group_29387172_microservice_1
-rwxrwxr-x.   my_proc_group_29387172_microservice_2
-rwxrwxr-x.   my_proc_group_29387172_data_dumper

Spawn all of them (and as much as you want):

生成所有这些(以及您想要的数量):

ADDR=1 ./my_proc_group_29387172_microservice_1
ADDR=2 ./my_proc_group_29387172_microservice_1
ADDR=3 ./my_proc_group_29387172_microservice_2
./my_proc_group_29387172_data_dumper

When you want to kill all processes you can use pkillcommand (pattern kill) or killallwith --regexp parameter:

当您想杀死所有进程时,您可以使用pkill命令(模式杀死)或带有--regexp参数的killall

pkill my_proc_group_29387172

Benefit :)- you can start as many process as you want at any time (or any day) from any script.

好处 :)- 您可以在任何时间(或任何一天)从任何脚本启动任意数量的进程。

Drawback :(- you can kill innocent processes if they has common part of name with your pattern.

缺点 :(- 如果无辜的进程与您的模式具有共同的名称部分,您可以杀死无辜的进程。