如何优雅地停止bash脚本中的无限循环?

时间:2012-06-26 08:11:04

标签: bash shell infinite-loop

我需要每隔X秒运行一次应用程序,因此,就cron不能以秒的方式工作,我写了一个带有无限循环的bash脚本,其中有X秒睡眠。

当我必须手动停止正在运行的脚本时,我想以正确的方式执行它 - 让应用程序完成正常运行,并且不要再次进入循环。

您有什么想法,如何实现这一目标? 我考虑过传递参数,但是我找不到如何将参数传递给运行脚本。

4 个答案:

答案 0 :(得分:24)

你可以捕获一个信号,比如SIGUSR1:

echo "My pid is: $$"
finish=0
trap 'finish=1' SIGUSR1

while (( finish != 1 ))
do
    stuff
    sleep 42
done

然后,当你想在下一次迭代时退出循环:

kill -SIGUSR1 pid

其中pid是脚本的进程ID。如果在睡眠期间信号升高,它将被唤醒(睡眠休眠直到出现任何信号)。

答案 1 :(得分:2)

您可以通过文件传递一些参数。在每次迭代中,您可以阅读此文件,看看您的运行条件是否已更改。

答案 2 :(得分:1)

如果你不得不进行一些清理,以下结构可能是合适的。使用kill,如cdarke的回答所示。

#===============================================================
#  FUNCTION DEFINITIONS
#===============================================================
# . . .

#===  FUNCTION  ================================================
#          NAME:  cleanup
#   DESCRIPTION:  
#===============================================================
cleanup ()
{
  # wait for active children, remove empty logfile, ..., exit
  exit 0
} # ----------  end of function cleanup  ----------

#===============================================================
#   TRAPS
#===============================================================
trap  cleanup SIGUSR1

#===============================================================
#   MAIN SCRIPT
#===============================================================
echo -e "Script '$0' / PID ${$}"

while : ; do                                # infinite loop
  # . . .
  sleep 10
done
# . . .

#===============================================================
#   STATISTICS / CLEANUP
#===============================================================
cleanup

答案 3 :(得分:0)

之前发布的陷阱解决方案适用于大型循环,但对于只是循环一个或几个命令的常见情况很麻烦。在这种情况下,我建议采用以下解决方案:

while whatever; do
    command || break
done

如果命令具有非零退出代码,这将退出循环,如果它被中断则会发生。因此,除非command处理SIGINT,否则按ctrl-C将停止当前命令并退出循环。

编辑:在更仔细地阅读您的问题之后,我看到您希望当前命令继续执行。在这种情况下,此解决方案不适用。