我想从另一个 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.sh
从wrapper.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 setsid
和man 2 setsid
。