Wie kann ich programmgesteuert einen neuen Cron-Job erstellen?


129

Ich möchte in der Lage sein, programmgesteuert einen neuen Cron-Job hinzuzufügen. Was ist der beste Weg, dies zu tun?

Aus meinen Nachforschungen geht hervor , dass ich die aktuelle Crontab entleeren und dann eine neue anhängen und diese zurück in die Crontab leiten könnte:

(crontab -l ; echo "0 * * * * wget -O - -q http://www.example.com/cron.php") | crontab -

Gibt es einen besseren Weg?


2
Ihre Lösung scheint gut zu sein.
Craig S

Entfernen Sie unter Solaris einfach den Bindestrich für die letzte Crontab. Sie können ein grep hinzufügen, um zu vermeiden, dass bereits eine Zeile hinzugefügt wird.
Lacroix1547


geschweifte Klammern anstelle von Klammern tun dies, ohne einen Prozess auszulösen. Stellen Sie sicher, dass um die Klammern Leerzeichen vorhanden sind. {...; }.
Jay Winston

Antworten:


-25

Es hat immer gut für mich funktioniert.

Sie sollten ein etwas komplexeres Skript in Betracht ziehen, das drei Dinge kann.

  1. Fügen Sie eine Crontab-Linie hinzu. versichern, dass es nicht existierte. Hinzufügen, wenn es bereits existiert, ist schlecht.

  2. Entfernen Sie die Crontab-Leitung. Vielleicht nur Warnung, wenn es nicht existiert.

  3. Eine Kombination der beiden oben genannten Merkmale, um die Crontab-Linie zu ersetzen.


77
Er fragt wie und du sagst ihm was?
Cerin

1
Was ist, wenn der Benutzer noch keine Crontab hat?
Maxim Egorushkin

132

Der beste Weg, wenn Sie als root ausgeführt werden, besteht darin, eine Datei in /etc/cron.d abzulegen

Wenn Sie einen Paketmanager zum Packen Ihrer Software verwenden, können Sie einfach Dateien in diesem Verzeichnis ablegen. Diese werden so interpretiert, als wären sie Crontabs, jedoch mit einem zusätzlichen Feld für den Benutzernamen, z.

Dateiname: /etc/cron.d/per_minute

Inhalt: * * * * * root /bin/sh /home/root/script.sh


5
Stellen Sie einfach sicher, dass die verwendete Version von cron /etc/cron.d/ unterstützt. Die meisten modernen Linux-Distributionen tun dies.
Sleske

8
Dies ist die einfachste und eleganteste Lösung. Sicher ist es besser, eine vorhandene Crontab mit anderen nicht verwandten Einträgen zu analysieren und zu bearbeiten.
Cerin

13
Eine mögliche Einschränkung ist die Häufigkeit, mit der cron neue Ergänzungen zu diesem Ordner aufnimmt (einmal pro Stunde). Wenn Sie erwarten, dass Ihr Job sofort ausgeführt wird, passen Sie auf.
JonathanK

