从bash脚本启动新进程组

时间:2015-06-10 13:53:59

标签: bash unix process signals freebsd

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

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

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

setsid /path/to/myscript
然而,我知道会话和进程组不一样。但是开始一个新的会议也解决了我的问题。

3 个答案:

答案 0 :(得分:6)

会话和小组不是一回事。让我们干净利落:

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

此外,当会话具有控制终端时,shell进程通常是会话负责人,指示哪个进程组是前台进程组(隐式地使其他组成为后台进程组)。组中的进程通常由线性管道放在那里。例如,ls -l | grep a | sort通常会创建一个新的流程组,其中lsgrepsort生效。

支持作业控制的shell(也需要内核和终端驱动程序的支持),就像bash一样,为每个被调用的命令创建一个新的进程组 - 如果你调用它来在后台运行(使用&表示法),该进程组不受终端控制,并且shell使其成为后台进程组(并且前台进程组仍然是shell)。

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

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

#!/bin/bash

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

这打印如下:

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

如您所见,execute.shpsgrep都在同一个流程组(PGID中的值)。

所以你想要的只是:

/path/to/myscript &

然后,您可以使用myscript检查ps -o pid,ppid,pgid,comm | grep myscript的流程组ID。要向群组发送信号,请将其发送给群组负责人(PGID是群组负责人的PID。发送到组的信号将传递到该组中的每个进程。

答案 1 :(得分:1)

使用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

答案 2 :(得分:0)

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

您可以在所有进程中使用通用名称。例如,对于以下所有过程,我们都有 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

生成所有它们(并根据需要):

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

当您想终止所有进程时,可以使用 pkill 命令(模式终止)或 killall -regexp 参数:

pkill my_proc_group_29387172

优点:)-您可以随时从任何脚本开始任意数量的进程。

缺点:(-如果无害的进程与您的模式具有相同的名称,则可以杀死它们。