Wie erstelle ich eine Crontab über ein Skript?

153

Ich muss einen Cron-Job über ein Skript hinzufügen, das ich zum Einrichten eines Servers ausführe. Ich benutze derzeit Ubuntu. Ich kann verwenden, crontab -eaber das öffnet einen Editor, um die aktuelle Crontab zu bearbeiten. Ich möchte dies programmgesteuert tun.

Ist das möglich?

gaurav
quelle
Wenn Sie einen Crontab-Eintrag ändern oder löschen möchten, lesen Sie meine Lösung unten.
Brian Smith

Antworten:

11

Cron-Jobs werden normalerweise in einer Benutzerdatei unter gespeichert /var/spool/cron

Am einfachsten ist es wahrscheinlich, eine Textdatei mit dem konfigurierten Job zu erstellen, diese dann in den Cron-Spool-Ordner zu kopieren und sicherzustellen, dass sie über die richtigen Berechtigungen verfügt (600).

Jason Stelzer
quelle
19
Das Ändern der Dateien direkt in / var / spool / cron ist verpönt. Wenn Sie sich die Dateien dort ansehen, enthalten sie normalerweise Warnungen wie "DIESE DATEI NICHT BEARBEITEN" als erste Zeile.
Jared
12
@Jared Obwohl ich der Idee durchaus zustimme, hilft es nicht viel, zu sagen, dass sie "verpönt" ist. Sagen Sie lieber, welche andere Datei gegebenenfalls bearbeitet werden soll, oder erläutern Sie die Risiken der manuellen Bearbeitung von Dateien. Ich plane, einige Cron-Jobs über die automatisierte Befehlszeile zu erstellen. Wenn das Bearbeiten dieser Datei sowohl die einzige Option als auch ohne wesentliche Nebenwirkungen ist, verstehe ich nicht, warum ich sie nicht verwenden sollte.
Balmipour
46
Scrollen Sie nach unten, um die richtige Antwort zu erhalten.
John Red
1
Meiner Meinung nach ist diese Antwort viel besser: stackoverflow.com/a/610860/2681752
galaux
2
Ich habe diesen Ansatz gewählt und es bereut. Unter RHEL ist das Verzeichnis / var / spool / cron nicht weltweit ausführbar, sodass Benutzer das Verzeichnis nicht durchlaufen und ihre Dateien nicht manuell bearbeiten können. Wenn Sie / var / spool / cron world ausführbar machen, wird Ihr freundlicher lokaler Systemadministrator sauer auf Sie sein, und die Berechtigungsänderung kann überschrieben werden, wenn das cronie-Paket jemals neu installiert oder aktualisiert wird.
Funktionvoid
383

Hier ist ein Einzeiler, der den neuen Job nicht in einer Datei verwendet / benötigt:

(crontab -l 2>/dev/null; echo "*/5 * * * * /path/to/job -with args") | crontab -

Das 2>/dev/nullist wichtig , damit Sie nicht das bekommt no crontab for usernameNachricht , dass einige * nixes produzieren , wenn es derzeit keine crontab Einträge sind.

Joe Casadonte
quelle
14
Dies sollte die akzeptierte Antwort sein. Ich brauche jetzt nur einen Weg, um zu überprüfen, ob der
Einzeiler, den
7
... oh warte, hier ist, wie man prüft, ob sich etwas in der Crontab meines Benutzers befindet, bevor ich es mit einem Skript hinzufüge: stackoverflow.com/a/14451184/3686125
ChrisPrime
1
Wenn dieses Skript als Befehl zum Wiederholen und Ändern einer vorhandenen Cron-Aufgabe gedacht ist, kann es hilfreich sein, die vorhandene Zeile in Crontab zu ersetzen. Es können mehrere Marker verwendet werden, um verschiedene Cron-Aufgaben zu steuern (Kontrollmarker-1, Kontrollmarker-2 usw.): (crontab -l 2> / dev / null | grep -v Kontrollmarker-1; Echo '* / 5 * * * * / path / to / job -with args # control-marker-1') | Crontab -
Chef
7
Ich stellte fest, dass dadurch vorhandene Crontab-Einträge entfernt wurden und ich einen anderen Benutzer (root) verwenden musste, sodass ich die vorhandenen Einträge wie folgt verwendete: echo -e "$(sudo crontab -u root -l)\n* * * * * echo hello > /home/danny/temp.log 2>&1" | sudo crontab -u root -Hoffentlich hilft dies jemandem
Danny
59

