So richten Sie einen Root-Cron-Job ordnungsgemäß ein

36

Ich habe versucht, einen Root-Cron-Job einzurichten, um ein Bash-Skript als Root auszuführen, das in Minute 7,37 ausgeführt wird, jede Stunde, jeden Tag im Monat, jeden Monat. Dieses Skript befindet sich in /usr/binund heißt tunlrupdate.sh. Es aktualisiert den DNS von Tunlr.

$ ls -l /usr/bin/tunlrupdate.sh 
-rwxr-xr-x 1 root root 2133 Sep 24 15:42 /usr/bin/tunlrupdate.sh

Dieses Bash-Skript finden Sie hier .

Beim Aufrufen schreibt das Skript, was in einem Protokoll in passiert /var/log/tunlr.log

Um diesen root-cron-Job hinzuzufügen, habe ich den Standard für die crontab von root verwendet

sudo crontab -e

Und diese 2 Zeilen am Ende eingefügt. Ich erwarte, dass cron das Skript als root ausführt.

# check for updated Tunlr DNS every 30 minutes at the hour + 7 mn and hour + 37 mn
07,37 * * * * root /usr/bin/tunlrupdate.sh

Ein späterer Befehl sudo crontab -lbestätigte, dass der Cron-Job eingefügt wurde.

Ich habe Ubuntu neu gestartet und habe in der Protokolldatei überprüft, ob der Cron-Job ordnungsgemäß gestartet wurde. Die Protokolldatei enthält jedoch nichts, /var/log/tunlr.logwas bedeutet, dass der Job nie erfolgreich gestartet wurde.

Ich habe das überprüft, wenn ich das Skript über die Befehlszeile ausführe

sudo /usr/bin/tunlrupdate.sh

dann wird die Logdatei entsprechend aktualisiert.

Warum läuft dieser Cron-Job in meinem System nicht wie geplant?

UPDATE 1: Alle bisher vorgeschlagenen Lösungen funktionieren nicht. Ich danke Olli für eine CLI, die das Systemprotokoll auflistet sudo grep CRON /var/log/syslog. Allerdings habe ich einen CRON-Fehler bekommen

CRON[13092]: (root) CMD (  [ -x /usr/lib/php5/maxlifetime ] && [ -d /var/lib/php5 ]
&& find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php
/maxlifetime) ! -execdir fuser -s {} 2>/dev/null \; -delete)

mit dem vorgeschlagenen PATH = Einfügen und Verwenden des absoluten Pfads von root für Funktionen im Skript oder ohne diese hier vorgeschlagenen Lösungen. Ich bekomme immer noch diesen Fehler.

Nach einiger Suche geortet ich in der Datei die Fehler /usr/lib/php5/maxlifetimewie erklärt hier :Change #!/bin/sh -e --> #!/bin/sh -x

Dann das CRON-Fehlerprotokoll in meinem System auflisten