6
@ JonathanK, wissen Sie zufällig, ob Cron aufgefordert werden kann, erneut zu scannen /etc/cron.d/*? Es ist schwer zu wissen, ob etwas funktioniert, wenn man eine Stunde warten muss, um es zu überprüfen!
Halfer

4
Wie sollen Dauerwellen für diese Datei eingestellt werden? chmod + x /etc/cron.d/per_minute?
Giò

101

Die Lösung von OP weist einen Fehler auf. Möglicherweise können Einträge zweimal hinzugefügt werden.

(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -

5
Dies ist tatsächlich eine bessere, wenn nicht beschriebene Lösung. Es stellt sicher, dass der Befehl nicht zweimal zu crontab hinzugefügt wird.
Bufke

2
Dies ist kaum eine gute Lösung für das Problem mit doppelten Einträgen. Was ist, wenn in der Zwischenzeit eine weitere Zeile zu crontab hinzugefügt wurde?
hmn

6
Um die Einzigartigkeit zu gewährleisten, kurz sortzuvor uniq:(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
mway

6
Keine Notwendigkeit für uniq. Verwenden Sie die -uOption ein sort.
Papiro

6
So vermeiden Sie keine Crontab für Benutzer, wenn ich Crontab zum ersten Mal bearbeite.
Wyx

23

Etwas zu cron hinzufügen

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | sort | uniq | crontab -

Um dies von Cron zu entfernen

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | grep -v hupChannel.sh |  sort | uniq | crontab -

Hoffnung würde jemandem helfen


Dies ist genau das, wonach ich gesucht habe. Ich würde nur Folgendes hinzufügen: | grep -v '^ #' | um die Kommentare
herauszufiltern

2
Das sollten Sie eigentlich nicht brauchen, 2>&1 | grep -v "no crontab"denn wenn keine Crontab vorhanden ist, wird die Ausgabezeile crontab: no crontab for...an stderr gesendet. Es gibt keinen Grund, diese Ausgabe zu erfassen, an stdout zu senden und sie dann mit grep herauszufiltern. Wenn Sie vermeiden möchten, crontab: no crontab for...in Ihrer Ausgabe zu sehen, verwenden Sie 2> /dev/null | sort.....
Matty


6

Ändern Sie einfach den Editor in den Befehl tee:

export EDITOR="tee"
echo "0 * * * * /bin/echo 'Hello World'" | crontab -e

3
Achtung - dies löscht alle vorhandenen Einträge.
Sternenfrucht

5

Angenommen, Ihre Crontab enthält bereits einen Eintrag, sollte der folgende Befehl relativ gut funktionieren. Beachten Sie, dass die $CMDVariable nur zur besseren Lesbarkeit dient. Das Sortieren vor dem Filtern von Duplikaten ist wichtig, da es uniqnur in benachbarten Zeilen funktioniert.

CMD='wget -O - -q http://www.example.com/cron.php"'
(crontab -l ; echo "0 * * * * $CMD") | sort | uniq | crontab -

Wenn Sie derzeit eine leere Crontab haben, erhalten Sie die folgende Fehlermeldung an stderr:

no crontab for user

Wenn Sie dies vermeiden möchten, können Sie ein wenig Komplexität hinzufügen und Folgendes tun:

(crontab -l ; echo "0 * * * * $CMD") 2>&1 | sed "s/no crontab for $(whoami)//"  | sort | uniq | crontab -

5

Die meisten Lösungen hier sind für das Hinzufügen von Linien zur Crontab. Wenn Sie mehr Kontrolle benötigen, möchten Sie in der Lage sein, den gesamten Inhalt der Crontab zu kontrollieren.

Sie können Rohrleitungen verwenden, um dies ziemlich elegant zu tun.

Um die Crontab vollständig neu zu schreiben, tun Sie dies

echo "2 2 2 2 2 /bin/echo foobar" |crontab -

Dies sollte leicht mit anderen hier beschriebenen Antworten wie zu kombinieren sein

crontab -l | <something> | tee |crontab -

Oder wenn Sie den Inhalt in einer Datei haben, ist es noch einfacher

cat <file> |crontab -

3

Hier ist ein weiterer einzeiliger Weg, der Duplikate vermeidet

(crontab -l 2>/dev/null | fgrep -v "*/1 *  *  *  * your_command"; echo "*/1 *  *  *  * your_command") | crontab -

Und hier ist eine Möglichkeit, JohnZs Antwort zu geben und no crontab for userNachrichten zu vermeiden , oder wenn Sie in einer Typumgebung arbeiten set -eumüssen und nichts einen Fehler zurückgeben kann (in diesem Fall ist das 2>/dev/nullTeil optional):

( (crontab -l 2>/dev/null || echo "")  ; echo "0 * * * * your_command") | sort -u - | crontab -

Oder wenn Sie die Dinge so aufteilen möchten, dass sie besser lesbar sind:

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
(echo "$preceding_cron_jobs" ; echo "$new_job") | sort - | uniq - | crontab -