Für Benutzer-Crontabs (einschließlich Root) können Sie Folgendes tun:

crontab -l -u user | cat - filename | crontab -u user -

Dabei enthält die Datei mit dem Namen "Dateiname" Elemente zum Anhängen. Sie können die Textmanipulation auch mit sedeinem anderen Werkzeug anstelle von durchführen cat. Sie sollten den crontabBefehl verwenden, anstatt die Datei direkt zu ändern.

Eine ähnliche Operation wäre:

{ crontab -l -u user; echo 'crontab spec'; } | crontab -u user -

Wenn Sie System-Crontabs ändern oder erstellen, können diese wie normale Textdateien bearbeitet werden. Sie werden in den gespeicherten /etc/cron.d, /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly, /etc/cron.monthlyVerzeichnissen und in den Dateien /etc/crontabund /etc/anacrontab.

Bis auf weiteres angehalten.
quelle
Sah vielversprechend aus, versuchte aber den zweiten Ansatz (mit echo) und bekam "crontab: Verwendungsfehler: Dateiname muss zum Ersetzen angegeben werden". Die Cron-Manpage zeigt die Syntax als crontab [ -u user ] file, dh mit einem obligatorischen Dateinamen. Gibt es einen Trick, um stattdessen die weitergeleiteten Daten zu akzeptieren?
Mark Berry
1
@ MarkBerry: Entschuldigung. In einer Pipe muss ein Bindestrich verwendet werden, um anzuzeigen, dass die Eingabe von stammt stdin. Ich werde meine Antwort korrigieren.
Bis auf weiteres angehalten.
29

In Ubuntu und vielen anderen Distributionen können Sie einfach eine Datei in das /etc/cron.dVerzeichnis einfügen, das eine einzelne Zeile mit einem gültigen crontab- Eintrag enthält. Es ist nicht erforderlich, einer vorhandenen Datei eine Zeile hinzuzufügen.

Wenn Sie nur etwas benötigen, das täglich ausgeführt werden soll, legen Sie einfach eine Datei ab /etc/cron.daily. Ebenso können Sie auch Dateien in fallen /etc/cron.hourly, /etc/cron.monthlyund /etc/cron.weekly.

IvanGoneKrazy
quelle
5
Aber Sie müssen root sein, um dies zu tun.
Keith
17

Eine noch einfachere Antwort auf Ihre Frage wäre:

echo "0 1 * * * /root/test.sh" | tee -a /var/spool/cron/root

Sie können Cronjobs auf Remote-Servern wie folgt einrichten:

#!/bin/bash
servers="srv1 srv2 srv3 srv4 srv5"
for i in $servers
  do
  echo "0 1 * * * /root/test.sh" | ssh $i " tee -a /var/spool/cron/root"
done

Unter Linux ist der Standardspeicherort der crontabDatei /var/spool/cron/. Hier finden Sie die crontabDateien aller Benutzer. Sie müssen nur Ihren Cronjob-Eintrag an die Datei des jeweiligen Benutzers anhängen. Im obigen Beispiel wird die Crontab-Datei des Root-Benutzers mit einem Cronjob versehen, der /root/test.shjeden Tag um 1 Uhr morgens ausgeführt wird.

Ganesh Pathak
quelle
Das wäre /var/spool/cron/crontabs/rootauf Ubuntu.
Mhor Mé
17

