logoOL.gif
user_gelb_schwarz_or.gif
logoUL.gif
logoUR.gif claim.gif
LinuxUser LinuxCommunity EasyLinux Linux-Magazin International
      Anzeige
TFT Monitor bei Mercateo kaufen.
Neues Netbook? Ein Preisvergleich lohnt sich.
Bei uns finden sie Notebooks, PDAs und Drucker mit Testberichten und Tipps.
Diamant Buchhaltungssoftware – transparent und detailliert auch für die Konzernbuchhaltung.
Günstige Shareware Programme als direkte Downloads im Software Portal.
Bis zu 70% sparen durch Preisvergleich.
      Anzeige

Erschienen in LinuxUser 12/2000

Jobs mit Cron abarbeiten

Diener auf die Minute

von Patricia Jung
 [ Dali: The_Disintegration_of_the_Persistence_of_Memory ]


So chaotisch Linuxer/innen auch manchmal sein mögen -- meistens werkelt unbeachtet im Hintergrund ein Pünktlichkeitsfanatiker namens cron(d) auf ihren Rechnern. Ihn zu nutzen, kann eine Menge langweilige Arbeit ersparen.

Ob man seinen Rechner der MP3-Sammlung sei dank allmorgendlich als Wecker missbrauchen oder sich langweiliger, immer wiederkehrender Aufgaben bei der Systemadministration entledigen möchte -- die Lösung des Problems heißt Cron, ein Dienst, der als Dämon namens cron oder crond still im Hintergrund vor sich hin werkelt.

Die Zentrale

Die zentrale Anlaufstelle, um sich der lästigen Pflichten zu entledigen, trägt den Namen /etc/crontab. Jede Minute kommt der Linux-Cron-Daemon angestolpert, um darin und in den persönlichen Crontabellen der User nachzuschauen, ob sich ein Auftrag findet, den es in dieser Minute zu erledigen gilt.

Während normalsterbliche Benutzer/innen sich des Programms crontab bedienen, das einen Editor aufruft und die syntaktische Korrektheit der Aufträge für cron überwacht, liegt die Verantwortung für die systemweite Crontabelle allein bei der Administratorin root und ihrem Lieblingseditor.

Auf den ersten Blick mag die Auftragsliste für Cron -- Listing 1 zeigt ein Beispiel -- etwas Erschrecken auslösen. Doch bei genauerer Betrachtung und/oder einem vergnüglichen Abend mit der ausnahmsweise auch für Nicht-Gurus gut verständlichen Manpage (man 5 crontab) kommt man recht schnell hinter das Schema, das von Tabelle 1 erklärt wird.


man 5: Wie in der Rubrik "Zu Befehl" im LinuxUser 02/2000 ausführlich erklärt, sind die Manpages nach Anwendungsgebiet in sogenannte Sektionen gegliedert. Mit crontab z. B. können zwei verschiedene Dinge gemeint sein: das Programm oder die Datei. Informationen zu ersterem findet man in Sektion 1 mit dem Befehl man 1 crontab oder kurz man crontab. Die Manpage zur Datei namens crontab hingegen ist in Sektion 5, also mit man 5 crontab, zu finden. In welchen Sektionen man etwas über crontab findet, erfährt man mit man -f crontab.

Tabelle 1: Format eines Crontab-Eintrags
Minute(n) Stunde(n) Tag(e) Monat(e) Wochentag(e) User auszuführender Befehl
mögliche Werte
0--59 oder der Platzhalter *, der für alle Minuten von 0--59 steht 0--23, * ("jede Stunde") 1--31, * ("jeden Tag im Monat") 1--12, * ("jeden Monat"), Jan--Dec oder jan--dec 0--7, wobei sowohl 0 als auch 7 für Sonntag stehen können, * ("jeden Wochentag"), Sun--Sat oder sun--sat nur in /etc/crontab: der Username der Benutzerin, mit deren Rechten der Befehl ausgeführt werden soll

Damit Cron seine Aufträge versteht, müssen sie in einem fest vorgegebenen sechs- (bei mit crontab erstellten, benutzerdefinierten Cron-Tabellen) bzw. siebenspaltigen (/etc/crontab) Tabellenformat aufgeschrieben werden. Ein Eintrag darf dabei keinen Zeilenumbruch enthalten und (in aller Regel) 1024 Zeichen nicht überschreiten.

Wer der Übersichtlichkeit wegen gern den einen oder anderen harten Zeilenumbruch einfügen will, kann das zwar tun, doch muss dann als letztes Zeichen vor dem Gebrauch der Enter-Taste ein \ stehen.

