Shellscript. Neue Zeile am Anfang einer Log-Datei schreiben

Admiral

Aktives Mitglied
Thread Starter
Dabei seit
15.03.2004
Beiträge
208
Reaktionspunkte
0
Hallo zusammen.
Ich möchte per Shell-Script eine Protokolldatei führen, in der die neuen Logeinträge nicht am Ende angehängt werden sondern am Anfang stehen, so das ich zuerst die neusten Einträge sehe.

Wäre klasse, wenn mir jemand helfen könnte.

Vielen Dank im Voraus.
Gruß Admiral
 
Wie man Einträge am Anfang einer Datei einfügt, weiß ich nicht.
Ich mach das immer so, dass ich die logdatei mit 'tail' ausgebe.

Beispiel:

Code:
tail -15 /var/log/mail.log

um die letzten 15 Zeilen zu sehen.

Mit
Code:
tail -f ...

kann man sogar "live" mitlesen, wie die Einträge hereinkommen.

Alternativ kannst Du Deine Logdatei so öffnen:

Code:
vi +:$ /var/log/system.log

Dann kommst Du gleich ans Ende, hast aber natürlich die komplette Datei im Editor.

HTH
Gruß
maceis
 
Eine einfache und total unelegante Möglichkeit wäre beispielsweise:
1. mv logfile logfile_temp
2. Aktuellen Eintrag schreiben in logfile (welches hiermit neu erstellt wird)
3. cat logfile_temp >> logfile
4. rm logfile_temp

Rinse and repeat...

Eventuell gar nicht mal so unelegant, da das OS wohl ähnliches sowieso machen müsste.

Allerdings würde ich die Lösungen von maceis auch bevorzugen, Logfiles mit dem neuesten Eintrag on top sind irgendwie... non-standard...
 
Logfiles mit dem neuesten Eintrag on top sind irgendwie... non-standard...

Nun, die Einträge life anzeigen lassen ist ganz nützlich. Aber meine Idee ist, das ich so ziemlich jeden Tag eine bestimmte Logdatei öffne um zu sehen ob alles so läuft wie geplant. Und so scrolle ich halt jeden Tag die Datei runter um die neusten Einträge zu begutachten. Mir ist es eben lieber sofort zu sehen was los ist - habe eben wenig Zeit und muss viele Dinge im Auge zu behalten :)
 
Nun, die Einträge life anzeigen lassen ist ganz nützlich.

Das ist schon richtig. Hierfür ist das erwähnte tail -f dein Freund :)
Evtl. auch in Verbindung mit Tools wie grep & Co., um nur bestimmte Einträge zu sehen (z.b. nur Linien mit dem Begriff "error"). UNIX bietet dir da 1000 Möglichkeiten. Am besten sogar, du kriegst automatisch eine Benachrichtigung, wenn etwas *nicht* gut läuft. Automatisieren.... ;)
 
PS: Mit einem Texteditor für grosse Jungs muss man auch nicht ans Ende scrollen, man drückt einfach ESC und dann G. ;)
 
na ja, es gibt sicherlich zig Möglichkeiten. Aber ich wollte halt einfach nur wissen wie es geht. Wenn es zu aufwendig ist mache ich es eben wie bisher. Ist ja auch nicht wirklich nötig, wäre nur mal nett gewesen wenn es einfach zu bewerkstelligen wäre. Ich werde das mal mit Tail laufen lassen.
 
nunja, es gibt diverse möglichkeiten, allerdings alle nicht rein shell!
Was steht denn an Mitteln zur Verfügung?
Am einfachsten ist das mit sed:
sed -i '1 i\TEXT' DATEI

alternativ mit tac:
(tac DATEI; echo "TEXT") | tac > DATEI

oder mit cat:
(echo "TEXT"; cat DATEI) | cat > DATEI

alternativ eine x-beliebige scriptingsprache wie perl, phyton, php etc.

edith: ob das aber ein verschieben der dateisektoren auf der Platte zur Folgehat ist mir grad auch nicht ganz klar...
 
