我正在编写旨在用作守护程序的Bash脚本。如果我的脚本用户未将--sync
选项传递给脚本,则我希望脚本使用该选项作为后台任务重新运行。这是我的代码(此SO帖子的最后一部分被盗):
#!/usr/bin/env bash
args=("$@") # capture them here so we can use them if --sync's not passed
async=true
while [ $# -gt 0 ]
do
case "$1" in
--sync)
async=false
;;
# other options
esac
shift
done
# if --sync isn't passed, rerun the script as a background task
$async && exec nohup "${BASH_SOURCE[0]}" --sync "${args[@]}" 0<&- &> /dev/null &
由于某些原因,它似乎没有用。当我这样做bash -x myscript
(这有助于调试脚本)时,即使它$async
为true,它似乎仍会继续运行,我认为这不会发生,因为exec
通常会停止执行。
同样,如果我从终端运行以下命令:
exec nohup true 0<&- &> /dev/null &
即使使用,它也无法退出外壳exec
。为什么会这样,我应该怎么做才能解决?(加分点:是否可以在不创建子shell的情况下执行此操作?)
谢谢。
在&
被施加到所述exec
命令本身,所以exec foo &
派生一个新的异步子外壳(或与其等同的,见下文)。该subshell立即用替换foo
。如果您还希望父级(即脚本)终止,则需要使用exit
命令明确终止。
将exec
很可能不会在这里买你什么。Bash足够聪明,它实际上没有为简单的后台命令启动子shell。因此,这样做应该足够了:
if $async; then
nohup "${BASH_SOURCE[0]}" --sync "${args[@]}" 0<&- &> /dev/null &
exit 0
fi
我不知道没有子shell就能做到这一点。但是,当您编写shell脚本时,会得到子shell。就我个人而言,我只是使用一个简单的变量,并用类似的方法测试它,if [[ $async ]];
而不是执行true
or false
,但是由于它们也是bash内置函数,因此相当等效。在其他Shell中,它们可能在子Shell中运行。
现在我想到了,由于您仍然要在异步执行中重新处理所有选项case
,因此不妨在语句内进行分叉和退出操作,因此根本不需要进行第二次检查:
case "$1" in
--sync)
nohup "${BASH_SOURCE[0]}" --sync "${args[@]}" 0<&- &> /dev/null &
exit 0
;;
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句