socket oder fifo

Message
Author
User avatar
killerhippy
Posts: 529
Joined: 19. May 2000 19:36
Contact:

socket oder fifo

#1 Post by killerhippy »

Hi,

ich weiß zwar nicht, ob das so geht, wie ich mir vorstelle, aber ich frag' mal einfach:

Ich habe da eine Konsolen Applikation, die mir nach Aufruf fleißig loggings auf die Konsole auswirft.

ein

# ./application 2>&1 | tee -a logfile

ermöglicht mir prima, ein monstermäßig großes logfile anzulegen. Leider kann man der Applikation nicht mitteilen, ein Logfile zu erzeugen.

Da der loggings viele sind und ich nicht alles wissen muß, sondern nur die aktuellen, sagen wir mal, 25 Zeilen von Interesse sind, habe ich mir gedacht, <b>kann man vielleicht einen fifo</b> einsetzen?

Da bin ich aber noch ganz ungebildet, was muss ich lesen, damit ich ein Gebilde erschaffe, wo mir das `tee` munter das logging reinwirft, womit ich aber mit `cat` oder `less` auf dasselbe immer nur die letzten 25 Zeilen bekomme?
Last edited by killerhippy on 15. Jan 2003 15:31, edited 1 time in total.
Es gibt keine dumme Fragen!

Killerhippy

logger

Re: socket oder fifo

#2 Post by logger »

man tail

User avatar
killerhippy
Posts: 529
Joined: 19. May 2000 19:36
Contact:

Re: socket oder fifo

#3 Post by killerhippy »

man tail
...
SYNOPSIS
tail [OPTION]... [FILE]....


ist mir bekannt, aber man kann tail nicht auf eine virtuelle Konsole werfen, und das Monsterlogfile wollte ich eigentlich zu produzieren vermeiden.

Inzwischen habe ich mir auch die manpages von fifo und socket mal angesehen, aber richtig schlau bin ich daraus auch nicht geworden...

...naja, wenn's hier keiner weiss, trotzdem danke für's Lesen

Jochen

Re: socket oder fifo

#4 Post by Jochen »

Die Schwierigkeit (weshalb ich bis jetzt auch nix gepostet habe) liegt darin, dass das Programm ja nicht weiss, dass es in eine Datei schreibt. Es sieht halt nur stdout und da hängt zufälligerweise eine Datei dran. Man kann dem Programm also nicht mitteilen "Mach die Datei zu und direkt wieder auf", wie z.B. beim syslogd oder Apache. Das ist nötig, weil Du die Datei umbenennen oder sogar löschen kannst, wie Du willst: Solange das Programm den Dateideskriptor offen hat, wird es nicht in eine neue Datei schreiben. Also müsstest Du das Programm stündlich beenden, das Logfile moven (mit vielleicht 3 Generationen, à la logrotate) und das Programm wieder neu starten. Deine Frage klang nicht so, als ob das eine Option wäre... Sorry, eine andere Lösung habe ich nicht parat.

Jochen

User avatar
killerhippy
Posts: 529
Joined: 19. May 2000 19:36
Contact:

Re: socket oder fifo

#5 Post by killerhippy »

danke für die Antwort, und ich dachte etwas in der Art

# ./application 2>&1 | tee <[socket|fifo]>

wobei insgesamt immer 6 Zeilen drinne sind, neue Zeilen die öltesten rauswerfen, wäre eine einfache Sache.

schade, daß dem nicht so ist...

Jochen

Re: socket oder fifo

#6 Post by Jochen »

Nu je, mit einem 2. Prozess, der immer die Named Pipe offen hält und alle Stunde zwischen 2 Logfiles hin- und herswitcht, sollte es gehen... Ich komme wahrscheinlich erst später dazu (mit ein bisschen Pech erst morgen oder übermorgen) was hierhin zu pinnen. Eine erste Idee habe ich schon, ich melde mich noch.

Jochen

Scriptus

Re: socket oder fifo

#7 Post by Scriptus »

Aha, also

# ./application 2>&1 | 25ZeilenLimiter

wobei 25ZeilenLimiter im Kreis bis 25 zählt und unter dieser Schlüsselnummer einen Eintrag in eine Datenbank macht. Wenn Du keine Datenbanken magst, nimm einen STL-Container und schreibe alle Sätze immer wieder neu (mit jedem, oder auch nur bei etwa jedem 5. Satz) in eine Datei. Im Falle einer Textdatei (sequenziell) muß sie immer komplett neu geschrieben werden, es sei denn, Du nutzt eine feste Satzlänge und hast somit eine Datei mit wahlfreiem Zugriff (struct/record).