Hast Du Deine Vorschläge eigentlich mal selbst ausprobiert?
Sieht nämlich nicht so aus!
 
ja, natürlich.
unter debian und einer bash und einer zsh.
funktioniert einwandfrei.

was funktioniert denn bei dir nicht?
 
Das hier ist aber ein Unix und kein Linux Forum, noch dazu für macuser.
Und hier funktioniert keiner Deiner Vorschläge.

Tut mir Leid!
 
bash ist bashdas OS ist dabei vollkommen egal.

mindestens der Vorschalg mit echo und cat|tac (solange vorhanden) sollte funktionieren. sonst ist die bash entweder uhr-uhr-uhr-alt oder einfach defekt.

eventuell etwas portabler:
echo "$(echo "foo" && cat test)" > test

sorry, hab hier kein OSX zum testen. nur ein ipad.
eventuellfinde ich montag zeit den kram mal unter osx zu testen.
 
Code:
cat DATEI
zeile 1
Zeile 2
Zeile 3

sed -i '1 i\TEXT' DATEI
sed: 1: "DATEI": extra characters at the end of D command
echo $?
1

tac
bash: tac: command not found

(echo "TEXT"; cat DATEI) | cat > DATEI
cat DATEI 
TEXT
TEXT

echo "$(echo "foo" && cat DATEI)" > DATEI
cat DATEI 
foo
foo

Ich mein ja nur!
 
Nun ja;
Das erste Problem liegt in der Reihenfolge der Auswertung der Kommandozeile durch die Shell.
Sieht sie Shell (und das ist nicht nur in der bash so) ein "> test", wird zuerst eine leere Datei "test" angelegt und danach werden die Kommandos vor dem ">" ausgeführt und deren Ausgabe nach "Test" umgeleitet.
Das ist ein alter Fehler, der leider immer wieder gemacht wird - eigentlich ein Anfängerfehler, wenn ich das mal so sagen darf.
Würde mich sehr wundern, wenn das in der einer aktuellen bash anders wäre, kann ich aber nicht beschwören, da ich in der zsh arbeite.

Funktioniert wunschgemäß:
Code:
(echo "neue zeile"; cat file) | cat > file.tmp && mv file.tmp file

cat file                                   
neue zeile
zeile 1
Zeile 2
Zeile 3

Würde bei mir aber unter "useless use of cat" laufen und ist (m. E.) nicht wirklich eine sinnvolle Lösung des ursprünglichen Problems.

Was sed angeht:
-i ist vorhanden, aber darüber mault er ja auch nicht.
Meines Wissens verwenden viele Linux Distris gnused.
Ist aber nicht SUS-konform und verhält sich daher anders als die in OSX vorhandene Version.
Ich hab das jetzt aus Zeitgründen nicht vertieft, aber ich bin sicher, dass man das auch mit Mac OS X sed, gelöst bekommt - und zwar Portable ;).

Nichts für ungut ;).
Gruß
maceis
 
Das sollte gehen:

Code:
sed -i "" -e "1i\\
Text" Datei.txt
 
  • Gefällt mir
Reaktionen: magheinz
Ich vergess immer das nicht allesin OSX POSIX-kompatibel ist. $() ist die POSIX-Variante für "``".


Abarbeitung einer Kommandozeile
Eine Kommandozeile wird von der Shell zunächst umfassend in folgenden Schritten analysiert:
1. Zerlegung der Kommandozeile anhand von \Newline-, Newline-, Tabulator- und Leerzeichen
2. Parameter-Ersetzung und Auswertung von Shell-Variablen-Zuweisungen (Erläut. später)
3. Kommandosubstitution (Erläut. später)
4. weitere Zerlegung der bisher entstandenen Teile anhand von Trennzeichen
5. Auswertung vorhandener Ein-/Ausgabe-Umlenkungen (siehe nächsten Abschnitt)
6. Dateinamen-Expandierung (d.h. Auflösung evtl. vorhandener Jokerzeichen)
http://cs.unitbv.ro/~costel/solg/unix_4.htm