Crontab-Dateien sind einfach Textdateien und können als solche wie jede andere Textdatei behandelt werden. Der crontabBefehl dient dazu, das Bearbeiten von Crontab-Dateien sicherer zu machen. Bei der Bearbeitung mit diesem Befehl wird die Datei auf Fehler überprüft und nur gespeichert, wenn keine vorhanden sind.

crontab [path to file]kann verwendet werden, um eine in einer Datei gespeicherte Crontab anzugeben. So crontab -ewird die Datei nur installiert, wenn sie fehlerfrei ist.

Daher kann ein Skript entweder direkt Cron-Tab-Dateien schreiben oder sie in eine temporäre Datei schreiben und mit dem crontab [path to temp file]Befehl laden . Das direkte Schreiben erspart das Schreiben einer temporären Datei, vermeidet aber auch die Sicherheitsüberprüfung.

Cledoux
quelle
2
Beachten Sie für Noobs wie mich, dass crontab [path to file]dies der Fall ist . Dies war definitiv die beste Option für mich, da sie besser lesbaren Code ermöglicht. Ich verwende crontab, um Pakete zu verfolgen und mein Desktop-Hintergrundbild mit dem Status zu ändern. Wenn ich keine Pakete erwarte, muss es nicht jede Stunde überprüft werden. Aus diesem Grund wollte ich, dass das Skript die Cron-Frequenz automatisch bearbeitet.
Rasmus
1
@Rasmus Das klingt nach einem großartigen Skript, das ich gerne stehlen würde. Gibt es eine Chance, über einen Kern oder ähnliches zu teilen?
Cledoux
7

(Ich habe nicht genug Ruf, um einen Kommentar abzugeben, daher füge ich als Antwort hinzu: Fühlen Sie sich frei, ihn als Kommentar neben seiner Antwort hinzuzufügen.)

Der Einzeiler von Joe Casadonte ist perfekt, es sei denn, Sie arbeiten mit set -e, dh wenn Ihr Skript bei einem Fehler fehlschlägt und noch keine Cronjobs vorhanden sind. In diesem Fall erstellt der Einzeiler NICHT den Cronjob, sondern stoppt das Skript NICHT. Der stille Fehler kann sehr irreführend sein.

Der Grund dafür ist, dass die crontab -lRückgabe mit einem 1Rückkehrcode erfolgt und der nachfolgende Befehl (the echo) nicht ausgeführt wird. Daher wird der Cronjob nicht erstellt. Da sie jedoch (aufgrund der Klammern) als Unterprozess ausgeführt werden, stoppen sie das Skript nicht.

(Interessanterweise funktioniert es, wenn Sie denselben Befehl erneut ausführen: Wenn Sie ihn einmal ausgeführt haben crontab -, wird crontab -limmer noch nichts ausgegeben, aber es wird kein Fehler mehr zurückgegeben (Sie erhalten die no crontab for <user>Nachricht nicht mehr). Der folgende echoBefehl wird also ausgeführt und die crontab wird erstellt)

In jedem Fall set -emuss die Zeile wie folgt lauten:

(crontab -l 2>/dev/null || true; echo "*/5 * * * * /path/to/job -with args") | crontab -
Faria
quelle
Ja, das hier ist noch perfekter.
Yngve Sneen Lindal
7

Als Korrektur zu den Vorschlägen crontab -l | crontab -: Dies funktioniert nicht auf jedem System. Zum Beispiel musste ich der Root-Crontab auf Dutzenden von Servern, auf denen eine alte Version von SUSE ausgeführt wird, einen Job hinzufügen (fragen Sie nicht warum). Alte SUSEs stellen der Ausgabe von Kommentarzeilen voran crontab -lund machen sie crontab -l | crontab -nicht idempotent (Debian erkennt dieses Problem in der Crontab-Manpage und hat seine Version von Vixie Cron gepatcht, um das Standardverhalten von zu ändern crontab -l).

