【问题标题】:How to stop infinite loop in bash script gracefully?如何优雅地停止bash脚本中的无限循环?
【发布时间】:2012-06-26 08:11:03
【问题描述】:

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

当我不得不手动停止正在运行的脚本时,我想以正确的方式来做——让应用程序完成运行,下次不要进入循环。

您有什么想法,如何实现? 我想过传递参数,但我找不到如何将参数传递给正在运行的脚本。

【问题讨论】:

    标签: bash shell infinite-loop


    【解决方案1】:

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

    echo "My pid is: $$"
    finish=0
    trap 'finish=1' SIGUSR1
    
    while (( finish != 1 ))
    do
        stuff
        sleep 42
    done
    

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

    kill -SIGUSR1 pid
    

    其中pid 是脚本的进程ID。如果在睡眠期间发出信号,它将唤醒(睡眠一直到有信号出现为止)。

    【讨论】:

      【解决方案2】:

      您可以通过文件传递一些参数。在每次迭代中,您都可以阅读此文件并查看您的运行条件是否发生了变化。

      【讨论】:

        【解决方案3】:

        如果您无论如何都必须进行一些清理,则以下结构可能是合适的。如 cdarke 的答案所示使用 kill。

        #===============================================================
        #  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
        

        【讨论】:

          【解决方案4】:

          前面发布的陷阱解决方案适用于大型循环,但对于仅循环单个或几个命令的常见情况来说很麻烦。在这种情况下,我推荐以下解决方案:

          while whatever; do
              command || break
          done
          

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

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

          【讨论】:

            猜你喜欢
            • 2018-11-29
            • 1970-01-01
            • 1970-01-01
            • 2023-03-22
            • 1970-01-01
            • 2021-06-04
            • 1970-01-01
            • 2013-03-24
            • 1970-01-01
            相关资源
            最近更新 更多