Wissensdatenbank · Linux

Konfiguration von Cron-Jobs

Zuletzt aktualisiert am 2020-01-18

Bitte prüfen Sie, ob Sie über ein gültiges E-Mail-Konto zum Empfang der E-Mails verfügen. Lesen Sie dazu bitte den folgenden Artikel zur „Konfiguration von Cron-Jobs“. Falls Sie weiterhin Hilfe benötigen, erstellen Sie bitte ein Support-Ticket.

Cron ist ein häufig verwirrender und falsch konfigurierter Aspekt des Betriebssystems. Technisch gesehen ist cron nur der Clock-Daemon (/usr/sbin/cron oder vielleicht /usr/sbin/crond), der Befehle zu bestimmten Zeiten ausführt. Eine Handvoll Konfigurationsdateien und Programme fließen jedoch in die Erstellung des Cron-Pakets ein. Wie viele Systemprozesse endet cron nie.

Die Kontrolldateien für cron sind die cron-Tabs oder crontabs. Die Crontabs befinden sich oft in /var/spool/cron/crontab. Auf SuSE finden Sie sie jedoch in /var/spool/cron/tabs. Die Namen der Dateien in diesem Verzeichnis sind die Namen der Benutzer, die die Cron-Jobs einreichen.

Anders als bei anderen UNIX-Varianten wartet der Linux-Cron-Daemon nicht im Ruhezustand bis zum Start des nächsten Cron-Jobs. Stattdessen prüft Cron nach Abschluss eines Jobs einmal pro Minute, ob weitere Jobs auszuführen sind. Außerdem sollten Sie die Dateien nicht direkt bearbeiten. Sie können sie zwar mit einem Texteditor wie vi bearbeiten, doch besteht dabei die Gefahr, dass etwas durcheinandergerät. Verwenden Sie daher das von Linux bereitgestellte Werkzeug crontab. (Weitere Details finden Sie auf der man-Page.)

Das Hilfsprogramm crontab erfüllt mehrere Funktionen. Zum einen werden damit Dateien mit Cron-Jobs an das System übergeben. Zum anderen kann es den Inhalt Ihrer crontab anzeigen. Als root können Sie außerdem Jobs für beliebige Benutzer übergeben und auflisten. Das Problem ist, dass Jobs nicht einzeln übergeben werden können. Mit crontab müssen Sie alle Jobs gleichzeitig übergeben.

Das mag zunächst etwas lästig klingen. Sehen wir uns jedoch den Vorgang des „Hinzufügens“ eines Jobs an. Um einen Cron-Job hinzuzufügen, müssen Sie zunächst den Inhalt der vorhandenen crontab mit der Option -l ausgeben. Wenn Sie root sind und der crontab eines anderen Benutzers etwas hinzufügen möchten, verwenden Sie die Option -u gefolgt vom Anmeldenamen des Benutzers. Leiten Sie diese crontab anschließend in eine Datei um, die Sie dann bearbeiten können. (Beachten Sie, dass crontab auf manchen Systemen die Option -e („edit“) bietet, die Ihnen die gesamte Arbeit abnimmt. Weitere Details finden Sie auf der man-Page.)

Angenommen, Sie sind der Benutzer root und möchten der crontab des Benutzers UUCP etwas hinzufügen. Lassen Sie sich zunächst mit folgendem Befehl die Ausgabe des vorhandenen crontab-Eintrags anzeigen:

crontab -l -u uucp >/tmp/crontab.uucp

Um einen Eintrag hinzuzufügen, fügen Sie einfach eine neue Zeile ein. Speichern Sie die Datei, beenden Sie den Editor und führen Sie das Hilfsprogramm crontab erneut aus. Lassen Sie diesmal die Option -l zum Auflisten weg und geben Sie stattdessen den Namen der Datei an. crontab kann auch Eingaben von stdin entgegennehmen. Sie könnten also den Dateinamen weglassen und die Cron-Jobs direkt auf der Kommandozeile eingeben. Beachten Sie, dass jede vorherige crontab unabhängig von der verwendeten Methode entfernt wird.

Die Datei /tmp/crontab.uucp enthält nun den Inhalt von UUCPs crontab. Es könnte ungefähr so aussehen:

