我有一个小的NodeJS脚本可以进行一些处理。根据需要处理的数据量,这可能需要几秒到几个小时。
我想做的是安排此命令在上一次尝试完成后每小时运行一次。我担心使用像cron之类的东西,因为我需要确保脚本的两个实例不会同时运行。
答案 0 :(得分:1)
如果你真的不喜欢 cron (或 at ),你可以使用一个简单的bash脚本:
#!/bin/bash
while true
do
#Do something
echo Invoke long-running node.js script
#Wait an hour
sleep 3600
done
(显而易见的)缺点是你必须以某种方式使它在后台运行(即通过 nohup 或屏幕)并添加适当的错误处理(你的脚本可能会失败,你仍然希望它在一小时内再次运行。)
更复杂的“自定义脚本”解决方案可能就是这样:
#!/bin/bash
#Settings
LAST_RUN_FILE=/var/run/lock/hourly.timestamp
FLOCK_LOCK_FILE=/var/run/lock/hourly.lock
FLOCK_FD=100
#Minimum time to wait between two job runs
MIN_DELAY=3600
#Welcome message, parameter check
if [ -z $1 ]
then
echo "Please specify the command (job) to run, as follows:"
echo "./hourly COMMAND"
exit 1
fi
echo "[$(date)] MIN_DELAY=$MIN_DELAY seconds, JOB=$@"
#Set an exclusive lock, or skip execution if it is already set
eval "exec $FLOCK_FD>$FLOCK_LOCK_FILE"
if ! flock -n $FLOCK_FD
then
echo "Lock is already set, skipping execution."
exit 0
fi
#Last run timestamp
if ! [ -e $LAST_RUN_FILE ]
then
echo "Timestamp file ($LAST_RUN_FILE) is missing, creating a new one."
echo 0 >$LAST_RUN_FILE
fi
#Compute delay, and wait
let DELAY="$MIN_DELAY-($(date +%s)-$(cat $LAST_RUN_FILE))"
if [ $DELAY -gt 0 ]
then
echo "Waiting for $DELAY seconds, before proceeding..."
sleep $DELAY
fi
#Proceed with an actual task
echo "[$(date)] Running the task..."
echo
"$@"
#Update the last run timestamp
echo
echo "Done, going to update the last run timestamp now."
date +%s >$LAST_RUN_FILE
这将做两件事:
设置一个独占执行锁(使用 flock ),这样就不会同时运行两个作业实例,无论你如何启动它们(手动或通过 cron 等);
如果上一个作业的完成时间少于 MIN_DELAY 秒前, 在再次运行工作之前,它将在剩余的时间内休眠;
现在,如果您安排运行此脚本,请使用 cron 每15分钟一次,例如:
* * * * * /home/myuser/hourly my_periodic_task and it's arguments
保证自上次作业完成后至少以 MIN_DELAY (一小时)的固定延迟执行,并且将跳过任何中间运行。
在最坏的情况下,它将在 MIN_DELAY + 15分钟内执行, (因为调度周期是离散的),但从不早于此。
其他非 cron 调度方法也应该起作用(即只是在循环中运行此脚本,或者重新调度并且每次运行 at )。
答案 1 :(得分:0)
您可以使用cron并将process.exit(0)
添加到节点脚本