it-swarm.com.de

Führen Sie cron job nur aus, wenn es noch nicht läuft

Ich versuche also, einen Cron-Job als eine Art Watchdog für einen von mir erstellten Daemon einzurichten. Wenn der Dämon fehlerhaft ist und ausfällt, möchte ich, dass der Cron-Job ihn regelmäßig neu startet. Ich bin mir nicht sicher, wie dies möglich ist, aber ich habe ein paar Cron-Tutorials durchgelesen und konnte nichts finden, was ich tun könnte suche ...

Mein Daemon wird über ein Shell-Skript gestartet, daher suche ich nur nach einer Möglichkeit, einen Cron-Job NUR dann auszuführen, wenn der vorherige Lauf dieses Jobs noch nicht ausgeführt wird.

Ich habe diesen Beitrag gefunden , der eine Lösung für das bietet, was ich mit Sperrdateien zu tun versuche. Ich bin nicht sicher, ob es einen besseren Weg gibt, dies zu tun ...

Danke für Ihre Hilfe.

115
LorenVS

Ich mache das für ein Print-Spooler-Programm, das ich geschrieben habe, es ist nur ein Shell-Skript:

#!/bin/sh
if ps -ef | grep -v grep | grep doctype.php ; then
        exit 0
else
        /home/user/bin/doctype.php >> /home/user/bin/spooler.log &
        #mailing program
        /home/user/bin/simplemail.php "Print spooler was not running...  Restarted." 
        exit 0
fi

Es läuft alle zwei Minuten und ist sehr effektiv. Ich erhalte eine E-Mail mit speziellen Informationen, wenn der Prozess aus irgendeinem Grund nicht ausgeführt wird.

110
jjclarkson

Verwenden Sie flock. Es ist neu. Es ist besser.

Jetzt müssen Sie den Code nicht mehr selbst schreiben. Weitere Gründe finden Sie hier: https://serverfault.com/a/8286

/usr/bin/flock -n /tmp/my.lockfile /usr/local/bin/my_script
95
Jess

Wie bereits erwähnt, ist das Schreiben und Überprüfen einer PID-Datei eine gute Lösung. Hier ist meine Bash-Implementierung:

#!/bin/bash

mkdir -p "$HOME/tmp"
PIDFILE="$HOME/tmp/myprogram.pid"

if [ -e "${PIDFILE}" ] && (ps -u $(whoami) -opid= |
                           grep -P "^\s*$(cat ${PIDFILE})$" &> /dev/null); then
  echo "Already running."
  exit 99
fi

/path/to/myprogram > $HOME/tmp/myprogram.log &

echo $! > "${PIDFILE}"
chmod 644 "${PIDFILE}"
58
rsanden

Versuche es nicht mit cron. Lassen Sie cron ein Skript ausführen, und lassen Sie es dann entscheiden, ob das Programm ausgeführt wird, und starten Sie es gegebenenfalls (beachten Sie, dass Sie Ruby oder Python) verwenden können = oder deine Lieblingsskriptsprache, um dies zu tun)

22
Earlz

Es ist überraschend, dass niemand von Run-One sprach. Ich habe mein Problem damit gelöst.

 apt-get install run-one

dann füge hinzu run-one vor Ihrem Crontab-Skript

*/20 * * * * * run-one python /script/to/run/awesome.py

Check out this askubuntu SE antworten. Dort finden Sie auch einen Link zu detaillierten Informationen.

18
Bedi Egilmez

Sie können es auch als Einzeiler direkt in Ihrer Crontab machen:

* * * * * [ `ps -ef|grep -v grep|grep <command>` -eq 0 ] && <command>
10
quezacoatl

Als Folge der Antwort von Earlz benötigen Sie ein Wrapper-Skript, das beim Start eine Datei mit dem Namen $ PID.running erstellt und beim Ende löscht. Das Wrapper-Skript ruft das Skript auf, das Sie ausführen möchten. Der Wrapper ist für den Fall erforderlich, dass das Zielskript fehlschlägt oder ein Fehler auftritt. Die PID-Datei wird gelöscht.

5
Byron Whitlock

Die Art und Weise, wie ich es beim Ausführen von PHP-Skripten mache, ist:

Die Crontab:

* * * * * php /path/to/php/script.php &

Der PHP-Code:

<?php
if (Shell_exec('ps aux | grep ' . __FILE__ . ' | wc  -l') > 1) {
    exit('already running...');
}
// do stuff

Dieser Befehl sucht in der Systemprozessliste nach dem aktuellen PHP-Dateinamen, falls vorhanden. Der Zeilenzähler (wc -l) ist größer als einer, da der Suchbefehl selbst den Dateinamen enthält

wenn Sie PHP-Benutzer sind, fügen Sie den obigen Code zum Anfang Ihres PHP-Codes hinzu, und er wird nur einmal ausgeführt.

4
talsibony

Ich würde empfehlen, ein vorhandenes Tool wie monit zu verwenden, um Prozesse zu überwachen und automatisch neu zu starten. Es sind weitere Informationen verfügbar hier . Es sollte in den meisten Distributionen problemlos verfügbar sein.

3
Zitrax

Mit lockrun müssen Sie kein Wrapper-Skript für Ihren Cron-Job schreiben. http://www.unixwiz.net/tools/lockrun.html

3

Dieser hat mich nie enttäuscht:

one.sh :

LFILE=/tmp/one-`echo "[email protected]" | md5sum | cut -d\  -f1`.pid
if [ -e ${LFILE} ] && kill -0 `cat ${LFILE}`; then
   exit
fi

trap "rm -f ${LFILE}; exit" INT TERM EXIT
echo $$ > ${LFILE}

[email protected]

rm -f ${LFILE}

cron job :

* * * * * /path/to/one.sh <command>
2
DJV
# one instance only (works unless your cmd has 'grep' in it)
ALREADY_RUNNING_EXIT_STATUS=0
bn=`basename $0`
proc=`ps -ef | grep -v grep | grep "$bn" | grep -v " $$ "`
[ $? -eq 0 ] && {
    pid=`echo $proc | awk '{print $2}'`
    echo "$bn already running with pid $pid"
    exit $ALREADY_RUNNING_EXIT_STATUS
}
1
ekerner

Ich würde Folgendes als Verbesserung für Antwort von rsanden vorschlagen (Ich würde als Kommentar posten, habe aber nicht genug Ansehen ...):

#!/usr/bin/env bash

PIDFILE="$HOME/tmp/myprogram.pid"

if [ -e "${PIDFILE}" ] && (ps -p $(cat ${PIDFILE}) > /dev/null); then
  echo "Already running."
  exit 99
fi

/path/to/myprogram

Dies vermeidet mögliche falsche Übereinstimmungen (und den Overhead von Grepping), und es unterdrückt die Ausgabe und verlässt sich nur auf den Exit-Status von ps.

1
dbenton

Einfache benutzerdefinierte PHP ist genug zu erreichen. Keine Notwendigkeit, mit Shell-Skript zu verwechseln.

nehmen wir an, Sie möchten php /home/mypath/example.php ausführen, wenn nicht ausgeführt wird

Verwenden Sie dann das folgende benutzerdefinierte PHP-Skript, um denselben Job auszuführen.

erstelle folgendes / home/mypath/forever.php

<?php
    $cmd = $argv[1];
    $grep = "ps -ef | grep '".$cmd."'";
    exec($grep,$out);
    if(count($out)<5){
        $cmd .= ' > /dev/null 2>/dev/null &';
        exec($cmd,$out);
        print_r($out);
    }
?>

Dann fügen Sie in Ihrem Cron Folgendes hinzu

* * * * * php /home/mypath/forever.php 'php /home/mypath/example.php'
1
lingeshram

Ziehen Sie in Betracht, pgrep (falls verfügbar) anstelle von ps zu verwenden, die durch grep geleitet werden, wenn Sie diesen Weg gehen. Ich persönlich habe eine Menge Meilen von den Skripten des Formulars entfernt

while(1){
  call script_that_must_run
  sleep 5
}

Obwohl dies fehlschlagen kann und Cronjobs sind oft der beste Weg für wichtige Dinge. Nur eine andere Alternative.

0
Richard Thomas