2016-10-27 5 views
0

Ich habe ein kleines NodeJS-Skript, das etwas verarbeitet. Abhängig von der Menge der Daten, die verarbeitet werden müssen, kann dies einige Sekunden bis Stunden dauern.Linux - Skript nach Ablauf der Zeit ausführen

Ich möchte, dass dieser Befehl jede Stunde nach dem letzten Versuch ausgeführt wird. Ich bin vorsichtig mit etwas wie Cron, weil ich sicherstellen muss, dass zwei Instanzen des Skripts nicht gleichzeitig ausgeführt werden.

+0

Verwenden Sie Cron in Kombination mit Dateisystemsperrung. Der Prozess prüft, ob eine Sperrdatei bereits existiert. Wenn dies der Fall ist, wird es beendet, wenn nicht, erstellt es eine und startet dann seine Verarbeitungsaufgabe. Wenn Sie fertig sind, wird die Sperrdatei wieder entfernt. Zusätzliche Punkte der Sperrdatei enthalten die Prozess-ID des Prozesses, der sie erstellt hat. Dies ermöglicht einen Bereinigungsjob, um abgestürzte Jobs zu entfernen. – arkascha

+1

Sie können cron + flock verwenden: siehe http://serverfault.com/questions/82857/prevent-duplicate-cron-jobs-running – zeppelin

+0

Verwenden Sie 'at' am Ende Ihres Skripts, um den nächsten Lauf zu planen. – Eric

Antwort

1

Wenn Sie wirklich nicht cron (oder bei) Sie nur einen einfachen Bash-Skript verwenden können, mögen:

#!/bin/bash 
while true 
do 
    #Do something 
    echo Invoke long-running node.js script 

    #Wait an hour 
    sleep 3600 
done 

Der (offensichtliche) Nachteil ist, dass Sie es irgendwie im Hintergrund laufen lassen müssen (zB über nohup oder Bildschirm) und fügen Sie eine ordnungsgemäße Fehlerbehandlung hinzu (wobei Sie s cript kann fehlschlagen, und Sie möchten immer noch, dass es in einer Stunde wieder läuft).

Etwas aufwändigere "benutzerdefinierten Skript" Lösung könnte so sein:

#!/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, [email protected]" 

#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 
"[email protected]" 

#Update the last run timestamp 
echo 
echo "Done, going to update the last run timestamp now." 
date +%s >$LAST_RUN_FILE 

Dieses 2 Dinge tun:

  • eine exklusive Ausführung Schloss Set (mit Herde), so dass keine zwei Instanzen des Jobs zur gleichen Zeit ausgeführt werden, unabhängig davon, wie Sie sie starten (manuell oder über cron usw.);

  • Wenn der letzte Auftrag abgeschlossen wurde weniger als MIN_DELAY Sekunden vor, es für die verbleibende Zeit schlafen, bevor die Arbeit wieder zum Laufen;

Nun, wenn Sie dieses Skript planen zu laufen, sagen alle 15 Minuten mit cron, wie folgt aus:

* * * * * /home/myuser/hourly my_periodic_task and it's arguments 

Es wird garantiert mit der festen Verzögerung von mindestens auszuführen MIN_DELAY (eine Stunde) seit dem letzten abgeschlossenen Auftrag, und Zwischenläufe werden übersprungen.

Im schlimmsten Fall wird es in MIN_DELAY + 15 Minuten (wie die Planungsperiode ist diskret), aber nie früher als ausführen.

Andere nicht-cron Scheduling-Verfahren sollten auch funktionieren (d.h. nur das Skript in einer Schleife ausgeführt wird, oder Neuplanung und jeden Durchlauf mit bei).

0

Sie können einen cron verwenden und process.exit(0) zu Ihrem Knoten Skript hinzufügen

Verwandte Themen