【发布时间】:2012-06-26 08:11:03
【问题描述】:
我需要每隔 X 秒运行一次应用程序,因此,只要 cron 不能以这种方式使用秒数,我就编写了一个带有无限循环的 bash 脚本,其中包含 X 秒睡眠。
当我不得不手动停止正在运行的脚本时,我想以正确的方式来做——让应用程序完成运行,下次不要进入循环。
您有什么想法,如何实现? 我想过传递参数,但我找不到如何将参数传递给正在运行的脚本。
【问题讨论】:
标签: bash shell infinite-loop
我需要每隔 X 秒运行一次应用程序,因此,只要 cron 不能以这种方式使用秒数,我就编写了一个带有无限循环的 bash 脚本,其中包含 X 秒睡眠。
当我不得不手动停止正在运行的脚本时,我想以正确的方式来做——让应用程序完成运行,下次不要进入循环。
您有什么想法,如何实现? 我想过传递参数,但我找不到如何将参数传递给正在运行的脚本。
【问题讨论】:
标签: bash shell infinite-loop
你可以捕获一个信号,比如 SIGUSR1:
echo "My pid is: $$"
finish=0
trap 'finish=1' SIGUSR1
while (( finish != 1 ))
do
stuff
sleep 42
done
然后,当你想在下一次迭代中退出循环时:
kill -SIGUSR1 pid
其中pid 是脚本的进程ID。如果在睡眠期间发出信号,它将唤醒(睡眠一直到有信号出现为止)。
【讨论】:
您可以通过文件传递一些参数。在每次迭代中,您都可以阅读此文件并查看您的运行条件是否发生了变化。
【讨论】:
如果您无论如何都必须进行一些清理,则以下结构可能是合适的。如 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
【讨论】:
前面发布的陷阱解决方案适用于大型循环,但对于仅循环单个或几个命令的常见情况来说很麻烦。在这种情况下,我推荐以下解决方案:
while whatever; do
command || break
done
如果命令有一个非零退出代码,这将退出循环,如果它被中断就会发生。因此,除非command 处理SIGINT,否则按 ctrl-C 将停止当前命令并退出循环。
编辑:仔细阅读您的问题后,我发现您希望当前命令继续执行。在这种情况下,此解决方案不适用。
【讨论】: