bash - bash 脚本中“jobs”命令的奇怪行为
问题描述
我对 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
如果您每次jobs
在该 shell 中再次运行时都看到“[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
对作业表的任何影响都仅限于子shell。家长没有意识到您已经看到“完成”消息。
因此,每次运行时[[ $(jobs) ]]
,它都会向您显示“Done”消息,从而表明该声明是正确的。
添加 ajobs &> /dev/null
将导致父级更新其自己的作业表,而不仅仅是子外壳的表,因此它将正确完成。
推荐阅读
- apache-camel - 使用 REST API 向 IBM MQ 生成消息。阿帕奇骆驼
- django - 在测试用例期间出现 mongodb 连接错误?
- kubernetes - 如何在 Kubernetes 中列出服务后面的流量的所有 Pod 的名称
- java - Springboot复选框值到控制器
- flutter - 带有大量无法理解的日志的 Flutter 升级问题(虽然没有害处)
- node.js - 如何将多个数据流从单个客户端发送到 tcp 服务器
- python - 无法为 python3 安装 PySide
- amazon-web-services - AWS Kendra 是否有单一 API?
- qt - UBUNTU 18.04 中 Qt5.11.1 的链接错误
- github - 如何在 GitHub 存储库中创建文件夹?