39,9 * * * * /usr/lib/uucp/uudemon.hour > /dev/null
10 * * * * /usr/lib/uucp/uudemon.poll > /dev/null
45 23 * * * ulimit 5000; /usr/lib/uucp/uudemon.clean > /dev/null
48 10,14 * * 1-5 /usr/lib/uucp/uudemon.admin > /dev/null

Trotz des Erscheinungsbilds besteht jeder crontab-Eintrag nur aus sechs Feldern. Die ersten fünf geben den Zeitpunkt der Ausführung an, das sechste enthält den eigentlichen Befehl. Die ersten fünf Felder werden durch ein Leerzeichen oder einen Tabulator getrennt und stehen der Reihe nach für folgende Einheiten:

Minuten (0-59)
Stunde (0-23)
Tag des Monats (1-31)
Monat des Jahres (1-12)
Wochentag (0-6, 0=Sonntag)
Um alle möglichen Werte anzugeben, verwenden Sie ein Sternchen (*). Einen einzelnen Wert geben Sie an, indem Sie genau diesen Wert eintragen. In der zweiten Zeile des vorherigen Beispiels steht im ersten Feld beispielsweise der Wert 10, also 10 Minuten nach der vollen Stunde. Da die übrigen vier Zeitfelder Sternchen enthalten, wird der Befehl an jedem Tag in jeder Stunde jeweils 10 Minuten nach der vollen Stunde ausgeführt.

Wertebereiche bestehen aus dem Anfangswert, einem Bindestrich und dem Endwert. In der vierten Zeile steht im Feld für den Wochentag beispielsweise der Bereich (1-5). Das bedeutet, dass der Befehl nur an den Tagen 1-5, also von Montag bis Freitag, ausgeführt wird.

Um verschiedene Werte anzugeben, die nicht innerhalb eines Bereichs liegen, trennen Sie die einzelnen Werte durch ein Komma. Im vierten Beispiel hat das Stundenfeld die beiden Werte 10 und 14. Das bedeutet, dass der Befehl um 10 Uhr und 14 Uhr ausgeführt wird.

Beachten Sie, dass sich Zeitangaben addieren. Sehen wir uns dazu ein Beispiel an:


10 * 1,16 * 1-5 /usr/local/bin/command


Der Befehl wird jeweils 10 Minuten nach jeder vollen Stunde am Ersten und am Sechzehnten sowie von Montag bis Freitag ausgeführt. Fiele der Erste oder der Sechzehnte auf ein Wochenende, würde der Befehl dennoch ausgeführt, da das Feld für den Tag des Monats greift. Das bedeutet jedoch nicht, dass der Befehl zweimal ausgeführt wird, wenn der Erste ein Montag ist.

Ein crontab-Eintrag kann so definiert werden, dass er in anderen Intervallen als nur stündlich oder täglich ausgeführt wird. Die Granularität lässt sich beispielsweise auf alle zwei Minuten oder alle drei Stunden festlegen, ohne dass Sie jeden einzelnen Eintrag in die crontab schreiben müssen.

Angenommen, wir möchten den vorherigen Befehl nicht 10 Minuten nach der vollen Stunde, sondern alle zehn Minuten ausführen. Wir könnten einen Eintrag wie den folgenden erstellen:


0,10,20,30,40,50 * 1,16 * 1-5 /usr/local/bin/command


Dieser Eintrag wird alle 10 Minuten ausgeführt: zur vollen Stunde, 10 Minuten danach, 20 Minuten danach und so weiter. Einfacher geht es, wenn wir den Eintrag so anlegen:


*/10 * 1,16 * 1-5 /usr/local/bin/command


Diese Syntax ist für manche Administratoren möglicherweise neu. (Für mich war sie es.) Der Schrägstrich (/) bedeutet, dass der Befehl innerhalb des angegebenen Intervalls (hier: jede Minute) jeweils nach einer bestimmten Anzahl von Minuten ausgeführt wird, in diesem Fall alle 10 Minuten.

Dies funktioniert auch bei der Angabe eines Bereichs. Soll der Job beispielsweise nur zwischen 20 und 40 Minuten nach der vollen Stunde ausgeführt werden, könnte der Eintrag so aussehen:


20-40 * 1,16 * 1-5 /usr/local/bin/command


Was ist, wenn der Befehl zu diesen Zeiten nur alle drei Minuten ausgeführt werden soll? Die Zeile könnte dann so aussehen:


20-40/3 * 1,16 * 1-5 /usr/local/bin/command


Um es noch komplizierter zu machen, könnten Sie festlegen, dass der Befehl zwischen der vollen Stunde und 20 Minuten danach alle zwei Minuten, zwischen 20 und 40 Minuten danach alle drei Minuten und zwischen 40 Minuten danach und der vollen Stunde alle 5 Minuten ausgeführt wird.


0-20/2,21-40/3,41-59/5 * 1,16 * 1-5 /usr/local/bin/command


Eine wirklich praktische Eigenschaft vieler Linux-Varianten ist, dass Sie Abkürzungen für die Wochentage und die Monate angeben können. Es ist viel einfacher, sich zu merken, dass fri für Freitag steht, als dass es die 5 ist.

Mit Ausnahme bestimmter Fehler in den Zeitfeldern werden Fehler erst gemeldet, wenn cron den Befehl ausführt. Alle Fehlermeldungen und Ausgaben werden per E-Mail an die Benutzer gesendet. Zumindest steht das so in der crontab-Manpage, und es stimmt im Wesentlichen auch. Wie Sie in den vorherigen Beispielen sehen, leiten Sie stdout jedoch nach /dev/null um. Wenn Sie wollten, könnten Sie auch stderr dorthin umleiten, und Sie würden nie erfahren, ob Fehler aufgetreten sind.

Die Ausgabe wird per E-Mail an den Benutzer gesendet, weil es kein echtes Terminal gibt, auf dem die Cronjobs ausgeführt werden. Daher gibt es keinen Bildschirm, auf dem die Fehler angezeigt werden könnten. Außerdem gibt es keine Tastatur, die Eingaben entgegennimmt. Bedeutet das, dass Sie einem Cronjob keine Eingaben übergeben können? Nein. Denken Sie an die Erläuterungen zu Shell-Skripten zurück: Wir können stdin, stdout und stderr neu definieren. So können alle auf Dateien zeigen und sich wie erwartet verhalten.

Ich möchte darauf hinweisen, dass ich davon abrate, im Befehlsfeld der crontab Umleitungen vorzunehmen. Ich halte dort so wenig wie möglich fest. Stattdessen trage ich den absoluten Pfad zu einem Shell-Skript ein. So kann ich den crontab-Eintrag zunächst mit etwas Einfachem testen. Sobald das funktioniert, kann ich Änderungen am Shell-Skript vornehmen, ohne den Cronjob erneut einreichen zu müssen.

Bedenken Sie, dass cron nicht exakt arbeitet. Es synchronisiert sich jeweils auf den Beginn einer Minute. Auf einem stark ausgelasteten System, auf dem Taktsignale verloren gehen, werden Jobs möglicherweise erst einige Minuten nach der geplanten Zeit ausgeführt. Außerdem können andere Prozesse mit höherer Priorität Cronjobs verzögern. In manchen Fällen (insbesondere auf sehr stark ausgelasteten Systemen) werden Jobs, die jede Minute laufen sollen, unter Umständen übersprungen.

Der Zugriff auf cron wird über zwei Dateien gesteuert, die sich beide in /etc befinden. Wenn die Datei cron.allow existiert, können Sie darin festlegen, welche Benutzer cron verwenden dürfen. Die Datei cron.deny legt fest, welchen Benutzern die Verwendung von cron ausdrücklich untersagt ist. Existiert keine der beiden Dateien, haben nur die Systembenutzer Zugriff. Möchten Sie jedoch allen Benutzern Zugriff gewähren, legen Sie eine leere cron.deny-Datei an. Mit anderen Worten: Niemandem wird der Zugriff verweigert.

Es ist oft nützlich, dass root Jobs als anderer Benutzer ausführt, ohne dass der Benutzer gewechselt werden muss (z. B. mit dem Befehl su). Die meisten Linux-Dialekte bieten einen Mechanismus in Form der /etc/crontab-Datei. Diese Datei ist in der Regel nur durch root beschreibbar und in einigen Fällen kann nur root sie lesen (was in Hochsicherheitsumgebungen oft erforderlich ist). Die allgemeine Syntax ist die gleiche wie die Standard-Crontabs, mit ein paar Ausnahmen.

