Wie erstelle ich mit Bash automatisch einen Cron-Job ohne den interaktiven Editor?

395

Hat crontab ein Argument zum Erstellen von Cron-Jobs ohne Verwendung des Editors (crontab -e)? Wenn ja, wie würde der Code einen Cronjob aus einem Bash-Skript erstellen?

Raúl Roa
quelle
5
Leider zeigen die meisten Top-Antworten hier nur, wie man Crontab modifiziert - wenn auch auf einigermaßen sichere Weise -, aber ich denke, es ist insgesamt der falsche Ansatz. Besser, sicherer und einfacher ist es, eine Datei in {{cron.d}} abzulegen, und es gibt (derzeit) Antworten mit niedrigen Stimmen, die erklären, wie das geht, wenn Sie weiter nach unten schauen.
Gregmac

Antworten:

539

Sie können der Crontab wie folgt hinzufügen:

#write out current crontab
crontab -l > mycron
#echo new cron into cron file
echo "00 09 * * 1-5 echo hello" >> mycron
#install new cron file
crontab mycron
rm mycron

Erklärung der Cron-Linie

* * * * * "command to be executed"
- - - - -
| | | | |
| | | | ----- Day of week (0 - 7) (Sunday=0 or 7)
| | | ------- Month (1 - 12)
| | --------- Day of month (1 - 31)
| ----------- Hour (0 - 23)
------------- Minute (0 - 59)

Quelle nixCraft .