Jochen

Re: socket oder fifo

#8 Post by Jochen »

Soooo, hoffentlich liest Du das jetzt überhaupt noch... Ich habe mir an der Lösung eine Weile lang die Zähne ausgebrochen, aber jetzt klappt es. Mein Problem lag darin, uberhaupt zu erkennen, dass Sockets und/oder FIFOs totaler Overkill sind...

Kurz und gut: Aufruf des Dienstes erfolgt wie immer, stdout und stderr werden weitergepipet in das folgende Skript, welches ich einfach mal "logplex" getauft habe.
<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">#!/bin/bash
# Skript: logplex

# Basisname der Logfiles
LOGBASE=/tmp/log

# Die aktuelle Nummer des Logfiles wird an $LOGBASE angehängt
LOGNUM=1

# Anzahl Sekunden, wie lange ein Logfile gefüllt werden soll, bevor es durch das andere
# abgeloest wird.
LOGTIME=10

# stdin auf fd 4 duplizieren, da stdin nicht im inneren der Schleife ankommt!
exec 4<&0
# stderr der Shell schliessen, da sonst immer die unschönen "Terminated"-Meldungen beim kill kommen
exec 2>&-

for (( ; ; )) ; do
LOGFILE=$LOGBASE.$LOGNUM
cat <&4 >$LOGFILE &
PID=$!
sleep $LOGTIME
[[ $LOGNUM = 1 ]] && LOGNUM=2 || LOGNUM=1
kill $PID
done

exit 0
</font><hr></pre></blockquote>Wenn Du LOGBASE und LOGTIME nach Deinen Wünschen setzst, sollte es so passen. Läuft zumindest so bei mir ganz gut. Man könnte das jetzt noch ausbauen, mit Parametern für LOGBASE und LOGTIME und so, aber dazu habe ich jetzt keine Lust mehr. Die schön gemachte Variante poste ich, wenn sich hier überhaupt noch Interesse an dem Skript zeigt.

Bei Fragen einfach wieder hier posten...

Jochen

User avatar
killerhippy
Posts: 529
Joined: 19. May 2000 19:36
Contact:

Re: socket oder fifo

#9 Post by killerhippy »

Hi Jochen,

_vielen_vielen_Dank!

Habe ja fast schon nicht mehr dran geglaubt.

Donnerlütt, die Intelligenz kann ich ja gar nicht nachvollziehen, was für noch nie gesehene Konstrukte, wau!

Sobald ich mir Zeit nehme, zu verstehen, was da abgeht, frage ich bestimmt nach...

Erste Tests mit einem Workaround (applikation zZ nicht funktionabel, weil plattencrash und das eingespielte backup noch nicht wieder voll aufgerüstet ist) haben gezeigt, daß die Funktionalität genau erfüllt ist!!!

Damit haste dir ne pulle Bier verdient! Schick mir deine eMail!
Es gibt keine dumme Fragen!

Killerhippy

Jochen

Re: socket oder fifo

#10 Post by Jochen »

> Habe ja fast schon nicht mehr dran geglaubt.

Das glaube ich gerne. Ne, ich hatte irgendwo 'nen Zündaussetzer und bin nicht auf die einfache Lösung gekommen. Und die hat mich dann auch noch etwas Zeit gekostet, weil ich auch die einfache Lösung zuerst viel zu komplex aufgebaut hatte...

Übrigens Danke für die Blumen <img src="http://www.pl-forum.de/UltraBoard/Images/Happy.gif" border="0" align="middle">. War aber mehr Fleissarbeit und Übung als Intelligenz, fürchte ich...

Aber jetzt zum Thema:

Interessant wird es erst ab "exec 4<&0". Das Shell-Builtin exec (man-page, "SHELL BUILTIN COMMANDS") lädt normalerweise ein neues Binary, ohne einen neuen Prozess zu erzeugen, uberschreibt also die Shell. Wenn man aber keinen Dateinamen angibt, werden lediglich die aufgeführten Dateiumlenkungen gemacht (man-page, "REDIRECTION").

