我对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的表,因此它将正确完成。