SIGSTOP 在编写脚本时不起作用

SIGSTOP does not work when scripted

我有一个非常大的档案,必须逐个文件提取并进一步处理。我没有足够的内存来提取整个档案(无论是在 RAM 中还是在闪存中)- 因此我编写了一个小应用程序,它在每个提取文件后停止 (raise(SIGSTOP))。等效代码可能是此代码:

#include <stdio.h>
#include <signal.h>

int main() {
    printf("started.\n"); fflush(stdout);
    sleep(2);                             // extracting archive
    printf("stopping\n"); fflush(stdout);
    raise(SIGSTOP);                       // stopping
    printf("resume + done\n"); fflush(stdout);
    return 0;
}

当我在终端中执行它时,它工作正常:

$ gcc -o dosleep main.c
$ ./dosleep 
started.
stopping

[1]+  Stopped                 ./dosleep
$ fg
./dosleep
resume + done
$ 

但是从脚本调用方法时,命令永远不会 returns:

$ cat doit.sh 
#!/bin/sh
echo "STARTING"
./dosleep
echo "BACK"
$ ./doit.sh 
STARTING
started.
stopping

^C^C^C^C^C^C

为什么终端和脚本的行为如此不同?有没有办法改变这种行为?

谢谢,卡尔

作业控制在非交互式 shell 中默认关闭,但您可以显式启用它:

set -m

因此,如果我们修改您的脚本以在 shebang 上添加 set -m 行或 -m,如下所示:

#!/bin/bash -m
./start-delay
echo BACK

...然后 BACKstopping 之后发出。


引自 bash 手册页 section on set,强调:

-m Monitor mode. Job control is enabled. This option is on by default for interactive shells on systems that support it (see JOB CONTROL above). All processes run in a separate process group. When a background job completes, the shell prints a line containing its exit status.