Der erste Unterschied ist der Header, den Sie hier sehen:


SHELL=/bin/sh
PATH=/usr/bin:/usr/sbin:/sbin:/bin:/usr/lib/news/bin
MAILTO=root
#
# check scripts in cron.hourly, cron.daily, cron.weekly, and cron.monthly
#

59 * * * * root rm -f /var/spool/cron/lastrun/cron.hourly
14 0 * * * root rm -f /var/spool/cron/lastrun/cron.daily
29 0 * * 6 root rm -f /var/spool/cron/lastrun/cron.weekly
44 0 1 * * root rm -f /var/spool/cron/lastrun/cron.monthly

Die Variable SHELL legt fest, in welcher Shell jeder Befehl ausgeführt wird. Die Variable PATH entspricht der üblichen Umgebungsvariablen PATH und definiert den Suchpfad. Die Variable MAILTO gibt an, wer die E-Mail-Nachrichten erhalten soll, darunter Fehlermeldungen und die Standardausgabe der ausgeführten Befehle.

Die Struktur der eigentlichen Einträge ist mit Ausnahme des Benutzernamens (root jeweils hier) ziemlich gleich. Auf diese Weise können die Root-Benutzer (oder wer auch immer /etc/crontab bearbeiten kann) definieren, welcher Benutzer den Befehl ausführt. Denken Sie daran, dass dies eine große Sicherheitslücke sein kann. Wenn jemand in diese Datei schreiben kann, kann er einen Eintrag erstellen, der als root ausgeführt wird und somit die vollständige Kontrolle über das System hat.

Der nächste Befehl der cron-„Suite“ ist at. Er dient dazu, einen Befehl zu einem bestimmten Zeitpunkt auszuführen. Der Unterschied besteht darin, dass ein at-Job nach der Ausführung aus dem System verschwindet. Wie bei cron beeinflussen zwei Dateien, at.allow und at.deny, das Programm at auf die gleiche Weise.

Der Befehl batch wird ebenfalls verwendet, um Befehle einmalig auszuführen. Mit batch übergebene Befehle werden jedoch ausgeführt, sobald das System dazu kommt, also wenn es weniger ausgelastet ist, beispielsweise mitten in der Nacht. Je nach Systemlast ist es möglich, dass solche Jobs über den ganzen Tag verteilt werden.

Beachten Sie das Verhalten von at und batch. Beide nehmen die Namen der Befehle über die Kommandozeile entgegen und nicht als Argumente des Befehls selbst. Sie müssen zunächst den Befehl ausführen, woraufhin eine neue Zeile erscheint, in der Sie die auszuführenden Befehle eingeben. Drücken Sie nach jedem Befehl die Eingabetaste. Wenn Sie fertig sind, drücken Sie Strg-D.

Da diese beiden Befehle Befehle über stdin entgegennehmen, müssen Sie die Befehle nicht jedes Mal in einer neuen Zeile eingeben. Eine Möglichkeit besteht darin, die Eingabe aus einer Datei umzuleiten. Zum Beispiel:


at now +1 hour < command_list


Dabei ist command_list eine Datei, die eine Liste von Befehlen enthält. Sie könnten at (oder batch) auch am Ende einer Pipe verwenden:


cat command_list | at now + 1 hour

cat command_list | batch

Eine weitere interessante Sache über beide at und Batch ist, dass sie eine Art Shell-Skript erstellen, um Ihren Befehl auszuführen. Wenn Sie bei oder Batch ausführen, wird eine Datei in /usr/spool/cron/atjobs erstellt. Diese Datei enthält die Systemvariablen, die Sie normalerweise definiert hätten, sowie einige andere Informationen, die in /usr/lib/cron.proto enthalten sind. Dies schafft im Wesentlichen eine Umgebung, als ob Sie sich angemeldet hätten.

← Alle Knowledgebase Artikel

Tell us what you need

Compare available plans or describe your workload so we can discuss a suitable starting point.