如何防止 exec 保持脚本运行?

如何防止 exec 保持脚本运行?

exec这样使用:

#!/bin/bash
exec > >(tee /tmp/mylog.log) 2>&1
bash -c 'sleep 12312' &

我希望命令的输出位于日志文件中,然后我想启动一个长时间运行的脚本,并完全分离它,而不对其输出执行任何操作。

但我注意到,使用 exec 运行脚本将输出重定向到文件会使其继续与长时间运行的脚本一起运行。例如,将上面的脚本保存到一个文件中/tmp/start.sh,运行它,ps aux会显示/bin/bash /tmp/start.sh仍在运行!

但是,如果我删除 exec 行,它就会按预期工作。

那么如何“分离”exec stdout 重定向并使脚本在结束后立即终止?

答案1

持续运行的 bash 进程是 的父进程tee,而不是原始脚本。您可以通过添加显示进程 ID 的跟踪来看到这一点:

#!/bin/bash
echo original=$$
exec > >(echo substitution=$BASHPID; tee /tmp/mylog.log) 2>&1
bash -c 'echo sleeper=$$; sleep 12312' &

这使得出现一个额外的 bash 进程,它是sleep.要摆脱这些 bash 进程,请exec自始至终使用:

#!/bin/bash
echo original=$$
exec > >(echo substitution=$BASHPID; exec tee /tmp/mylog.log) 2>&1
bash -c 'echo sleeper=$$; exec sleep 12312' &

我在 bash 4.3 上测试了这个答案。 bash 的未来版本可能会变得更加智能,而不是尾部调用(如 ksh)。

相关内容