如何在自己的进程组中启动 bash 脚本

如何在自己的进程组中启动 bash 脚本

我想从另一个 bash 脚本启动一个 bash 脚本,但在它自己的进程组中启动它,就像从终端运行它一样。

有几个类似的问题,但我找不到与我的示例相匹配的答案。

拿这两个脚本

$ cat main.sh 
#! /usr/bin/env bash

set -e

echo if this has been started in its own group the following will pass
ps -o ppid,pgid,command $$
ps -o pgid | grep $$
echo passed

$ cat wrapper.sh 
#! /usr/bin/env bash

set -e

./main.sh

当我main.sh单独运行时,终端将其放入自己的组中:

$ ./main.sh 
if this has been started in its own group the following will pass
 PPID  PGID COMMAND
20553  1276 bash ./main.sh
 1276
 1276
 1276
passed
$ echo $?
0

但是当我main.shwrapper.sh测试失败中运行时(如预期)

$ ./wrapper.sh 
if this has been started in its own group the following will pass
 PPID  PGID COMMAND
 2224  2224 bash ./main.sh
$ echo $?
1

但是,我必须在 or 中放入什么wrapper.sh才能main.sh使其main.sh在自己的组中运行,就像直接从终端运行时一样?

(如果它有所作为,我实际上希望运行./main.sh &wrapper.sh,但在这个实验的前台运行它更容易。)

(我使用的是ubuntu 18)

答案1

假设使用 Bash,直接的答案是在命令行上使用set -m, 或启用“监视模式”(作业控制):-m

从手册页:

-m 监控模式。作业控制已启用。对于支持它的系统上的交互式 shell,此选项默认处于启用状态(请参阅上面的作业控制)。所有进程都在单独的进程组中运行。当后台作业完成时,shell 会打印一行包含其退出状态的行。

$ bash -m wrapper.sh 
if this has been started in its own group the following will pass
 PPID  PGID COMMAND
12630 12631 bash ./main.sh
12631
12631
12631
passed

然而,问题对于“为什么”相当严格,并且可能有原因在非交互式 shell 中默认禁用监视模式,所以 YMMV。

答案2

考虑使用setsid.它为您的流程创建一个新会话,使其成为流程组领导者。

参见man 1 setsidman 2 setsid

相关内容