Als Spaltentrenner dienen normalerweise Leer- oder Tabulatorzeichen, und mit einem # am Anfang einer Zeile bestimmt man den Rest als wichtig für Menschen, jedoch unwichtig für Cron, also zum Kommentar.

Die systemweite Aufgabenliste für Cron in Listing 1 enthält demnach drei Aufträge: Täglich um 6.42 Uhr wird der Crondämon mit den Rechten von root das Kommando run-parts /etc/cron.daily ausführen. Jeden Sonntag (7) um 6.47 Uhr ist ein Lauf von run-parts /etc/cron.weekly fällig, und an jedem Ersten des Monats kommt fünf Minuten später (6.52 Uhr) noch ein run-parts /etc/cron.monthly hinzu.

Advanced Features

Neben den in Tabelle 1 angegebenen "einfachen" Angaben gibt es bei den unter Linux verwendeten Cron-Daemonen auch noch ein paar komplexere Möglichkeiten, Zeiten festzulegen:

Mit einem /etc/crontab-Eintrag wie

43 5,13,21 * * * listar /home/listar/bin/gen-archive 
wird der Cron-Daemon z. B. mit den Rechten des Benutzers listar um 5.43 Uhr, um 13.43 Uhr und um 21.43 Uhr das Programm /home/listar/bin/gen-archive ausführen. Dieses Beispiel stammt von einem Mailinglisten-Server und zeigt, dass Cron nicht etwa nur Systemprogramme, sondern z. B. auch von der Administratorin selbst geschriebene Shellskripte ausführen kann.


Shellskript: Die Shell, ihres Zeichens Vermittlerin zwischen der Benutzerin an der Kommandozeile und dem Betriebssystemkern, bietet -- je nachdem, welches Programm man dafür verwendet -- oft weitreichende Manipulationsmöglichkeiten. Dazu gehört bei Kommandozeileninterpretern wie der unter Linux meist standardmäßig eingestellten Bash eine eingebaute Programmiersprache. Damit erstellte Programme heißen Skripte, da sie nicht erst mit einem extra Compiler in ein ausführbares Programm übersetzt werden müssen, sondern direkt von der Shell interpretiert werden.

Gerade bei solchen zusammengesetzten Zeitangaben wie der Stundenangabe 5,13,21 empfiehlt es sich, darauf zu achten, dass man keine zusätzlichen Leerzeichen versehentlich einfügt -- bei Manipulationen an der /etc/crontab ist man schließlich selbst die letzte Kontrollinstanz.

Listing 1: Beispiel einer systemweiten /etc/crontab

# /etc/crontab: systemweite Crontab
# Anders als bei jeder anderen Crontab benoetigen
# Sie das Kommando `crontab' hier nicht, um eine
# geaenderte Version dieser Datei zu installieren.
# Dieses File enthaelt zudem ein Feld "Benutzername",
# das in anderen Crontabelle fehlt.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

42 6 * * * root run-parts /etc/cron.daily
47 6 * * 7 root run-parts /etc/cron.weekly
52 6 1 * * root run-parts /etc/cron.monthly

Distributionschaos

Obwohl in der Kommandospalte natürlich jedes halbwegs sinnvolle Kommando stehen kann, hat es sich eingebürgert, die systemweiten Cron-Jobs etwas systematischer zu ordnen. Jede Aktion, die einmal täglich ausgeführt werden soll, wird in ein Shellskript gepackt und z. B. im Verzeichnis /etc/cron.daily (vgl. Tabelle 2) abgelegt (Ausführbarkeitsrechte nicht vergessen!), wöchentlich zu erledigende Aufgaben in /etc/cron.weekly usw.

Die globalen Verzeichnisse für Cron-Skripte haben folgenden Vorteil: Viele Programmpakete ziehen für Cron prädestinierte Aufgaben nach sich -- ein News-Server möchte einmal am Tag News holen und alte Postings "auslaufen lassen", die System-Log-Utilities syslogd und klogd sollten sicher gehen können, dass Logdateien einmal die Woche gestutzt oder besser rotiert werden, etc.


Posting: Ein Beitrag in einer News-Gruppe.
System-Log: Der Kernel und wichtige Systemprogramme lassen ihre Aktivitäten und Fehlerfälle vom "Kernel-Log-Dämon" klogd bzw. vom "System-Log-Daemon" syslogd mitprotokollieren. Aus diesen Logfiles (meist unter /var/log/ zu finden) kann die Systemadministratorin bei Problemen Rückschlüsse ziehen.

