如何解决Bash脚本在子进程输出后没有结束
我有一个launcher.sh
脚本,应该在启动另一个可执行文件然后退出之前做一些工作。启动器退出后,另一个可执行文件应该仍然存在。
有时,launcher.sh
不会结束,即使其执行达到了exit 0
点。我使用以下脚本重现了此行为:
#!/bin/bash
function service() {
echo stdout $0
echo stderr $0 >&2
while true; do
sleep 3600
done
}
exec > >(awk '{ print strftime("[%FT%T]"),$0; fflush(); }') 2>&1
echo "$0 started"
service&
echo "$0 ended"
exit 0
输出以下内容:
[2020-10-07T16:39:18] ./launcher.sh started
[2020-10-07T16:39:18] ./launcher.sh ended
[2020-10-07T16:39:18] stdout ./launcher.sh
[2020-10-07T16:39:18] stderr ./launcher.sh
因此,我希望主launcher.sh
进程消失,而另一个sleep
正在运行。但是实际上,主要的仍然在这里,等待更多输出输出到awk
。
17359 pts/0 S 0:00 /bin/bash ./launcher.sh
17361 pts/0 S 0:00 \_ sleep 3600
17358 pts/0 S 0:00 /bin/bash ./launcher.sh
17360 pts/0 S 0:00 \_ awk { print strftime("[%FT%T]"),$0; fflush(); }
我注意到这种现象仅是因为service
输出了一些文本。 service
没有输出任何内容时,主launcher.sh
进程确实退出,而子进程仍然存活。
有没有办法使主launcher.sh
进程退出(同时仍然记录service
的最终早期输出)?
解决方法
运行exec > >(awk '{ print strftime("[%FT%T]"),$0; fflush(); }') 2>&1
时,这会将stdout和stderr更改为指向为过程替换启动的子外壳-不仅用于脚本,而且用于进程,脚本也将启动。其中包括service
。
在重定向命令中添加额外的exec
,以消除保留启动awk的子shell(awk
本身正在直接读取stdin;父shell没有用处):
exec > >(exec awk '{ print strftime("[%FT%T]"),$0; fflush(); }') 2>&1
...并且如果您不希望service
写入运行awk的进程替换中,最简单的方法是仅重定向stdout和stderr(如果意图真的很好,请重定向stdin)以将其作为服务来运行)
service </dev/null >/dev/null 2>&1 &
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。