
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 pid
Datei 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 25d
ist 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}