Eine clevere Installationsroutine sorgt folglich dafür, dass mit der Installation auch gleich der passende Cron-Job aufgesetzt wird. Schriebe sie einfach eine Zeile in /etc/crontab, sähe es da bald sehr unübersichtlich aus, und besonders geschickt deinstalliert sich so etwas auch nicht -- abgesehen davon, dass sich nicht immer alles halbwegs übersichtlich mit einer Zeile ausdrücken lässt. Also kopiert oder generiert die Installationsroutine ein nettes Shellskript, das root gegebenenfalls auch anpassen kann, und legt es im passenden Verzeichnis ab.

Leider zeigt sich an dieser Stelle das Distributionschaos ganz besonders, allerdings glätten sich die Wogen bei den Namen der Cron-Skript-Verzeichnisse in aktuellen Distributionen zum Glück etwas.

Schlimmer sieht es aus, wenn man sich anschaut, auf welche Art und Weise der Cron-Daemon dafür sorgt, dass diese Skripte zu passenden Zeiten ausgeführt werden. Oft -- wie in Listing 1 zu sehen -- benutzen Distributoren hier das Kommando run-parts, um alle Skripte im jeweiligen Verzeichnis abzuarbeiten. Diese Verfahrensweise wird von Debian, Red Hat und Derivaten verwendet. Caldera tanzt ein bisschen aus der Reihe, indem man statt des Binaries run-parts das Shellskript cronloop verwendet.

SuSE hingegen gefiel dieses Verzeichniskonzept lange Zeit ganz und gar nicht: Bis Version 5.3 ruft /etc/crontab hier das Skript /root/bin/cron.daily auf, das täglich die zu erledigenden distributionsspezifischen Aufgaben herunter rattert und zu guter Letzt auch noch das Skript /root/bin/daily.local für lokale Problemstellungen abarbeitet. Als sei das nicht schon unübersichtlich genug, wird zudem noch fröhlich und unsystematisch in /etc/crontab rumgewurstelt.

Ab Version 6.0 schließen die Nürnberger einen Kompromiss und legen ebenfalls besagte Directories an. Während run-parts andernorten als universell einsetzbarer, von cron unabhängiger Skriptstarter konzipiert ist, werden die in den Cron-Verzeichnissen befindlichen Skripte bei SuSE 6.0 und neuer von einem einzigen spezialisierten Skript namens /usr/lib/cron/run-crons aufgerufen.

Tabelle 2: Wo gehören systemweite Cron-Skripte hin?
Wann auszuführen? stündlich täglich wöchentlich monatlich zu anderen Zeiten
Caldera Open Linux 1.2--2.4
/etc/cron.d/Hourly/
/etc/cron.d/Daily/
/etc/cron.d/Weekly/
/etc/cron.d/Monthly/
/etc/cron.d/lib/
Debian 1.3.1 --
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/
--
Debian 2.0--2.2 --
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/
/etc/cron.d/
Red Hat 4.2--5.2
/etc/cron.hourly/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/
--
Red Hat 6.2
/etc/cron.hourly/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/
/etc/cron.d/


SuSE 5.2--5.3 --
/root/bin/cron.daily
(Skript für distributionsspezifische Jobs),
/root/bin/daily.local
(lokale Anpassungen und Erweiterungen)
-- -- --
SuSE 6.0
/etc/cron.hourly/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/
--
SuSE 6.4
/etc/cron.hourly/
/etc/cron.daily/
/etc/cron.weekly/
/etc/cron.monthly/
/etc/cron.d/

Variabel

Doch wenden wir uns wieder Listing 1 zu: Da wären schließlich noch die mysteriösen Zeilen

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
zu erklären. Wer schon mal den Suchpfad für ausführbare Programme in der Shell geändert hat, findet hier alte Bekannte in leicht geänderter Funktion wieder: Variablen, die in der Form Variablenname=Wert angeben werden.

Mit der Umgebungsvariablen PATH legt man fest, dass ausführbare Dateien in den nach dem Gleichheitszeichen angegebenen und durch Doppelpunkt getrennten Verzeichnissen einfach nur mit ihrem Namen aufgerufen werden können. Liegt ein Programm außerhalb des Suchpfads, muss man es hingegen mit der kompletten Pfadangabe aufrufen.

Zwei ausführbare Dateien gleichen Namens kann es durchaus geben -- sie müssen lediglich in verschiedenen Verzeichnissen liegen. Da der Cron-Daemon mit root-Rechten ausgestattet ist (Wie sonst sollte er imstande sein, Aufgaben mit den Berechtigungen unterschiedlicher User auszuführen?) und damit in recht gefährlichem Gebiet operiert, geht man auf Nummer sicher und gibt mit der Variable PATH in der Crontabelle explizit an, welche Verzeichnisse als Suchpfad zugelassen sind. Da das Verzeichnis /home/listar/bin im obigen Beispiel nicht in PATH stand, musste gen-archive mit kompletter Pfadangabe in die /etc/crontab geschrieben werden.