sudo grep CRON /var/log/syslog
Feb 11 18:07:01 Marius-PC CRON[14067]: (root) CMD (root /usr/bin/tunlrupdate.sh)
Feb 11 18:07:01 Marius-PC CRON[14066]: (root) MAIL (mailed 1 byte of output; but got
status 0x00ff, #012)

Das Bash-Skript wird immer noch nicht ausgeführt. Dieses Mal wird kein Fehler im Protokoll angezeigt. Um sicherzugehen, dass dies nicht der Inhalt des Skripts war, habe ich das Skript auf die folgenden 3 Zeilen reduziert:

#!/bin/bash
LOGFILE=/var/log/tunlr.log
echo $LOGFILE >> $LOGFILE

Ich bekomme den Cronjob immer noch nicht durch. In die Protokolldatei wird nichts geschrieben. So kann sogar ein leeres Skript nicht in Cron ausgeführt werden? Ich verstehe es nicht. Ich weiß, dass ich ein Skript probiere, das auf diese zwei Zeilen reduziert ist:

#!/bin/bash
exit 0

Und immer noch das gleiche Fehlerprotokoll. Das Cron-Skript geht nicht durch ...

Antonio
quelle
Wenn du willst, dass es ein "root" -Cronjob ist, musst du root sein, dann gib crontab -e ein. Außerdem müssen Sie sich nur als root anmelden (Konsolentyp "su root") und dann crontab -e (sudo wird in diesem Fall nicht benötigt).
Wolfgang
Gut. Ich verstehe den Sinn Ihrer Antwort nicht? Die Eingabe von $ sudo crontab -e erledigte den Job wie von $ sudo crontab -l gemeldet, dh die Zeile, die den neuen Job beschreibt, wurde zum cron des Roots hinzugefügt. Da der Job per se nicht im Benutzer cron vorhanden ist, zB $ crontab -l zeigt nicht an, dass hier ein Cron-Job hinzugefügt wurde.
Antonio
@WolfgangVogl er hat "sudo" benutzt was wie erwartet funktioniert.
Alexis Wilke

Antworten:

68

Wenn Sie ein Skript als normaler Benutzer ausführen möchten :

crontab -e

Und füge die Zeile hinzu:

07,37 * * * * /usr/bin/tunlrupdate.sh

Wenn Sie Ihr Skript als root ausführen möchten :

sudo crontab -e

Und füge die gleiche Zeile hinzu:

07,37 * * * * /usr/bin/tunlrupdate.sh
Guillaume
quelle
@NineCattoRules Wenn Sie die Ausgabe nicht löschen, was sehen Sie?
Angelo Fuchs
@AngeloFuchs alter Kommentar ... sicherlich habe ich diesen Befehl als root ( sudo crontab -estatt crontab -e) ausprobiert . Oder etwas anderes, trotzdem funktioniert es
NineCattoRules
10

Nun, endlich die funktionierende Lösung. Im Syslog sah ich die sich wiederholenden und faszinierenden:

CRON[18770]: (root) CMD (root /usr/bin/tunlrupdate.sh)

Das klingt so, als ob root nicht als cmd erkannt wurde. Da habe ich schon den Cron des Roots mit benutzt $ sudo /usr/bin/tunlrupdate.sh. Dann habe ich mit dem Originalskript (korrigiert für einen Fehler im UNIX-Cmd-Datum:% m, was Monat ist, wurde für Minuten verwendet, was% M ist) Folgendes versucht (was die Wurzel aus der Cron-Zeile entfernt):

$ sudo crontab -e
# check for updated Tunlr DNS every 30 minutes at the hour + 7 mn and hour + 37 mn
07,37 * * * * /usr/bin/tunlrupdate.sh

Dies stellte sich als endgültige Lösung heraus. [Obwohl ich zahlreiche Literaturstellen gefunden habe, in denen die fehlerhafte Linie mit der Wurzel in der Cron-Linie angegeben ist. Das war ein Fehler].

Antonio
quelle
Guter Punkt, Olli. Da stimme ich Ihnen zu. Als Referenz wird der Benutzer crontab in / var / spool / cron / crontabs / Benutzername oder für root / var / spool / cron / crontabs / root gespeichert. Siehe diese Seite askubuntu.com/questions/216692/where-is-the-user-crontab-stored Der enthaltene Ordner ist bereits und gibt den Namen des Benutzers an.
Antonio
Nun, Sie sollten diese Informationen nicht benötigen, da Sie Crontab-Dateien nur mit dem crontabBefehl bearbeiten sollten (außer Crontab-Dateien unter /etc).
Olli
1
@Antonio Die Scores mit dem Feld Benutzername werden nur in /etc/crontab(der systemweiten crontab) verwendet. Wenn sudo crontab -eSie mit root's crontab arbeiten, finden Sie es normalerweise in/var/spool/cron/crontabs
Matijs
2

Ein "Problem" bei Cron ist das Fehlen von Umgebungsvariablen (aus offensichtlichen Sicherheitsgründen). Vermutlich fehlen Ihnen PATH und HOME. Sie können diese direkt im Skript oder in der crontab-Datei definieren.

# check for updated Tunlr DNS every 30 minutes at the hour + 7 mn and hour + 37 mn
PATH=/usr/bin
07,37 * * * * root /usr/bin/tunlrupdate.sh

Sie müssen testen, bis alle erforderlichen Variablen gemäß den Anforderungen des Skripts definiert sind.

Alexis Wilke
quelle
1
Dies ist die einzige Antwort, die für mich tatsächlich funktioniert hat. Ich habe die SHELL- und PATH-Anweisungen aus der /etc/crontabDatei kopiert und in die eingefügt, sudo crontab -eund der Befehl wurde problemlos als root ausgeführt. Vielen Dank!
Terrance
0

Cron-Fehlermeldungen werden normalerweise standardmäßig per E-Mail gesendet. Sie können überprüfen, ob es eine E-Mail für root gibt sudo mail, oder indem Sie nur den Inhalt von /var/mail/rootz sudo less /var/mail/root.


Wenn E-Mail-Nachrichten nicht helfen, überprüfen Sie auch /var/log/syslog:

sudo grep CRON /var/log/syslog

Wie Alexis Wilke bereits sagte, haben Crons unterschiedliche Mechanismen zum Setzen von Umgebungsvariablen.

Dein Drehbuch braucht

PATH=/sbin:/bin:/usr/bin

zur Crontab. HOMEsollte nicht nötig sein. Sie sollten absolute Pfade in Ihre Skripte verwenden, zB /bin/datestatt date. Sie können geeignete Pfade für jeden Befehl finden which command_name, z

$ which date
/bin/date
Olli
quelle
Laufen Sie Ihr vorgeschlagenes grep-CRON in / var / log / syslog. Ich habe die Täuschung bekommen. 11. Februar 14:37:01 Marius-PC CRON [7826]: (root) CMD (root /usr/bin/tunlrupdate.sh) 11. Februar 14: 37:01 Marius-PC CRON [7825]: (root) MAIL (1 Byte der Ausgabe gesendet; Status 0x00ff, # 012) 11.02. 14:39:01 Marius-PC CRON [7849]: (root) CMD ( [-x / usr / lib / php5 / maxlifetime] && [-d / var / lib / php5] && find / var / lib / php5 / -depth -indepth 1 -maxdepth 1 -type f -cmin + $ (/ usr / lib / php5 / maxlifetime)! -execdir fuser -s {} 2> / dev / null \; -delete) Wenn ich in cron eine Definition für PATH hinzufüge, haben diese keine Auswirkungen auf mein System $ PATH?
Antonio
Diese Ausgabe besagt, dass versucht wurde, eine E-Mail zu senden, dies jedoch fehlgeschlagen ist. Das bedeutet, dass Sie diese Fehlermeldung nicht erhalten /var/mail/root. Sie können entweder das Problem beheben oder es mitPATH=...
Olli
@ Antonio, alternativ verwenden Sie diese gepatchte Version
Olli
Vielen Dank. Ich weiß, dass ich die System-E-Mail nicht konfiguriert habe und wusste, dass sie nicht erfolgreich war. Ich hatte das Skript bereits so geändert, dass es für jede aufgerufene Funktion den absoluten Pfad verwendet. Das Letzte, was ich in meiner vorherigen Frage gefragt habe, ist, dass eine PATH-Definition in crontab meine $ PATH-Systemvariable nicht durcheinander bringt.
Antonio
1
In der Zwischenzeit war ich damit beschäftigt, einen Fehler im Datumsformat des ursprünglichen Skripts zu korrigieren. Es wurde mit% m (die für Monat nicht Minute ist) anstelle von% M ...
Antonio
0

Sie können diese Zeile in Ihr Skript einfügen. Nachdem Sie die Cron-Protokolle überprüft und bestätigt haben, dass Ihr Auftrag ausgeführt wurde, können Sie den gleichen $ PATH von Crontabs erhalten.

/bin/echo $PATH > /root/path.txt

Und wahrscheinlich ist das Beste, was Sie tun können, um Probleme in Cron-Skripten zu diagnostizieren, alle Umgebungsvariablen von SO mit dem Befehl env in Ihrem Skript abzurufen. Fügen Sie diese Zeile einfach zu Ihrem Skript hinzu. Dann können Sie die Ausgabe analysierenallEvnVars.txt

/usr/bin/env > /root/allEvnVars.txt

Ein weiterer Trick besteht darin, die Ausgabe des Skripts an eine bestimmte Stelle zu lenken. Hinzufügen der /root/log.log. Auf diese Weise bleibt die gesamte Ausgabe des Skripts erhalten/root/log.log

07,37 * * * * root /usr/bin/tunlrupdate.sh  > /root/log.log

Sie können das Skript auch so planen, dass es jede Minute ausgeführt wird, um die Tests und Überprüfungen zu erleichtern.

*/1 * * * * root /usr/bin/tunlrupdate.sh  > /root/log.log
Cassio Seffrin
quelle