我对bash脚本比较陌生,对一些我觉得奇怪的东西有疑问。
我将此作为bash脚本的一部分编写:

sleep 10 &
while [[ $(jobs) ]]
do
        sleep 1
        echo test
        jobs &> /dev/null
done

为什么“工作”行是必要的?如果我不去管它,它将永远运行。
但如果我跑:
sleep 10 & while [[ $(jobs) ]]; do sleep 1; echo test; done

直接从bash开始工作。我已经在多个系统上试过了。

最佳答案

有趣的观察。
这是因为jobs的一个功能是在作业终止时显示状态,但前提是尚未通知您:

$ true & sleep 1; jobs;
[1] 18687
[1]+  Done                    true

如果你每次在shell中再次运行jobs时都看到“[1]+Done”,那将是烦人和无用的。因此,jobs还将清理作业表,以便第二个jobs不会再次通知您:
$ true & sleep 1; jobs; echo "Here's the output the second time:"; jobs
[1] 18694
[1]+  Done                    true
Here's the output the second time:
(nothing)

现在,当您运行$(jobs)时,您将创建一个子shell。由于Unix编程模型是如何工作的,$(jobs)是通过分叉当前进程(子shell)的相同副本来实现的,stdout连接到管道,让该进程运行jobs,然后从管道读取结果。
这意味着jobs对jobs表的任何影响都仅限于子shell。家长没有意识到你已经看到了“完成”的信息。
因此,每次运行[[ $(jobs) ]],它都会向您显示“Done”消息,以便语句为true。
添加jobs &> /dev/null将导致父进程更新自己的作业表,而不仅仅是子shell的表,因此它将正确完成。

10-04 22:47
查看更多