Tabelle 3 gibt einen Überblick über die wichtigsten in Cron-Tabellen benutzbaren Variablen.

Tabelle 3: Umgebungsvariablen in Cron-Tabellen
Umgebungsvariable Beschreibung Beispiel Erklärung
MAILTO Normalerweise schickt Cron sämtlichen Output per E-Mail an die auftraggebende Benutzerin. MAILTO definiert einen alternativen Empfänger.
MAILTO=trish,pjung@linux-user.de
[verschiedene Cronjobs]
MAILTO=""
[weitere Cronjobs]
Der Output der "verschiedenen Cronjobs" geht per Mail an die lokale Benutzerin trish sowie an die externe Mailadresse pjung@linux-user.de. Nachdem MAILTO noch einmal neu gesetzt wurde, gibt es für die "weiteren Cronjobs" niemanden mehr, der über Erfolg oder Misserfolg informiert wird.
PATH Pfad, in dem nach von Cron auszuführenden Kommandos gesucht wird. Fest einkompiliert ist in den meisten Fällen /usr/local/bin:/usr/bin:/bin:..
PATH=/home/trish/bin
Cron findet für diese Cron-Tabelle nur noch Kommandos aus /home/trish/bin ohne explizite Pfadangabe.
SHELL Shell, in der die Kommandos ausgeführt werden sollen. Voreingestellt ist /bin/sh und damit meistens ein Link auf die Bash.
SHELL=/usr/bin/tcsh
Statt /bin/sh wird jetzt die tcsh verwendet.


.: Der Punkt ist eine Abkürzung für das aktuelle Verzeichnis. Dies ist gerade beim Cron-Daemon mit seiner ungeschränkten Verfügungsgewalt eine recht gefährliche Pfadangabe.

Wie hält er's mit den Usern, sprich?

Während die Systemadministratorin in der systemweiten /etc/crontab peinlich selbst darauf achten muss, den Syntax-Ansprüchen des Cron-Daemons zu genügen, hat sie es leichter, wenn sie roots private Cron-Tabelle ändern will. Benutzerspezifische Wunschlisten an den Cron-Daemon werden -- wie eingangs erwähnt -- mit dem Programm crontab erstellt und gewartet.

Außer root hat kein User überhaupt die Möglichkeit, seine private Cron-Tabelle per Hand zu bearbeiten. Da der Cron-Daemon jede Minute angerückt kommt, um nach seinen Aufgaben zu sehen, vermeidet man so, dass ein unbedarfter Benutzer eine halbfertige oder syntaktisch vollkommen falsche Liste erstellt.

Tabelle 4: Wo stecken die persönlichen Cron-Tabellen?
Auch beim Verzeichnis, in dem die privaten Crontab-Dateien der User zu finden sind, herrscht fröhliche Uneinigheit unter den Distributoren. Immerhin können sich außer SuSE fast alle ein "unterhalb von /var/spool/cron" abringen. Ein paar Stichproben...
Debian 1.3.1 ff. /var/spool/cron/crontabs/
Red Hat 4.2 /var/spool/cron/
Red Hat 5.0 /var/spool/cron/crontabs/
Red Hat 6.2 /var/spool/cron/
Caldera OpenLinux 1.2 ff. /var/spool/cron/
SuSE 4.4 ff. /var/cron/tabs/
Slackware 3.4 /var/spool/cron/crontabs/

Stattdessen legt crontab eine Kopie der alten Crontab an, die die Benutzerin im von crontab automatisch aufgerufenen Editor verändern darf. Erst wenn sie den Editor endgültig schließt, führt crontab ein paar Syntaxprüfungen aus, bittet die Benutzerin ggf. um Korrektur und ersetzt zum Schluss die alte Cron-Tabelle durch die geänderte.

So hilfreich diese Kontrollinstanz ist -- Wunder sollte man nicht erwarten. Zum einen überprüft crontab wirklich nur, ob die richtige Anzahl Spalten vorhanden sind (versehentlich eingefügte Leerzeichen u. a. machen eine neue Spalte auf) und ob die Angaben in den Zeitspalten plausibel sind.

