Linux - 在时间段到期后运行脚本

时间:2016-10-27 21:34:37

标签: node.js linux bash scripting

我有一个小的NodeJS脚本可以进行一些处理。根据需要处理的数据量,这可能需要几秒到几个小时。

我想做的是安排此命令在上一次尝试完成后每小时运行一次。我担心使用像cron之类的东西,因为我需要确保脚本的两个实例不会同时运行。

2 个答案:

答案 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)添加到节点脚本