Um programmgesteuert Crontabs auf Systemen zu bearbeiten, auf denen crontab -lKommentare hinzugefügt werden , können Sie Folgendes versuchen:

EDITOR=cat crontab -e > old_crontab; cat old_crontab new_job | crontab -

EDITOR=catWeist crontab an, es catals Editor zu verwenden (nicht die übliche Standardeinstellung vi), wodurch die Datei nicht geändert, sondern in stdout kopiert wird. Dies kann immer noch fehlschlagen, wenn crontab -Eingaben in einem anderen Format als den crontab -eAusgaben erwartet werden . Versuchen Sie nicht, das Finale crontab -durch zu ersetzen crontab -e- es wird nicht funktionieren.

user2845840
quelle
4

Nun, /etc/crontabnur eine ASCII-Datei, also ist es am einfachsten, einfach

 echo "*/15 * * * *   root     date" >> /etc/crontab

Dadurch wird ein Job hinzugefügt, der Ihnen alle 15 Minuten eine E-Mail sendet. Passen Sie den Geschmack an und testen Sie über grepoder auf andere Weise, ob die Zeile bereits hinzugefügt wurde, um Ihr Skript idempotent zu machen.

Unter Ubuntu et al. Können Sie auch Dateien /etc/cron.*ablegen, die einfacher zu erstellen und zu testen sind. Außerdem können Sie sich nicht mit (System-) Konfigurationsdateien wie z /etc/crontab.

Dirk Eddelbuettel
quelle
1
Ich denke, dass technisch gesehen crond nicht erforderlich ist, um Änderungen an crontab zu überwachen, auch wenn dies in der Realität bei den meisten Implementierungen der Fall ist. Daher würde ich crontab -e einen Anruf empfehlen, um es anschließend zu bearbeiten. crontab -e berücksichtigt die EDITOR-Variable, wenn Speicher zur Verfügung steht. Wenn Sie sie daher für den Moment auf / bin / true setzen, muss die crontab nur erneut gelesen werden.
Ulrich Schwarz
1
Richtig, aber auf jedem neueren Linux-System crond wird überwacht, und zwar auf der angegebenen Plattform des OP.
Dirk Eddelbuettel
Nur wenn Sie root sind und das Skript als root ausgeführt werden soll. Dies ist im Fall der OP möglicherweise nicht wünschenswert.
Keith
Nicht so, ich habe viele Nicht-Root-Einträge in / etc / crontab. Sie benötigen "nur" sudo, um an die Datei anzuhängen. Wie ich bereits sagte, gibt es auch /etc/cron.*/, aber Sie müssen auch root sein, um dort schreiben zu können.
Dirk Eddelbuettel
2

Hier erfahren Sie, wie Sie einen Cron-Eintrag ändern, ohne die Cron-Datei (die verpönt ist) direkt zu bearbeiten.

crontab -l -u <user> | sed 's/find/replace/g' | crontab -u <user> -

Wenn Sie einen Cron-Eintrag entfernen möchten, verwenden Sie Folgendes:

crontab -l -u <user> | sed '/find/d' | crontab -u <user> -

Mir ist klar, dass Gaurav nicht darum gebeten hat, aber warum nicht alle Lösungen an einem Ort haben?

Brian Smith
quelle
1

Ich habe ein Crontab-Bereitstellungstool in Python geschrieben: https://github.com/monklof/deploycron

pip install deploycron

Die Installation Ihrer Crontab ist sehr einfach. Dadurch wird die Crontab mit der vorhandenen Crontab des Systems zusammengeführt.

from deploycron import deploycron
deploycron(content="* * * * * echo hello > /tmp/hello")
monklof
quelle
1

Es ist ein Ansatz, um den Cron-Job schrittweise hinzuzufügen:

  ssh USER_NAME@$PRODUCT_IP nohup "echo '*/2 * * * * ping -c2 PRODUCT_NAME.com >> /var/www/html/test.html' | crontab -u USER_NAME -"
Oleksii Kyslytsyn
quelle