Wie du siehst ist der "Anfängerfehler" kein Fehler da Kommandosubstitution vor der Umlenkung und somit vor dem Öffnen des filedescriptors für die Ausgabe stattfindet. (bash)

"useless use of cat" von mir aus, es funktioniert aber. der Aufwand für die Platte dürfte aber der gleiche sein wie beim arbeiten mit einer temporären datei.

Man kann meines erachtens nach nicht billig eine Zeile am Anfang einfügen. Das zieht immer ein Verschieben aller anderen Zeilen nach sich was sich bei großen Dateien dann wohl wirklich negativ auswirken dürfte.

Sinnvoller dürfet es sein am Ende anzufügen und dann beim Auswerten rückwärts zu arbeiten.
"tac" ist da ganz praktisch wenn vorhanden.

z.b. die letzen 20 zeilen rückwärts "tail -n20 file| tac".
Kann man bestimmt unter OSX nachinstallieren.
 
Die Backticks funktionieren unter OS X genauso.

Auch die Reihenfolge der Abarbeitung einer Kommandozeile ist die selbe, wie von Dir zitiert.

Allerdings macht Linux etwas anderes, als das was da steht.
Im Schritt 5 wird unter Linux (offensichtlich) nicht ganz zu Ende gebracht.
Zur Auswertung der Ausgabeumlenkung gehört nämlich auch das Anlegen der Zieldatei.

Früher (zumindest zu der Zeit, als ich Linux in einer Ausbildung gelernt habe), war das auch unter Linux noch so.
Heute offensichtlich nicht mehr, obgleich es in den manages zur Bash noch so dokumentiert ist:
Code:
   Redirecting Output
       Redirection  of  output causes the file whose name results from the expan-
       sion of word to be opened for writing on file descriptor n, or  the  stan-
       dard  output  (file descriptor 1) if n is not specified.  If the file does
       not exist it is created; [COLOR="#FF0000"]if it does exist it is truncated to zero size.[/COLOR]

Nachzulesen u. a. hier.

Gruß
maceis
 
natürlich macht die bash in osx und linux das gleiche. es ist schliesslich die selbe gnu-bash.unterschiede bestehen höchstens in der version oder wenn apple was geändert hat."NAME bash - GNU Bourne-Again SHell[...]COPYRIGHT Bash is Copyright (C) 1989-2005 by the Free Software Foundation, Inc."http://developer.apple.com/library/mac/#documentation/darwin/reference/manpages/man1/bash.1.htmlDie bash kann doch schritt 5 machen.vorher erfolgte doch schritt 3.die umleitung erfolgt dann bevor das kommando ausgeführt wird.das kommando ist das fertige (variablensubstitutin,kommandosubstitution etc sind dann abgeschlossen).Ich glaube du hast den Abschnitt in der manpage falsch verstanden.
 
Und ich glaube, Du hast den Satz nach Deiner Liste der Reihenfolge nicht mehr gelesen:

...
5. Auswertung vorhandener Ein-/Ausgabe-Umlenkungen (siehe nächsten Abschnitt)

6. Dateinamen-Expandierung (d.h. Auflösung evtl. vorhandener Jokerzeichen)

Erst danach wird das Kommando ausgeführt!

Das heißt, "Redirecting Output" - und somit das Leeren der Ausgabedatei - sollte vor Ausführung des Kommandos kommen.
cat file sollte also ein leeres file bearbeiten - zumindest nach meinem Verständnis.
Wie ich bereits sagte, war das "früher" auch unter Linux standardmäßig so.

Meine Vermutung geht dahin, dass das "übliche" Verhalten durch options beeinflusst werden kann und Deine Shell einfach anders eingestellt ist.

Das von Dir geschilderte Verhalten kann man unter OSX mit der - manpage-konformen - folgenden Vorgehensweise erzielen:
  1. Starten der bash mit der Option -C (ob das zwingend erforderlich ist, habe ich nicht getestet)
  2. Verwenden des Operators >| anstelle von >


Gruß
maceis
 
Zurück
Oben Unten