set -e和后台进程

9
在我的脚本中,我设置了set -e,以便在出现错误时停止处理。对于所有在前台运行的命令,它都表现良好,但我的一些命令必须在后台并行运行。不幸的是,如果后台进程失败,尽管有set -e标志,脚本也不会停止执行。
前台进程示例可行。
#!/bin/bash
set -e
ls -l no_file
sleep 100

带有后台进程的示例无法工作。

#!/bin/bash
set -e
ls -l no_file &
sleep 100

如何处理后台进程的失败?
1个回答

10

使用 & 异步启动命令总是返回退出状态 0。要获取命令的实际退出状态,请使用内置的 wait。以下是一个简单的例子:

$ (sleep 5; ls -l nofile) &
[1] 3831
$ echo $?
0
$ wait -n
ls: cannot access 'nofile': No such file or directory
[1]+  Exit 2                  ( sleep 5; ls --color=auto -l nofile )
$ echo $?
2

wait -n 等待 任何一个 子进程完成(这非常有用)。如果您想等待特定的进程,可以在启动它时捕获 PID——PID 存储在特殊变量 $! 中——然后根据 PID 等待:

$ (sleep 5; ls -l nofile) &
$ myjobpid=$!
$ # do some other stuff in parallel
$ wait ${myjobpid}
ls: cannot access 'nofile': No such file or directory
[1]+  Exit 2                  ( sleep 5; ls --color=auto -l nofile )

《Bash手册》中相关章节标题为“作业控制”


使用等待PID的解决方案正是我正在寻找的。谢谢。 - Marcin
我没有看到这个回答如何与原始问题中的 set -e 交互。 - user239558
@user239558:这个答案的第一句话是:“异步启动命令(使用&)总是返回退出状态0”。也就是说,它总是成功的,不会出错。实际问题在原帖的最后一句话:“如何处理后台进程的失败?” - AlexP
我认为答案应该澄清三件事情:waitwait -n之间的区别,当没有后台进程存在时调用waitwait -n的影响,以及处理后台进程的模式。 - user239558

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接