Oder entfernen Sie optional alle Verweise auf Ihren_Befehl (z. B. wenn sich der Zeitplan geändert hat, möchten Sie, dass er nur einmal erstellt wird). In diesem Fall brauchen wir nicht mehr uniq(zusätzlicher Bonus, Einfügereihenfolge bleibt ebenfalls erhalten):

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
preceding_cron_jobs=$(echo "$preceding_cron_jobs" | grep -v your_command )
(echo "$preceding_cron_jobs" ; echo "$new_job") | crontab -

2

Mann Crontab ist auch nützlich:

CRONTAB (1)

NAME

   crontab - manipulate per-user crontabs (Dillon's Cron)

ZUSAMMENFASSUNG

   crontab file [-u user] - replace crontab from file

   crontab - [-u user] - replace crontab from stdin

   crontab -l [user] - list crontab for user

3
Der Teil, der "crontab von stdin ersetzen" sagt, ist eigentlich eine halbe Antwort :-)
Grodriguez

2

Neben der Antwort von JohnZ finden Sie hier die Syntax, die Sie als Root planen können, wenn Sie ein Sudoer sind:

(sudo crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | sudo crontab -

1
function cronjob_exists($command){

    $cronjob_exists=false;

    exec('crontab -l', $crontab);


    if(isset($crontab)&&is_array($crontab)){

        $crontab = array_flip($crontab);

        if(isset($crontab[$command])){

            $cronjob_exists=true;

        }

    }
    return $cronjob_exists;
}

function append_cronjob($command){

    if(is_string($command)&&!empty($command)&&cronjob_exists($command)===FALSE){

        //add job to crontab
        exec('echo -e "`crontab -l`\n'.$command.'" | crontab -', $output);


    }

    return $output;
}

    append_cronjob('* * * * * curl -s http://localhost/cron/test.php');

1

Dadurch wird überprüft, ob Ihr Befehl noch nicht vorhanden ist, bevor Sie ihn hinzufügen.

crontab -l 2>/dev/null | grep -q '/path/to/script' || echo "5 * * * * /path/to/script" | crontab -

Prost.


0

Piping stdout in crontabhat die neue crontab für mich unter macOS nicht installiert, daher habe ich diese Lösung stattdessen mithilfe des teeEditors in einer Sub-Shell gefunden:

(EDITOR=tee && (crontab -l ; echo "@daily ~/my-script.sh" ) | uniq - | crontab -e)

0

Wenn die Aufgabe als Benutzer ausgeführt werden soll:

crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | crontab -

Wenn die Aufgabe mit Berechtigungen ausgeführt werden soll:

sudo crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | sudo crontab -

und Aufgabe überprüfen (mit oder ohne 'sudo'):

crontab -l | sed '/^$/d; /#/d'


-2

Sie können die Cron-Tabellentextdatei auch direkt bearbeiten, aber Ihre Lösung scheint vollkommen akzeptabel zu sein.


1
Ich wäre diesbezüglich misstrauisch, da Bedenken bestehen, dass gleichzeitige Änderungen zu einer Beschädigung der Datei führen könnten. Die Verwendung des Befehlszeilebefehls crontab sollte dieses Problem vermeiden.
Craig S

Craig, ohne weitere Nachforschungen wäre ich mir nicht sicher, ob die Befehlszeilenversion atomar und rennsicher ist. Wahrscheinlich sowieso "ziemlich sicher".
Tuomassalo

"Direktes Bearbeiten der Datei" ist ohne Root-Zugriff nicht möglich (vorausgesetzt, Sie können herausfinden, wo sich die Crontab-Datei des Benutzers befindet und wie Sie sicherstellen können, dass der Cron-Daemon Ihre Änderungen korrekt empfängt), und das programmgesteuerte "Bearbeiten" scheint die Frage zu sein will in erster Linie Rat.
Tripleee
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.