编写脚本时SIGSTOP不起作用

问题描述 投票:0回答:1

我有一个非常庞大的存档,必须逐个文件提取并进一步处理。我没有足够的内存来提取整个存档(无论是在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
$ 

但是当从脚本调用该方法时,该命令永远不会返回:

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

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

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

谢谢,卡尔

shell kill raise
1个回答
1
投票

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

set -m

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

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

...然后BACKstopping之后发出。


引自bash手册页section on set,重点补充说:

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

© www.soinside.com 2019 - 2024. All rights reserved.