微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

linux – Bash:如何让脚本重新运行作为后台任务?

我正在编写一个旨在用作守护进程的Bash脚本.如果我的脚本的用户没有向脚本传递–sync选项,我希望脚本使用该选项将其自身重新运行为后台任务.这是我的代码(最后一部分是从this SO post被盗):

#!/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.为什么会这样,我该怎么做才能解决这个问题? (加分点:如果不创建子shell,有没有办法做到这一点?)

谢谢.

解决方法:

&正在应用于exec命令本身,所以exec foo&分叉一个新的异步子shell(或其等价物,见下文).子shell立即用foo替换自己.如果您希望父(也就是您的脚本)也终止,您需要使用exit命令显式地执行此操作.

这位高管可能不会在这里给你买任何东西. Bash非常聪明,实际上并没有为简单的后台命令启动子shell.所以它应该足够:

if $async; then
  nohup "${BASH_SOURCE[0]}" --sync "${args[@]}" 0<&- &> /dev/null &
  exit 0
fi

我不知道没有子shell的方法.但是当你编写shell脚本时,你会得到子shell.就个人而言,我只是使用一个简单的变量并使用if [[$async]]等测试它;而不是执行true或false,但由于这些也是bash内置的,它非常相同.在其他炮弹中,它们可以在子炮弹中运行.

现在我想到了,因为你无论如何都在重新处理异步执行中的所有选项,你可能只是在case语句中fork和exit,所以你根本不需要第二次检查:

case "$1" in
    --sync)
        nohup "${BASH_SOURCE[0]}" --sync "${args[@]}" 0<&- &> /dev/null &
        exit 0
        ;;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