.TL .I at \(em ein (fast) vergessenes Helferlein .AU markus schnalke .AI Der Autor ist ein überzeugter Fan der Unix-Philosophie und interessiert sich somit stark für Programme die nach ihren ``Geboten'' programmiert wurden. Dies sind in erster Linie die alten Unix-Tools, die auf nahezu jedem System verfügbar sind. So auch \fIat\fR, das Inhalt dieses Artikels ist. Dieser Artikel wurde für \fIfreiesMagazin\fR (\fChttp://freiesmagazin.de\fR) geschrieben und ist dort zweigeteilt in der Oktober- und November-Ausgabe des Jahres 2008 erschienen. Dieses PDF und sein \fItroff\fR Quellcode sind auf der Website des Autors (\fChttp://marmaro.de/docs\fR) veröffentlicht. .AB Den .I cron -Daemon kennt und verwendet fast jeder Unix-Benutzer, sein Gegenstück .I at dagegen kennen die meisten nur vom Namen. Die Funktion die .I at anbietet, kann jedoch im Alltag deutlich häufiger eingesetzt werden, als man es erstmal erwartet. .PP Dies ist eine kurze Einführung in .I at mit Beispielen in denen vorgestellt wird was man damit machen kann. .AE .NH Was ist .I at ? .PP Es wird kaum jemanden geben, der .I at erklärt, ohne nicht davor .I cron erklärt zu haben. Hier wird ebenso vorgegangen werden, denn die beiden Programme sind ein Paar das sich ergänzt. .PP .I cron ist ein Daemon, der Programme regelmäßig startet; das kann stündlich, tageweise, oder auch um vier Uhr fünfzehn am ersten Tag jedes Monats sein. .I at startet auch Programme, nur eben nicht regelmäßig, sondern genau einmal zu einem bestimmten Zeitpunkt. .PP Auf Rechnern gibt es üblicherweise eine ganze Reihe von Systemaufgaben, die regelmäßig erledigt werden müssen. Man kann also davon ausgehen, dass ein .I cron -Daemon auf quasi jedem System installiert ist, und auch läuft. (Die regelmäßigen Systemaufgaben kann man sich auf Debian-Systemen mit .CW "ls /etc/cron.*" auflisten lassen.) Der .I cron -Daemon kann dann auch von den Usern genutzt werden indem sie sich ihre eigenen .I Cronjobs anlegen (siehe dazu .I crontab (5)). .PP .I at dagegen ist kein Dienst der vom System genutzt wird. Er ist für die Benutzer da und somit auch nicht auf jedem System von Haus aus installiert. Allerdings sind sowohl .I at als auch .I cron (bzw. .I crontab ) in POSIX und der SUSv3\** .FS Single Unix Specification Version 3, Nachfolger von POSIX .br Die Beschreibung von .I at findet man unter .UL http://www.opengroup.org/onlinepubs/009695399/utilities/at.html . .FE spezifiziert, somit dürften sie für jedes Unix verfügbar sein. .NH Struktur .PP Das .I at -System besteht aus den zwei Programmen .I at und .I atd . Auf vielen Systemen existieren noch weitere Programme, die jedoch nur Aliase für bestimmte .I at -Aufrufe sind. In der folgenden Tabelle sind die Programme kurz vorgestellt. Nähere Informationen finden sich in der Manpage .I at (1). .TS center; lb l. atd Ein Daemon der im Hintergrund läuft und zum passenden Zeitpunkt die Jobs ausführt. at Ein User-Programm mit dem Jobs angelegt, aufgelistet und gelöscht werden können. _ atq Das gleiche wie \fCat \-l\fP: die angelegten Jobs des Users auflisten. atrm Ein Alias für \fCat \-d\fP: einen Job entfernen. batch T{ Stellvertretend für \fCat \-q b \-m now\fP. Damit wird ein Job anlegt, der gestartet wird, wenn das System unter geringer Last steht. T} .TE .SP Von den drei Aliasen ist nur .I batch nach POSIX und SUSv3 spezifiziert, er sollte also verfügbar sein. Die anderen beiden sind auf GNU/Linux-Systemen verbreitet, bei BSD eher nicht. .PP Die oben aufgelisteten Programme liegen natürlich irgendwo im Pfad. (Das Kommando .CW "whereis at" sagt wo.) .PP Zusätzlich gibt es das Spool-Verzeichnis, in dem die Jobs gespeichert sind. Dort schaut .I atd regelmäßig, ob einer der Jobs jetzt zu starten ist. Dieses Verzeichnis liegt je nach System an verschiedenen Orten. Es wird üblicherweise entweder unter .CW /var oder .CW /var/spool ein Verzeichnis mit Namen .CW at oder .CW cron sein. .PP Weiterhin können die Dateien .CW at.allow und .CW at.deny existieren, mit denen Usern die Berechtigung für das Nutzen von .I at gegeben oder entzogen werden kann. Diese Dateien sollten entweder im jeweiligen Spool-Verzeichnis oder direkt unter .CW /etc liegen. .PP Grundsätzlich sollte die Manpage .I at (1) alle Pfade auflisten. .NH Verwendung .PP Jobs mit .I at anzulegen ist keine große Sache. Man startet das Programm einfach mit einer Zeitangabe als Argument. Dann gibt man die Befehle ein die ausgeführt werden sollen und beendet mit .CW ^D \**. .FS .CW ^D steht für die Tastenkombination .CW Strg+D . .FE Diesen Vorgang werde ich jetzt genauer beschreiben. .NH 2 Zeitangabe .PP Die Zeitangabe kann in allerlei verschiedenen Formen erfolgen, in jedem Fall ist sie aber das Pflichtargument beim Aufruf von .I at . Die einfachste Form ist die direkte Angabe einer Uhrzeit oder eines Datums. In der folgenden Tabelle stehen die gängigsten Formate. .TS center tab(=); lb lb lb l l l. Beschreibung=Schema=Beispiel _ Stunde=HH=18 Stunde + Minute=HHMM=1800 Stunde + Minute=HH:MM=18:00 _ Tag=DD.MM.YY=24.12.08 .TE (Im deutschsprachigen Raum unübliche Zeitangaben wurden weggelassen. Diese können bei Bedarf in der Dokumentation nachgelesen werden.) .PP Wird nur eine Uhrzeit angegeben, bezieht diese sich auf die folgenden 24 Stunden \(em also den aktuellen Tag oder, falls sie an diesem schon vergangen sein sollte, auf den nächsten Tag. Uhrzeit- und Tagesangaben können auch kombiniert werden. Dabei muss die Uhrzeit- stets vor dem Tagesangabe erfolgen. Ein Beispiel hierfür wäre .CW "18:00 24.12.08" . .PP Der Einfachheit halber existieren auch Aliase. .TS center tab(=); lb lb l l. Aliasname=steht für _ midnight=00:00 noon=12:00 now= _ today= tomorrow= .TE .PP Gültige Zeitangaben sind zum Beispiel: .CW "noon tomorrow" , oder .CW "14:59 tomorrow" . .PP Man könnte meinen, der Alias .I today sei überflüssig, da sich Uhrzeiten automatisch auf den aktuellen Tag beziehen und es nur bei einer bereits zurückliegenden Uhrzeit einen Unterschied macht. Zum Beispiel .CW 08:00 und .CW "08:00 today" . Im ersten Fall wird der Job für acht Uhr am folgenden Tag angesetzt, im zweiten Fall wird er sofort ausgeführt, da die Zeit bereits in der Vergangenheit liegt. (D.h. er entspricht .CW now .) .PP Tatsächlich wird .CW today aber ziemlich oft verwendet. Noch öfter allerdings .CW now (aber hauptsächlich weil es zwei Buchstaben kürzer ist *g*). .PP Der Grund dafür sind die relativen Inkremente, die zu den Zeitpunkten noch angegeben werden können. Jede beliebige, oben beschriebene, Zeitangabe kann duch ein relatives Inkrement erweitert werden. Die Syntax dafür ist .CW " + " . Die .I ist dabei eine der folgenden Worte: .I minutes , .I hours , .I days , .I weeks , .I months , .I years . (Oder die jeweiligen Einzahl-Formen.) .PP So könnten Zeitangaben etwa diese sein: .CW "now + 1 hour" oder .CW "today + 4 days" oder auch .CW "14:30 tomorrow + 1 week" . .PP Es sollte nun ersichtlich geworden sein, dass es eine Vielzahl möglicher Formen der Zeitangabe gibt. Diese Auflistung ist keineswegs vollständig. Sie ist primär an der SUSv3 orientiert. Je nach System können einzelne Angabemöglichkeiten abweichen oder weitere verfügbar sein. Es ist deshalb empfehlenswert, einen Blick in die lokale Manpage .I at (1) zu werfen. .NH 2 Befehle .PP Die Befehle werden, wie für gute Unix-Programme üblich, von der Standardeingabe gelesen. Das heißt, standardmäßig von der Tastatur. Man kann also Befehle eingeben und beendet diese Eingabe dann mit .CW ^D , das für EOF (= End of File) steht. Das Prinzip ist das selbe wie zum Beispiel bei .I cat oder .I mail auch. .PP Da die Befehle von der Standardeingabe gelesen werden, hat man sehr einfach die Möglichkeit, sie alternativ aus einer Datei oder einer Pipe zu lesen. Hier zwei Beispiele dafür: .B1 .I Aus einer Datei .DS .CW .SM $ cat >at-commands echo "hello world" ^D $ " , und der Job ist weg. Alternativ kann hier der Alias .CW atrm verwendet werden \(em aber ob dieser existiert hängt vom vorliegenden System ab. .NH 2 Benachrichtigung .PP Manch einer hat sich vielleicht schon gefragt, welchen Sinn ein Befehl wie .I date oder ein .I echo in einem Hintergrund-Job haben soll. Richtig, das macht erstmal wenig Sinn. Zum Testen allerdings ist es ungemein geschickt. Wie .I cron auch, schickt .I at in Jobs anfallenden Ausgaben per System-Mail an den jeweiligen Nutzer. (Ein MTA muss dafür natürlich verfügbar sein.) Um zu zeigen wie das aussehen kann, folgt hier ein Auszug einer Shellsession. .B1 .I Mailnachricht eines Jobs .DS .CW .SM $ at now at> echo hello world at> ^D job 8 at 2008-08-11 14:59 $ mail Mail version 8.1 6/6/93. Type ? for help. "/var/spool/mail/meillo": 1 message 1 new >N 1 meillo@localhost Mon Aug 11 14:59 16/727 "Output from your job 8" & p Message 1: From meillo@localhost Mon Aug 11 14:59:13 2008 Date: Mon, 11 Aug 2008 14:59:13 +0200 From: meillo@localhost Subject: Output from your job 8 To: meillo@localhost hello world & d & q .LG .DE .B2 .PP Mail-Benachrichtigungen werden nur verschickt, wenn Ausgaben im Job anfallen. Erzeugt keines der Programme im Job eine Ausgabe, wird auch keine Mail verschickt. Falls man es trotzdem wünscht, kann man sich aber mit der Option .CW \-m in jedem Fall nach Beendigung des Jobs eine Nachricht senden lassen. Gerade bei lange laufenden Programmen ist dies sinnvoll. .PP Der Alias .I batch , der Jobs automatisch dann ausführt wenn die Systemlast niedrig ist, hat diese Option standardmäßig gesetzt. Wer also umfangreiche, und vielleicht sogar ressourcen-intensive Aufgaben zu erledigen hat, sollte sich .I batch genauer anschauen. .NH Beispiele aus dem Alltag .PP Der bisherige Artikel bot nicht viel mehr als die Manpage .I at (1). Okay, die Inhalte waren aufbereitet und (hoffentlich) verständlicher formuliert. .PP Mehrwert soll vor allem dieser Abschnitt bieten, denn es werden Situationen beschreiben, die wahrscheinlich bei Vielen regelmäßig auftreten. Es soll gezeigt werden, wie .I at dabei sinnvoll einsetzt werden kann. Ohne .I at zu verwenden, lassen sich einige der Probleme nicht so schön lösen. .PP Hier steht wirkliche Praxiserfahrung. .NH 2 Erinnerungen per Mail .PP Es passiert oft, dass man in ein paar Tagen eine Email an jemanden senden will, oder dass man an einem bestimmten Datum eine Aktion starten muss, oder andere Dinge dieser Art. An dieser Stelle ist .I at wohl am meisten wert. Ein simples .B1 .I Erinnerungs-Nachricht verschicken lassen .DS .CW .SM $ at 01.12.08 at> mail meillo \-s "Weihnachtsfeier organisieren" at> (zusätzliche Informationen hier einfügen) at> ^D job 9 at 2008-08-13 10:03 .LG .DE .B2 und schon muss man nicht mehr daran denken. Am entsprechenden Tag wird man dann die Mail in seinem Postfach finden und weiß: Jetzt ist es soweit. Dies ist einfacher und vor allem schneller, als zum Beispiel Programme wie .I remind dafür zu verwenden. .PP So ähnlich ist es bei folgendem Sachverhalt: Viele lassen ihre Daten von automatisierten Backup-Scripten (gesteuert von .I cron ) sichern. Nun gibt es aber Tätigkeiten, bei denen man doch selbst Hand anlegen muss. Das ist etwa das Einlegen eines Rohlings in den DVD-Brenner um das Backup offline zu haben. Also lasse man sich in seinem Backup-Intervall von .I cron eine Erinnerungs-Mail schicken, dass es jetzt wieder an der Zeit ist einen Rohling einzulegen und das (automatisch erstellte) Backup darauf zu brennen. .PP Es kann vorkommen, dass man beim Eintreffen der Mail ziemlich beschäftigt ist und auch in den nächsten Tagen nicht dazu kommen wird das Backup zu brennen. Vielleicht ist man ja nicht zuhause, oder es könnte sein, dass man gerade keine Rohlinge da hat. Anstatt die Mail jetzt in der Inbox liegen zu lassen, wo sie vermutlich bald untergehen würde, lässt man sich von .I at einfach zwei oder drei Tage später eine neue Mail schicken: .CW "now + 2 days" . (Eigentlich .CW "today + 2 days" , aber .CW now ist kürzer.) .NH 2 Erinnerungen im Terminal .PP Neben Erinnerungen per Email, die man üblicherweise erst Tage später erhalten will, kann es sinnvoll sein sich nur Stunden oder Minuten später an etwas erinnern zu lassen. Hierfür sind Emails nicht besonders geeignet, da sie nicht minutengenau abgerufen und schon gar nicht so regelmäßig gelesen werden. Viel sinnvoller ist es, sich direkt im Terminal eine Hinweismeldung anzeigen zu lassen. .PP Das geeignete Tool dafür ist .I write . Es schickt eine Meldung an das Terminal in dem der User gerade arbeitet. Für Konsolenbenutzer ist das eine sehr praktische Sache. .PP Nehmen wir an, man muss um 16 Uhr aus dem Haus und deshalb rechtzeitig mit Programmieren aufhören. Anstatt eine Eieruhr zu stellen, kann man auch .i at verwenden. .B1 .I Den Computer als Eieruhr nutzen .DS .CW .SM $ at 15:40 at> write meillo at> programmieren beenden at> ^D job 10 at 2008-08-13 10:37 .LG .DE .B2 .PP Zur angegebenen Uhrzeit wird auf dem aktuellen Terminal folgende Meldung erscheinen: .B1 .I Meldung der ``Eieruhr'' .DS .CW .SM Message from meillo@localhost on (none) at 15:40 ... programmieren beenden EOF .LG .DE .B2 .PP Wer vorwiegend grafische Programme nutzt, wird davon nicht besonders viel haben, aber für Kommandozeilen-Freunde ist es eine ziemlich nette Sache. .NH 2 Zeitgesteuerte Downloads .PP Auch in der heutigen Zeit, soll es Leute geben, denen nur eine sehr langsame Internetverbindung zur Verfügung steht. (Der Autor des Artikels gehört leider zu ihnen.) Diese versuchen größere Downloads möglichst auf Zeiten zu verlagern, an denen sie nicht interaktiv im Netz tätig sind. Wer einen Server hat der dauerhaft online ist oder seinen Desktop-Rechner die Nacht durch laufen lässt, hat da kein Problem. .PP Fans von .I ncftp sind da ziemlich verwöhnt, denn mit .I ncftpbatch ist es ohne weiteres möglich Downloads auf nachts zu verlagern. Tatsächlich ist .I ncftpbatch nichts anderes als ein eingebauter .I at -Daemon. Statt ihn zu verwenden, kann man aber genau so gut jedes beliebige Programm in Verbindung mit .I at einsetzen. Eine große Datei lädt man sich mit folgenden Anweisungen über Nacht runter. .B1 .I Nachts Downloads starten .DS .CW .SM $ at \-m midnight at> cd $HOME/downloads at> wget \-c ftp://example.com/some-big-file.ext at> ^D job 11 at 2008-08-13 15:26 .LG .DE .B2 Durch das Einfügen von .CW "sudo halt" als weitere Zeile, kann man seinen Rechner sogar automatisch runterfahren lassen. (Das Programm .I sudo muss dazu natürlich installiert und passend konfiguriert sein.) .NH 2 Hangup vermeiden .PP Wer nicht nur auf seinem Desktop-Rechner, sondern auch auf entfernten Servern arbeitet, startet lang laufende Aufgaben gerne am Ende seiner Arbeitszeit. Das Problem ist erstmal, dass gestartete Prozesse Kinder der Login-Shell sind und deshalb automatisch beendet werden, wenn (beim Logout) die Shell beendet wird. Das Programm in Hintergrund (mit .CW & ) zu starten hilft da nicht. .PP Was Prozesse von der Login-Shell entkoppelt ist das Kommando .I nohup , das für ``no hangup'' , also kein Beenden des Programms beim Beenden der Verbindung, steht. Loggt man sich aus, wird der Prozess automatisch ein Kind des .I init -Prozesses und lebt weiter. .PP Alternativ zu .I nohup kann das gleiche Verhalten auch mit .CW "at now" erreicht werden. Ob hier .I at sinnvoll eingesetzt wird, oder ob .I nohup oder auch .I dtach oder .I screen besser geeignet sind, soll nicht beurteilt werden. Darüber zu wissen ist aber sicher nicht schlecht. .NH 2 Den Computer beenden .PP Das letztes Beispiel beschreibt das automatische Herunterfahren des Rechners. Manch einer hört gerne Abends im Bett noch ein bisschen Musik. Wenn diese vom Computer kommt, dann sollte sich dieser aber auch automatisch ausschalten, wenn die Musik geendet hat. Hierfür gibt es auch wieder mehrere Ansätze, und auch wenn dieser Artikel .I at beschreibt, werden auch die anderen kurz vorstellen. Es ist entscheidend, die Alternativen zu kennen um eine vernünftige Wahl treffen zu können. .PP Zuerst die .I at -Variante: Man startet den Player, schaut wie lange die Musik noch läuft, addiert eine ``Toleranzminute'' hinzu und ruft dann .CW "at now + minutes" mit dem Shutdown-Befehl (z.B. .CW "sudo /sbin/halt" ) auf. Sollte man sich später doch noch anders entscheiden und will den Rechner doch nicht zu dieser Zeit herunterfahren, kann man den Job ja mit .CW "at \-d" entfernen. .PP Alternativ kann man .I sleep verwenden. Der passende Befehl wäre dann in etwa: .CW "sleep m && sudo /sbin/halt" . Das `&&' statt `;' , damit man den Timer noch abbrechen kann. Wird .I sleep mit .CW ^C beendet, dann gibt es einen Wert ungleich Null zurück und das nachfolgende Kommando wird nicht ausgeführt \(em genau das was wir in diesem Fall wollen. .PP Statt .I sleep kann man mit auch einfach seinen Musikplayer vor das Shutdown-Kommando spannen. Ein Beispiel hierfür wäre: .CW "mpg321 songs/*.mp3 && sudo /sbin/halt" . Das Gute daran ist, dass der Shutdown eben gerade dann eingeleitet wird, wenn die Lieder vorbei sind. Das Problem ist aber, dass .I mpg321 nicht mit einem Fehlercode endet, wenn er abgebrochen wird. Man kann sich also nicht mehr umentscheiden, wenn der Befehl einmal gestartet ist. Denn der Rechner wird auch heruntergefahren, wenn der Player abgebrochen wird. Ein anderer Player reagiert an dieser Stelle vielleicht anders. Man sollte sich dieses Sachverhalts bewusst sein! .PP Der Autor verwendet meist die Variante mit .I sleep , da sie wohl die einfachste ist. Aber er meint .I at ist genauso gut geeignet und vor allem noch flexibler, da man auch eine absolute Uhrzeit angeben kann. .NH Fazit .PP Das war jetzt das wichtigste zu .I at . Seine Struktur und Bedienung wurde erklärt und Beispiele für seinen Einsatz im Alltag eines Unix-Benutzers wurden gegeben. Ziel war es, .I at mal aus seinem Schattendasein herauszuholen und ins Rampenlicht zu rücken. Ich hoffe Sie haben etwas für sich mitgenommen und wissen nun, was dieses Programm ist und haben gesehen, was es kann. .PP Vielleicht setzen Sie .I at ja mal selbst ein \(em ich würde mich freuen! .RD .I 2008-09-12 markus schnalke .LD