我基本上想在一个新的进程组中运行一个脚本(它调用更多的脚本),这样我就可以向脚本调用的所有进程发送信号。在Linux中,我发现setsid可以帮助我做到这一点,但这在FreeBSD上不可用。setsid的语法(由util-linux-ng提供)。
setsid /path/to/myscript
然而,我了解到会话和进程组是不一样的。但是开始一个新的会话也解决了我的问题。
xriantvc1#
会议和小组不是一回事。让我们把事情弄清楚:一个会话由一个或多个进程组组成,可以有一个控制终端。当会话具有控制终端时,会话在任何时刻都具有恰好一个前台进程组和一个或多个后台进程组。在这种情况下,前台进程组中的每个进程都可以看到所有终端生成的信号和输入。此外,当会话具有控制终端时, shell 进程通常是会话领导者,指示哪个进程组是前台进程组(隐含地使其他组成为后台进程组)。组中的进程通常通过线性管道放置在那里。例如,ls -l | grep a | sort通常会创建一个新的进程组,其中存在ls、grep和sort。支持作业控制的Shell(这也需要内核和终端驱动程序的支持),就像bash的情况一样,为每个被调用的命令创建一个新的进程组--如果您调用它是为了在后台运行(用&表示法),该进程组不被给予终端的控制,并且 shell 使其成为后台进程组(并且前台进程组仍然是 shell )。因此,正如您所看到的,在这种情况下,您几乎肯定不想创建会话。创建会话的一个典型情况是,您正在守护进程,但除此之外,创建新会话通常没有太多用处。您可以将该脚本作为后台作业运行,正如我提到的,这将创建一个新的进程组。由于fork()继承了进程组ID,因此脚本执行的每个进程都将位于同一个组中。例如,考虑这个简单的脚本:
ls -l | grep a | sort
ls
grep
sort
&
fork()
#!/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.sh、ps和grep都在同一个进程组(PGID中的值)上。所以你想要的是:
execute.sh
ps
PGID
/path/to/myscript &
然后您可以使用ps -o pid,ppid,pgid,comm | grep myscript检查myscript的进程组ID。要向组发送信号,请使用kill和进程组ID的 * 负数 *(PGID是组领导者的PID)。发送到一个组的信号被传递到该组中的每个进程。在上面的示例中,要将SIGTERM发送到由execute.sh启动的每个进程,包括脚本本身,您将使用kill -- -12343。(注意,向整个组发送信号不同于仅向组长发送信号:kill 12343和kill -- -12343是不同的!)
ps -o pid,ppid,pgid,comm | grep myscript
myscript
kill
PID
SIGTERM
kill -- -12343
kill 12343
b09cbbtk2#
在FreeBSD中,你可以尝试使用script命令,它将在内部执行setsid命令。
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
ycl3bljg3#
这不是确切的答案,而是基于名称的替代方法。您可以为所有进程提供一个公共的名称部分。例如,我们为以下所有进程设置了my_proc_group_29387172part:
-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命令(模式kill)或killall并带**--regexp**参数:
pkill my_proc_group_29387172
好处:)-您可以在任何时间(或任何一天)从任何脚本启动任意多个进程。缺点:(-如果进程的名字与你的模式有共同的部分,你可以杀死它们。
3条答案
按热度按时间xriantvc1#
会议和小组不是一回事。让我们把事情弄清楚:
一个会话由一个或多个进程组组成,可以有一个控制终端。当会话具有控制终端时,会话在任何时刻都具有恰好一个前台进程组和一个或多个后台进程组。在这种情况下,前台进程组中的每个进程都可以看到所有终端生成的信号和输入。
此外,当会话具有控制终端时, shell 进程通常是会话领导者,指示哪个进程组是前台进程组(隐含地使其他组成为后台进程组)。组中的进程通常通过线性管道放置在那里。例如,
ls -l | grep a | sort
通常会创建一个新的进程组,其中存在ls
、grep
和sort
。支持作业控制的Shell(这也需要内核和终端驱动程序的支持),就像bash的情况一样,为每个被调用的命令创建一个新的进程组--如果您调用它是为了在后台运行(用
&
表示法),该进程组不被给予终端的控制,并且 shell 使其成为后台进程组(并且前台进程组仍然是 shell )。因此,正如您所看到的,在这种情况下,您几乎肯定不想创建会话。创建会话的一个典型情况是,您正在守护进程,但除此之外,创建新会话通常没有太多用处。
您可以将该脚本作为后台作业运行,正如我提到的,这将创建一个新的进程组。由于
fork()
继承了进程组ID,因此脚本执行的每个进程都将位于同一个组中。例如,考虑这个简单的脚本:这将打印如下内容:
正如您所看到的,
execute.sh
、ps
和grep
都在同一个进程组(PGID
中的值)上。所以你想要的是:
然后您可以使用
ps -o pid,ppid,pgid,comm | grep myscript
检查myscript
的进程组ID。要向组发送信号,请使用kill
和进程组ID的 * 负数 *(PGID
是组领导者的PID
)。发送到一个组的信号被传递到该组中的每个进程。在上面的示例中,要将SIGTERM
发送到由execute.sh
启动的每个进程,包括脚本本身,您将使用kill -- -12343
。(注意,向整个组发送信号不同于仅向组长发送信号:kill 12343
和kill -- -12343
是不同的!)b09cbbtk2#
在FreeBSD中,你可以尝试使用
script
命令,它将在内部执行setsid
命令。ycl3bljg3#
这不是确切的答案,而是基于名称的替代方法。
您可以为所有进程提供一个公共的名称部分。例如,我们为以下所有进程设置了my_proc_group_29387172part:
生成所有这些(以及您想要的数量):
当你想杀死所有进程时,可以使用pkill命令(模式kill)或killall并带**--regexp**参数:
好处:)-您可以在任何时间(或任何一天)从任何脚本启动任意多个进程。
缺点:(-如果进程的名字与你的模式有共同的部分,你可以杀死它们。