Cron-Skript wird mehrmals ausgeführt

Cron-Skript wird mehrmals ausgeführt

Wir haben ein Skript, mit dem einige Verzeichnisse mit einem USB-Laufwerk synchronisiert werden. Es ist so eingestellt, dass es einmal täglich ausgeführt wird, dauert aber oft länger.

Um sicherzustellen, dass nicht mehrere Kopien des Skripts gleichzeitig ausgeführt werden, überprüfen wir die Liste der Prozesse und beenden das Skript sofort, wenn es vorhanden ist.

#!/bin/bash

#check if we are already running
running=$(ps aux | /usr/bin/grep -i "usb_sync" | /usr/bin/grep -v grep | /usr/bin/grep -c bash)
echo "usb_sync $running" >/opt/local/backup/usb_sync_log
#If we are, the quit
if [ $running -gt 1 ] ; then
  exit 0
fi

Das Problem ist, dass diese Prüfung einwandfrei funktioniert, wenn sie über sudo und manuellen Aufruf über die CLI ausgeführt wird. Wenn sie jedoch über cron ausgeführt wird, wird sie trotzdem gestartet. Ich habe ein paar verschiedene Varianten ausprobiert, aber sie scheinen alle zu funktionieren.

Dies ist auf FreeNAS 11.2.

Antwort1

Eine pidDatei ist ein gängiger Ansatz, um die mehrfache Ausführung eines Skripts zu verhindern. Sie kann folgendermaßen verwendet werden:

#!/bin/bash

PIDFILE=/home/vagrant/forever.pid
if [ -f $PIDFILE ]
then
  PID=$(cat $PIDFILE)
  ps -p $PID > /dev/null 2>&1
  if [ $? -eq 0 ]
  then
    echo "Process already running"
    exit 1
  else
    ## Process not found assume not running
    echo $$ > $PIDFILE
    if [ $? -ne 0 ]
    then
      echo "Could not create PID file"
      exit 1
    fi
  fi
else
  echo $$ > $PIDFILE
  if [ $? -ne 0 ]
  then
    echo "Could not create PID file"
    exit 1
  fi
fi

sleep 25d
rm $PIDFILE

Wo sleep 25dist der eigentliche Befehl, der ausgeführt werden soll? Ich empfehle, dies zu lesenBlogeintragfür eine ausführliche Erklärung der verschiedenen Methoden zur Behandlung dieses Problems. Das obige Skript stammt von dort.

Die in der Cron-Datei festgelegten Zugriffsrechte des Benutzers zum Ausführen des Skripts sollten überprüft werden. Das aktuelle Skript kann auch einfach nicht erkennen, ob das Skript bereits ausgeführt wird, da die Zugriffsrechte nicht ausreichen. In jedem Fall scheint die Verwendung einer PID-Datei eine bessere und weniger fehleranfällige Lösung zur Behebung dieses Problems zu sein.

Antwort2

Das geht auch viel einfacher. Erstellen Sie eine Flag-Datei. Am Anfang Ihres Skripts können Sie Folgendes verwenden:

    ## Basic config
SCRIPTNAME=$(basename "$0")
RUNFILE="${SCRIPTNAME}.run"
# 25h in seconds adjust to your needs.
MAX_AGE=90000


    # check for running process
    if [ -f "$RUNFILE" ]; then
      echo "process still running - exit"
      if [ $(( $(date +%s) - $(date +%s --reference $RUNFILE) )) -gt ${MAX_AGE} ]; then
         rm $RUNFILE;
      else 
         exit
      fi
    fi
    touch $RUNFILE

<your code>

rm ${RUNFILE}

Der Inhalt der Runfile könnte die PID des laufenden Prozesses sein. Dies wäre einfacher zu analysieren, wenn ein Prozess läuft.

Anstatt

touch ${RUNFILE}

verwenden

echo $$ >${RUNFILE}

verwandte Informationen