Um die Syntax zu verstehen, hilft es zu wissen, dass "<" (wie in "cat < /etc/passwd") nur eine Kurzschreibweise für "0<" ist. 0 ist hier der Filedeskriptor und steht damit für stdin. Man darf aber jeden Filedeskriptor dort aufführen. 1 und 2 sind noch belegt (stdout und stderr), ab 3 sollte alles frei sein. Genauso ist ">" eine Kurzschreibweise für "1>", also stdout umlenken. So wird auch die Schreibweise klar, um stderr umzulenken: "2>", wie aus "grep target file 2>/dev/null" gewohnt.

Nun muss das Wort nach ">" oder "<" nicht immer ein Dateiname sein. Wenn das Zeichen danach ein "&" gefolgt von einer Zahl ist, wird stattdessen auf den Filedeskriptor mit der entsprechenden Nummer zugegriffen. Um genau zu sein: Dieser FD wird dupliziert. Die Schreibweise "2>&1" (wie in "./application 2>&1 | logplex") ist bekannt, um stderr auf stdin umzulenken. Hier wird also intern der stdout-FD (1) dupliziert auf den stderr-FD (2), so dass die Fehlermeldungen inline auf stdout erscheinen.

Soviel zur Theorie. "exec 4<&0" bedeutet jetzt, dass ich stdin (0) auf den bis dato unbenutzten FD 4 dupliziere. Weshalb? Die bash reicht stdin nicht an den Schleifenkörper weiter! (Das hat mich ein bisschen Hirnschmalz gekostet...). Aber FD 4 ist problemfrei erreichbar, so dass ich in der Schleife ein <pre>cat <&4 >$LOGFILE &</pre> schreiben kann, um den in FD 4 duplizierten stdin der Shell wieder an stdin von cat zu duplizieren! Und zwar im Hintergrund mit Ausgabeumlenkung in eine von 2 Logdateien, die im Wechsel zu benutzen sind.

Startet man ein Programm im Hintergrund, setzt die Shell die interne Variable "$!" mit der PID des neuen Prozesses. Die kann man für ein "wait" oder aber wie hier für einen kill-Aufruf nutzen, aber erst, nachdem die LOGTIME abgelaufen ist. (Das Zwischenspeichern von $! in PID ist hier nicht wirklich notwendig, aber da $! bei jedem weiteren Hintergundkommando geändert wird, habe ich es mir zur Gewohnheit zu machen, den Wert dort sofort nach Aufruf zu speichern.)

Für den nächsten Schleifendurchlauf muss ansonsten nur noch der Name des Logfiles neu gesetzt werden. Hätte man auch als <blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">if [[ $LOGNUM = 1 ]] ; then
LOGNUM=2
else
LOGNUM=1
fi</font><hr></pre></blockquote>schreiben können, aber ich war faul. (man-Page, "SHELL GRAMMAR", "Lists").

Und das "exec 2>&-"? Dies schliesst stderr meiner ausführenden Shell. Weshalb? Immer, wenn ein Kindprozess der Shell mittels kill terminiert wird, meldet dies die Shell auf stderr. Diese Meldung ist störend, da sie am Terminbal erscheint. "&-" bedeutet in diesem Zusammenhang sozusagen "Nicht duplizieren, sondern schliessen". Und die Terminierungsmeldung entfleucht ins Nirvana...

Alle Klarheiten beseitigt?

Jochen

User avatar
killerhippy
Posts: 529
Joined: 19. May 2000 19:36
Contact:

Re: socket oder fifo

#11 Post by killerhippy »

Hi Jochen,

vielen Dank für die Ausführliche Dokumentation. Verstanden habe ich, was du erklärt hast wohl, mal sehen, ob ich's irgendwann anwenden kann ;)
Es gibt keine dumme Fragen!

Killerhippy

Jochen

Re: socket oder fifo

#12 Post by Jochen »

So, und jetzt wie versprochen die etwas flexiblere Version. Wie immer: Der Kern des Programmes ist kurz und simpel, aber der Aufwand, den man treiben muss, damit alles korrekt und flexibel funktioniert, ist mind. 3mal so gross...
<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">#!/bin/bash
# Skript: logplex
#
# Autor: Jochen Gruse
#
# Zweck: Teilt stdin in zwei Logfiles auf, die abwechselnd in
# einem bestimmten Zeitintervall ausgetauscht werden.
#
# Optionen: -t time Zeit, nach der die Logfiles gewechselt
# werden sollen. Einfache Zahlen werden als
# Zeit in Sekunden interpretiert. Auch die
# Angaben von GNU-sleep sind moeglich wie zum
# Beispiel "1d" fuer einen Tag oder "3h 30m"
# fuer 3 Stunden und 30 Minuten.
# -h Usage ausgeben
#
# Argumente: Dateiname
# An den Namen wird je nach Logdatei noch .1 oder .2
# angehängt. Angabe ist optional, Default ist
# "/tmp/log".
#
# Aenderungen: 1.0 Jochen Gruse Erstellt
# 1.1 Jochen Gruse Optionen -t, -h implementiert
# 1.2 Jochen Gruse Bugfix zum Checken des
# Arguments zu -t.
# 1.3 Jochen Gruse Prüfung, ob auch in die
# Logdateien geschrieben werden
# kann.