Dogbane
quelle
14
Sie sollten tempfile oder mktemp
Paweł Polewicz
166
(crontab -l; echo "00 09 * * 1-5 echo hallo") | crontab -
Edo
32
(crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -- einfacher zu kopieren Edos Antwort
WBAR
8
Ich würde vorschlagen , dass sich ändern ;mit &&als sicherer Schutz vor dem Fall , wenn crontab -lfehlschlägt. (crontab -l && echo "0 0 0 0 0 some entry") | crontab -
Also
12
@MacUsers, crontab -lschlägt fehl, wenn keine Crontab vorhanden ist. Daher &&macht es die Verwendung des Skripts unmöglich, den ersten Eintrag zur Crontab hinzuzufügen.
JPhi1618
312

Möglicherweise können Sie dies im laufenden Betrieb tun

crontab -l | { cat; echo "0 0 0 0 0 some entry"; } | crontab -

crontab -llistet die aktuellen Crontab-Jobs auf, catdruckt sie aus, echodruckt den neuen Befehl und crontab -fügt alle gedruckten Inhalte der Crontab-Datei hinzu. Sie können den Effekt sehen, indem Sie eine neue machen crontab -l.

TheBonsai
quelle
3
Danke, könnten Sie die Syntax erklären oder auf eine URL verweisen, die sie erklärt?
Websites
9
crontab -llistet die aktuellen Crontab-Jobs auf, catdruckt sie aus, echodruckt den neuen Befehl und crontab -fügt alle gedruckten Inhalte der Crontab-Datei hinzu. Sie können den Effekt sehen, indem Sie ein neuescrontab -l
nha
3
Arbeitet ein Vergnügen für mich. Wenn der Benutzer keine Crontab hat, sehen Sie no crontab for <username>, aber es funktioniert trotzdem.
Fazy
21
funktioniert nicht auf meiner Amazon EC2-Instanz. Funktioniert stattdessen (crontab -l ; echo "00 09 * * 1-5 echo hello") | crontab -.
Stéphane Bruckert
11
Dies sieht aus wie ein Kandidat für eine UUcatA .
Ceving
86

Diese kürzere Datei erfordert keine temporäre Datei, ist immun gegen mehrfache Einfügungen und ermöglicht das Ändern des Zeitplans eines vorhandenen Eintrags.

Angenommen, Sie haben diese:

croncmd="/home/me/myfunction myargs > /home/me/myfunction.log 2>&1"
cronjob="0 */15 * * * $croncmd"

So fügen Sie es der Crontab ohne Duplizierung hinzu:

( crontab -l | grep -v -F "$croncmd" ; echo "$cronjob" ) | crontab -

So entfernen Sie es aus der Crontab, unabhängig vom aktuellen Zeitplan:

( crontab -l | grep -v -F "$croncmd" ) | crontab -

Anmerkungen:

  • grep -F stimmt buchstäblich mit der Zeichenfolge überein, da wir sie nicht als regulären Ausdruck interpretieren möchten
  • Wir ignorieren auch die Zeitplanung und suchen nur nach dem Befehl. Diesen Weg; Der Zeitplan kann geändert werden, ohne dass das Risiko besteht, der Crontab eine neue Zeile hinzuzufügen
MoonCactus
quelle
@moeseth: kannst du das näher erläutern?
MoonCactus
Sie sollten es auf Ihrem Computer versuchen
Moeseth
2
@moeseth: Ich habe es offensichtlich auf meinem Computer (Linux) versucht. Ich würde keine zufälligen nicht funktionierenden Sachen vorschlagen: /
MoonCactus
2
Übrigens können 27 Menschen (bis heute) nicht falsch liegen. Beschreiben Sie daher bitte, warum es für Ihr Setup nicht funktioniert, damit wir Ihnen helfen können.
MoonCactus
2
Möglicherweise liegt ein OSX-Problem vor.
Moeseth
40

Vielen Dank an alle für Ihre Hilfe. Ich habe zusammengesetzt, was ich hier und anderswo gefunden habe:

Der Code

command="php $INSTALL/indefero/scripts/gitcron.php"
job="0 0 * * 0 $command"
cat <(fgrep -i -v "$command" <(crontab -l)) <(echo "$job") | crontab -

Ich konnte nicht herausfinden, wie ich die Notwendigkeit für die beiden Variablen beseitigen konnte, ohne mich zu wiederholen.

commandist offensichtlich der Befehl, den ich planen möchte. jobnimmt $commanddie Planungsdaten und fügt sie hinzu. Ich brauchte beide Variablen separat in der Codezeile, die die Arbeit erledigt.

Einzelheiten

  1. Dank duckyflip verwende ich dieses kleine Redirect-Ding ( <(*command*)), um die Ausgabe von crontab -lin eine Eingabe für den fgrepBefehl umzuwandeln .
  2. fgrepfiltert dann alle Übereinstimmungen von $command( -vOption) heraus, wobei die Groß- und Kleinschreibung nicht berücksichtigt wird ( -iOption).
  3. Wieder wird das kleine Redirect-Ding ( <(*command*)) verwendet, um das Ergebnis wieder in eine Eingabe für den catBefehl umzuwandeln .
  4. Der catBefehl erhält auch echo "$job"(selbsterklärend) wiederum durch Verwendung des Redirect-Dings ( <(*command*)).
  5. Die gefilterte Ausgabe von crontab -lund die einfache echo "$job", kombinierte Ausgabe werden weitergeleitet ('|'), crontab -um schließlich geschrieben zu werden.
  6. Und wenn sie nicht gestorben sind, leben sie noch heute!

In einer Nussschale:

Diese Codezeile filtert alle Cron-Jobs heraus, die dem Befehl entsprechen, und schreibt dann die verbleibenden Cron-Jobs mit dem neuen aus, wobei sie sich effektiv wie eine "Hinzufügen" - oder "Aktualisieren" -Funktion verhält. Um dies zu verwenden, müssen Sie lediglich die Werte für die Variablen commandund jobaustauschen.

Stoutie
quelle
5
Der Vorteil dieses Ansatzes besteht darin, dass Sie ihn mehrmals ausführen können, ohne sich um doppelte Einträge in der Crontab sorgen zu müssen (im Gegensatz zu allen anderen Lösungen). Das liegt amfgrep -v
Aleemb
5
Wenn Sie die traditionelle Art der Verrohrung von links nach rechts bevorzugen, ersetzen Sie die letzte Zeile durch: crontab -l | fgrep -i -v "$command" | { cat; echo "$job"; } | crontab -l
Antoine Lizée
1
@ AntoineLizée, du antwortest hat am Ende extra "l", was nicht da sein sollte.
Henry
26

EDIT (festes Überschreiben):

cat <(crontab -l) <(echo "1 2 3 4 5 scripty.sh") | crontab -
duckyflip
quelle
Dies wird alle Crontab-Inhalte ersetzen
TheBonsai
1
@ TheBonsai oh ich verstehe, ich habe es jetzt behoben, so dass es den neuen Befehl an den vorhandenen Crontab-Inhalt
anhängen sollte
3
Denken Sie daran, dass die Prozessersetzung von Bash Fehler verschluckt. Wenn dies crontab -lfehlschlägt, aber crontab -erfolgreich ist, ist Ihre Crontab ein Einzeiler.
20.
13

Es gab viele gute Antworten bezüglich der Verwendung von Crontab, aber keine Erwähnung einer einfacheren Methode, wie z. B. der Verwendung cron.

Unter Verwendung cronwürde sich die Vorteile von Systemdateien und Verzeichnisse nehmen /etc/crontab, /etc/cron.daily,weekly,hourlyoder /etc/cron.d/:

cat > /etc/cron.d/<job> << EOF
SHELL=/bin/bash 
PATH=/sbin:/bin:/usr/sbin:/usr/bin 
MAILTO=root HOME=/  
01 * * * * <user> <command>
EOF

In diesem obigen Beispiel haben wir eine Datei in erstellt /etc/cron.d/, die Umgebungsvariablen für die erfolgreiche Ausführung des Befehls bereitgestellt und die userfür den Befehl und das commandselbst bereitgestellt . Diese Datei sollte nicht ausführbar sein und der Name sollte nur alphanumerische Zeichen und Bindestriche enthalten (weitere Details siehe unten).

Um eine gründliche Antwort zu geben, schauen wir uns die Unterschiede zwischen crontabvs an cron/crond:

crontab -- maintain tables for driving cron for individual users

Für diejenigen, die den Job im Kontext ihres Benutzers auf dem System ausführen möchten, crontabkann die Verwendung durchaus sinnvoll sein.

cron -- daemon to execute scheduled commands

Für diejenigen, die Konfigurationsmanagement verwenden oder Jobs für andere Benutzer verwalten möchten. In diesem Fall sollten wir verwenden cron.

Ein kurzer Auszug aus den Manpages gibt Ihnen einige Beispiele dafür, was zu tun ist und was nicht:

/ etc / crontab und die Dateien in /etc/cron.d müssen Eigentum von root sein und dürfen nicht gruppen- oder anderweitig beschreibbar sein. Im Gegensatz zum Spool-Bereich können die Dateien unter /etc/cron.d oder die Dateien unter /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly und /etc/cron.monthly ebenfalls vorhanden sein Symlinks, vorausgesetzt, sowohl der Symlink als auch die Datei, auf die er verweist, gehören root. Die Dateien unter /etc/cron.d müssen nicht ausführbar sein, während die Dateien unter /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly und /etc/cron.monthly dies tun Sie werden von Laufteilen ausgeführt (weitere Informationen finden Sie unter Laufteile (8)).

Quelle: http://manpages.ubuntu.com/manpages/trusty/man8/cron.8.html

Das Verwalten von Cron auf diese Weise ist aus Systemsicht einfacher und skalierbarer, ist jedoch nicht immer die beste Lösung.

Mike Mackintosh
quelle
1
Es kann erwähnenswert sein, dass <job>keine Dateierweiterung enthalten sein sollte.
JWW
7

Möglicherweise automatisieren Sie dies und möchten nicht, dass ein einzelner Job zweimal hinzugefügt wird. In diesem Fall verwenden Sie:

__cron="1 2 3 4 5 /root/bin/backup.sh"
cat <(crontab -l) |grep -v "${__cron}" <(echo "${__cron}")

Dies funktioniert nur, wenn Sie BASH verwenden. Mir ist die korrekte DASH ( sh) -Syntax nicht bekannt .

Update: Dies funktioniert nicht, wenn der Benutzer noch keine Crontab hat. Ein zuverlässigerer Weg wäre:

(crontab -l ; echo "1 2 3 4 5 /root/bin/backup.sh") | sort - | uniq - | crontab - 

Wenn Ihre Distribution dies unterstützt, können Sie alternativ auch eine separate Datei verwenden:

echo "1 2 3 4 5 /root/bin/backup.sh" |sudo tee /etc/crond.d/backup

Fand diese in einer anderen SO-Frage .

kvz
quelle
Vielleicht sh statt bash verwenden?
KVZ
Ich sh: 1: Syntax error: "(" unexpectedbenutze immer noch sh .
Batandwa
Dies funktioniert nur, wenn Sie BASH verwenden. Mir ist die korrekte DASH (sh) -Syntax nicht bekannt. Die Antwort wurde ebenfalls aktualisiert
kvz
1
fwiw, ich bekomme diesen Fehler mit bash, wenn zwischen <und ein Leerzeichen steht (. Das bedeutet , dass es < (fehlschlägt, aber <(funktioniert, es sei denn, Ihr Zeitplan enthält Sternchen ...
Doublesharp
Ich glaube, das ist der richtige Weg:cat <(crontab -l |grep -v "${CRON}") <(echo "${CRON}") | crontab -
Stanislav
5

Für eine schöne schnelle und schmutzige Erstellung / Ersetzung einer Crontab aus einem BASH-Skript habe ich diese Notation verwendet:

crontab <<EOF
00 09 * * 1-5 echo hello
EOF
Gibbsoft
quelle
5

Eine Variante, die crontab nur bearbeitet, wenn dort die gewünschte Zeichenfolge nicht gefunden wird:

CMD="/sbin/modprobe fcpci"
JOB="@reboot $CMD"
TMPC="mycron"
grep "$CMD" -q <(crontab -l) || (crontab -l>"$TMPC"; echo "$JOB">>"$TMPC"; crontab "$TMPC")
Gerald Schade
quelle
3

Wenn Sie Vixie Cron verwenden, z. B. auf den meisten Linux-Distributionen, können Sie einfach eine Datei mit dem einzelnen Cronjob in /etc/cron.d ablegen.

Dies funktioniert natürlich nur für root. Wenn Ihr System dies unterstützt, sollten Sie dort mehrere Beispiele sehen. (Beachten Sie den in der Zeile enthaltenen Benutzernamen in derselben Syntax wie die alte / etc / crontab.)

Es ist eine traurige Fehlfunktion in cron, dass es keine Möglichkeit gibt, dies als normaler Benutzer zu handhaben, und dass so viele cron-Implementierungen überhaupt keine Möglichkeit haben, damit umzugehen.

Futter
quelle
2

Also, in Debian, Ubuntu und vielen ähnlichen Debian-basierten Distributionen ...

Es gibt einen Verkettungsmechanismus für Cron-Tasks, der eine Konfigurationsdatei aufnimmt, bündelt und zu Ihrem laufenden Cron-Dienst hinzufügt.

Sie können eine Datei unter /etc/cron.d/somefilename ablegen, wobei somefilename beliebig ist.

sudo echo "0,15,30,45 * * * * ntpdate -u time.nist.gov" >> /etc/cron.d/vmclocksync

Lassen Sie uns dies zerlegen:

sudo - weil Sie erhöhte Berechtigungen benötigen, um cron-Konfigurationen im Verzeichnis / etc zu ändern

Echo - ein Fahrzeug, um eine Ausgabe auf Standardausgang zu erzeugen. printf, cat ... würde auch funktionieren

"- Verwenden Sie ein doppeltes Anführungszeichen am Anfang Ihrer Zeichenfolge, Sie sind ein Profi

0,15,30,45 * * * * - der Standard-Cron-Laufplan, der alle 15 Minuten ausgeführt wird

ntpdate -u time.nist.gov - der eigentliche Befehl, den ich ausführen möchte

"- weil meine ersten doppelten Anführungszeichen einen Kumpel benötigen, um die ausgegebene Zeile zu schließen

>> - Die doppelte Umleitung wird angehängt anstatt überschrieben *

/etc/cron.d/vmclocksync - vmclocksync ist der Dateiname, den ich ausgewählt habe. Er befindet sich in /etc/cron.d/


* Wenn wir die> Umleitung verwenden, können wir garantieren, dass wir nur einen Aufgabeneintrag haben. Es besteht jedoch die Gefahr, dass andere Regeln in einer vorhandenen Datei weggeblasen werden. Sie können selbst entscheiden, ob eine mögliche Zerstörung mit> richtig ist oder ob mögliche Duplikate mit >> für Sie sind. Alternativ können Sie etwas Verworrenes oder Beteiligtes tun, um zu überprüfen, ob der Dateiname vorhanden ist, ob etwas darin enthalten ist und ob Sie ein Duplikat hinzufügen - aber ich habe etwas zu tun und kann das nicht tun Sie jetzt.

BradChesney79
quelle
2

Bash-Skript zum Hinzufügen von Cron-Jobs ohne den interaktiven Editor. Der folgende Code hilft beim Hinzufügen eines Cronjobs mithilfe von Linux-Dateien.

#!/bin/bash

cron_path=/var/spool/cron/crontabs/root

#cron job to run every 10 min.
echo "*/10 * * * * command to be executed" >> $cron_path

#cron job to run every 1 hour.
echo "0 */1 * * * command to be executed" >> $cron_path
akash
quelle
1
Ich weiß, es war eine lange Zeit, aber dies ist immer noch die einzig gute Antwort, da alle am meisten gewählten die alten Cron entfernen, anstatt nur die neue anzuhängen.
Afe
1
Dieser installiert keinen Cron. Es wird nur an eine Datei angehängt. Sie müssen den Cron-Prozess irgendwie benachrichtigen, um den neuen Eintrag zu installieren.
Apoorv Parijat
1

Hier ist eine Bash-Funktion zum Hinzufügen eines Befehls crontabohne Duplizierung

function addtocrontab () {
  local frequency=$1
  local command=$2
  local job="$frequency $command"
  cat <(fgrep -i -v "$command" <(crontab -l)) <(echo "$job") | crontab -
}
addtocrontab "0 0 1 * *" "echo hello"
Klas Mellbourn
quelle
1
CRON="1 2 3 4 5 /root/bin/backup.sh" 
cat < (crontab -l) |grep -v "${CRON}" < (echo "${CRON}")

Fügen Sie den Parameter -w hinzu, um den genauen Befehl grep zu erhalten, ohne dass der Parameter -w den Cronjob "testing" hinzufügt, wodurch der Cron-Job "testing123" gelöscht wird.

Skriptfunktion zum Hinzufügen / Entfernen von Cronjobs. Keine doppelten Einträge:

cronjob_editor () {         
# usage: cronjob_editor '<interval>' '<command>' <add|remove>

if [[ -z "$1" ]] ;then printf " no interval specified\n" ;fi
if [[ -z "$2" ]] ;then printf " no command specified\n" ;fi
if [[ -z "$3" ]] ;then printf " no action specified\n" ;fi

if [[ "$3" == add ]] ;then
    # add cronjob, no duplication:
    ( crontab -l | grep -v -F -w "$2" ; echo "$1 $2" ) | crontab -
elif [[ "$3" == remove ]] ;then
    # remove cronjob:
    ( crontab -l | grep -v -F -w "$2" ) | crontab -
fi 
} 
cronjob_editor "$1" "$2" "$3"

geprüft :

$ ./cronjob_editor.sh '*/10 * * * *' 'echo "this is a test" > export_file' add
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file
speefak
quelle
Wenn Sie denselben Befehl zweimal in der Crontab haben (zu unterschiedlichen Zeiten ausgeführt), werden beim Entfernen beide Zeilen gelöscht.
Michaelkay
1

Meine bevorzugte Lösung hierfür wäre:

(crontab -l | grep . ; echo -e "0 4 * * * myscript\n") | crontab -

Dadurch wird sichergestellt, dass Sie die leere neue Zeile unten korrekt behandeln. Um Probleme mit crontab zu vermeiden, sollten Sie die crontab-Datei normalerweise mit einer leeren neuen Zeile beenden. Und das obige Skript stellt sicher, dass zuerst alle Leerzeilen mit dem "grep" entfernt werden. Teil, und fügen Sie dann am Ende eine neue leere Zeile mit dem "\ n" am Ende des Skripts hinzu. Dadurch wird auch verhindert, dass über Ihrem neuen Befehl eine Leerzeile angezeigt wird, wenn Ihre vorhandene Crontab-Datei mit einer Leerzeile endet.

gsus
quelle
1
echo "0 * * * * docker system prune --force >/dev/null 2>&1" | sudo tee /etc/cron.daily/dockerprune
user11547308
quelle
0

Nein, in crontab gibt es keine Option zum Ändern der Cron-Dateien.

Sie müssen: Nehmen Sie die aktuelle Cron-Datei (crontab -l> newfile), ändern Sie sie und platzieren Sie die neue Datei (crontab newfile).

Wenn Sie mit Perl vertraut sind, können Sie dieses Modul Config :: Crontab verwenden .

LLP, Andrea

andcoz
quelle
0

Skriptfunktion zum Hinzufügen von Cronjobs. Überprüfen Sie doppelte Einträge, verwendbare Ausdrücke *> "

cronjob_creator () {         
# usage: cronjob_creator '<interval>' '<command>'

  if [[ -z $1 ]] ;then
    printf " no interval specified\n"
elif [[ -z $2 ]] ;then
    printf " no command specified\n"
else
    CRONIN="/tmp/cti_tmp"
    crontab -l | grep -vw "$1 $2" > "$CRONIN"
    echo "$1 $2" >> $CRONIN
    crontab "$CRONIN"
    rm $CRONIN
fi
}

geprüft :

$ ./cronjob_creator.sh '*/10 * * * *' 'echo "this is a test" > export_file'
$ crontab  -l
$ */10 * * * * echo "this is a test" > export_file

Quelle: mein Gehirn;)


quelle
-5

Sie können wahrscheinlich den Standardeditor in ed ändern und einen Heredoc zum Bearbeiten verwenden.

EDITOR=ed
export EDITOR

crontab -e << EOF
> a
> * * * * * Myscript
> * * * * * AnotherScript
> * * * * * MoreScript
> .
> w
> q
> EOF

Beachten Sie das führende > in diesem Code bedeutet, dass die Eingabetaste gedrückt wird, um eine neue Zeile zu erstellen.

Die a bedeutet ANHANG, damit nichts überschrieben wird.

Die .bedeutet, dass Sie mit der Bearbeitung fertig sind.

Das w bedeutet SCHREIBEN der Änderungen.

Das q bedeutet BEENDEN oder beenden.

Sie können es überprüfen

crontab -l

Sie können auch einen Eintrag löschen.

EDITOR=ed
export EDITOR

crontab -e << EOF
> /Myscript/
> d
> .
> w
> q
> EOF

Dadurch wird der crontab-Eintrag mit Myscript gelöscht.

Das d bedeutet, das Muster innerhalb des / / zu löschen .

Nein, überprüfe es noch einmal

crontab -l

Diese Lösung funktioniert in einem Skript zu wenig als das > natürlich :-)

Jetchisel
quelle