Einen Eintrag wie
88 4 * * * asdadad  
(Achtung: Da private Crontabs immer spezifisch für einen User sind, fehlt die Spalte mit dem Benutzernamen!) mahnt crontab beim Abspeichern zwar mit dem Hinweis auf die falsche Minute ("bad minute") an:
crontab: installing new crontab
"/tmp/crontab.XXXXVYM64K":0: bad minute
errors in crontab file, can't install.
Do you want to retry the same edit?   
Doch sobald man mit einem y wie "yes" reumütig zum Editor zurück kehrt und aus der 88 eine 8 macht, wird crontab die alte Crontabelle klaglos mit der neuen ersetzen, so wenig ein Kommando asdadad auch existieren mag.

Solange crontab jedoch syntaktische Fehler ausmachen kann, lässt es sich nicht so ohne weiteres überlisten. Hätten wir auf die Frage "Möchten Sie Ihre Änderungen noch einmal überarbeiten?" mit einem n geantwortet, wäre die temporäre Datei /tmp/crontab.XXXXVYM64K zwar erhalten geblieben, die Änderungen jedoch nicht in die echte Crontabelle übertragen worden.

Der Widerspenstigen Zähmung

Wie man mit man crontab erfährt, könnte man diese Datei mit einem Editor seiner Wahl in Ruhe korrigieren und mit

crontab /tmp/crontab.XXXXVYM64K
doch noch zu Ehren kommen lassen. Genausogut kann man jede andere vorgefertigte Datei zu installieren versuchen. Auch wenn sich diese Vorgehensweise sicher dazu eignet, eine sorgfältig erstellte Crontabelle nach einer Neuinstallation o. ä. wieder einzuspielen, wird man doch in der Regel zu
crontab -e
greifen, um seine private Cron-Tabelle zu editieren oder neu anzulegen. Hier kann es nicht schaden, die Grundlagen des vi-Editors zu kennen (mit der Tastenfolge ESC : q ! kommt man ohne Speichern wieder raus), denn der ist in der Regel voreingestellt.

Wer diesen nicht mag, kann mit einer der (Shell-, nicht Cron-) Umgebungsvariablen EDITOR oder VISUAL seinen Lieblingseditor festlegen. Arbeitet man unter KDE, gibt man z. B. die Befehlsfolge

export EDITOR=kedit
crontab -e
in einem Terminal-Fenster an. Nach dem Ausloggen oder in der Regel auch in einem anderen X-Terminal ist der neue Wert von EDITOR dann natürlich verschwunden.

Wer ihn dauerhaft haben möchte, schreibt die export-Zeile z. B. in die Datei .bashrc oder .bash_profile im Home-Verzeichnis. Für X-Terminals, die über einen Menüpunkt oder ein Icon aufgerufen werden, kann hier ein wenig Experimentieren erforderlich sein.

Allerdings sollte man beim dauerhaften Ändern dieser Variablen vorsichtig sein: Auch andere Programme richten sich danach, und wer kommt schon gleich auf die Idee, dass ein in der Textkonsole gestartetes Tool deshalb aufgibt, weil sich ein grafischer Editor nun mal nur unter X starten lässt? Für den Notfall sei hier auch das Gegengift erwähnt:

unset EDITOR
bringt die Variable wieder in den (nicht gesetzten) Urzustand, und export EDITOR=mcedit setzt stattdessen den vom Midnight Commander mc benutzten Editor, der ohne X auskommt.

So nützlich crontab also ist: Völlig unbedarftes Herangehen ist nicht unbedingt Erfolg versprechend. Eine gewisse Vereinfachung versprechen grafische Crontab-Editoren, denen wir uns im nächsten (Erscheinungs-)Jahr widmen. Wer trotz allem an seiner Crontabelle verzweifelt: Ein

crontab -r
(wie "remove") löscht sämtliche Einträge unweigerlich. (pju)

Infos

Ein ausführlicher Artikel zu Cron ist im Linux-Magazin 08/1998, S. 63, erschienen und online unter http://www.linux-magazin.de/ausgabe/1998/08/Cron/cron.html nachzulesen.

Dieser Online-Artikel kann Links enthalten, die auf nicht mehr vorhandene Seiten verweisen. Wir ändern solche "broken links" nur in wenigen Ausnahmefällen. Der Online-Artikel soll möglichst unverändert der gedruckten Fassung entsprechen.




Druckerfreundliche Version | Feedback zu dieser Seite | Datenschutz | © 2010 Linux New Media AG

[Linux-Magazin] [LinuxUser] [EasyLinux] [Linux-Community] [Ubuntu User] [Linux Technical Review] [Linux Magazine] [Linux Pro Magazine] [Ubuntu User]
[EasyLinux Poland] [Linux Magazine Poland] [Linux Magazine Brasil] [EasyLinux Brasil] [Linux Magazine Spain]