######################################################################
# Initialisierung
######################################################################

# Basisname der Logfiles
LOGBASE=/tmp/log

# Die aktuelle Nummer des Logfiles wird an $LOGBASE angehaengt
LOGNUM=1

# Anzahl Sekunden, wie lange ein Logfile gefuellt wird, bevor es
# durch das andere abgeloest wird.
LOGTIME=10

PROGNAME=$(basename "$0")

function usage {
[[ -n "$*" ]] && echo "$PROGNAME: $*" >&2
echo "Usage: $PROGNAME [-t time] [-h] [logname]" >&2
}

######################################################################
# Argumente bearbeiten
######################################################################

# Optionen bearbeiten
while getopts ":t:h" OPTION ; do
case $OPTION in
t) if echo "$OPTARG" | grep -Eq '^(([0-9]+[smhd]( +[0-9]+[smhd])*)|[0-9]+)$' ; then
LOGTIME="$OPTARG"
else
usage "Option argument \"$OPTARG\" is not a valid time."
exit 2
fi
;;
h) usage
exit 1
;;
\?) usage "Unknown option \"-$OPTARG\"."
exit 2
;;
:) usage "Option \"-$OPTARG\" requires an option argument."
exit 2
;;
*) echo "ERROR - Never should have reached this line!" >&2
exit 10
;;
esac
done
shift $(( OPTIND - 1 ))

case $# in
0) : # Hier ist nur der bereits gesetzte Default zu uebernehmen
;;
1) LOGBASE="$1"
;;
*) usage "No more than 1 filename, please."
exit 2
;;
esac

# OK, hier steht der Name der Logfiles fest. Bleibt nur die Frage, ob
# man die auch benutzen kann?

for I in 1 2 ; do
if ! cat /dev/null > "$LOGBASE.$I" 2>&- ; then
usage "Cannot write to \"$LOGBASE.$I\""
exit 2
fi
done

######################################################################
# Main
######################################################################

# stdin auf FD 4 duplizieren, da stdin nicht im Inneren der
# Schleife ankommt!
exec 4<&0

# stderr der Shell schliessen, da sonst immer die unschoenen
# "Terminated"-Meldungen beim kill kommen
exec 2>&-

while true ; do
LOGFILE="$LOGBASE".$LOGNUM
cat <&4 >"$LOGFILE" &
PID=$!
sleep $LOGTIME
[[ $LOGNUM = 1 ]] && LOGNUM=2 || LOGNUM=1
kill $PID
done

exit 0</font><hr></pre></blockquote>Das sollte jetzt einigermassen selbsterläuternd sein.

Jochen

User avatar
killerhippy
Posts: 529
Joined: 19. May 2000 19:36
Contact:

Re: socket oder fifo

#13 Post by killerhippy »

Danke vielmals,

hast du wirklich keinen Bierdurst?

Jochen

Re: socket oder fifo

#14 Post by Jochen »

Bier erst ab 4. <img src="http://www.pl-forum.de/UltraBoard/Images/Happy.gif" border="0" align="middle"> (14:30)

Aber ernsthaft: Per Email gibt's höchstens ein Bit und ich bevorzuge nun mal Altbier (gebürtiger Düsseldorfer). Oder solltest Du etwa im Dunstkreis des Rheinlandes (Köln/Düsseldorf) oder der Euregio (Aachen) wohnen? Dann können wir uns gerne mal treffen. Ansonsten freue ich mich, wenn Du das Skript gut gebrauchen kannst.

Jochen

User avatar
killerhippy
Posts: 529
Joined: 19. May 2000 19:36
Contact:

Re: socket oder fifo

#15 Post by killerhippy »

nach vier ist vor vier (freie Abwandlung von "Vor der Messe ist nach der Messe")
;)

Ja, wenn du so weit weg wohnst, dann gaeb's ja noch die snailmail.
Es gibt keine dumme Fragen!

Killerhippy

Post Reply