frank-w
Anmeldungsdatum: 30. September 2008
Beiträge: 408
|
Hallo, ich möchte die Ausgabe (stdout+stderr) eines Befehls in eine Log-Datei schreiben...soweit ganz einfach nun möchte ich aber, dass die Ausgabe von stderr entsprechend gekennzeichnet wird (z.b. mit [E] am Anfang)...das habe ich nach langem suchen auch gefunden: | (echo a;echo b>&2) 2> >(sed 's/^/[E] /'>&2)
|
nun versuche ich das noch in eine Logdatei zu bekommen | (echo a;echo b>&2) 2> >(sed 's/^/[E] /'>&2) &> log
|
und es landet folgendes in der log:
ich hätte jetzt aber erwartet
kann mir das jemand erklären und hat vielleicht sogar ein funktionierende Variante? der nächste Schritt wäre dann Datum/Zeit hinzufügen (mache ich aktuell mit ts "%Y-%m-%d %H:%M:%S")
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4578
Wohnort: Berlin
|
@frank-w: Es kommt auf die Reihenfolge an:
| $ (echo a;echo b>&2) &> test.log 2> >(sed 's/^/[E] /'>&2)
$ cat test.log
a
[E] b
|
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12837
|
Marc_BlackJack_Rintsch schrieb: @frank-w: Es kommt auf die Reihenfolge an:
| $ (echo a;echo b>&2) &> test.log 2> >(sed 's/^/[E] /'>&2)
$ cat test.log
a
[E] b
|
Das funktioniert bei mir nicht verlässlich. Wenn ich dies ausführe: | echo $BASH_VERSION
rm -f test.log
(echo a;echo b>&2) &> test.log 2> >(sed 's/^/[E] /'>&2)
echo --------
cat test.log
|
bekomme ich deutlich häufiger | 4.4.12(1)-release
--------
a
|
als Dein Ergebnis. Das ist auch logisch, denn die Dateideskriptoren werden geschlossen, sobald die erste Subshell terminiert. Wenn der sed dann einen Tucken braucht, schreibt er nicht mehr in den geöffneten Deskriptor 2 sondern in den geschlossenen. Man sieht keinen Fehler, weil der ebenfalls nicht auf 2 geschrieben werden kann. Es wirkt auch fragil, 2 auf sich selbst umzuleiten, weil das Ergebnis von der Reihenfolge abhängt. Man kann die Sache etwas verbessern, indem man das nicht tut und außerdem eine Pause einfügt. | rm -f test.log
( (echo a;echo b>&2) 2> >(sed 's/^/[E] /'); sleep 0.1 ) > test.log
echo --------
cat test.log
|
Schön finde ich das nicht. Man müsste eher darauf warten, dass der sed -Prozess fertig ist. So ist das robuster: | {
mkfifo pipe
sed 's/^/[E] /' pipe &
(echo a;echo b>&2) 2>pipe
wait
} >| test.log
echo --------
cat test.log
|
In einem Skript würde man dann auch noch den Namen der Pipe würfeln, damit es keine Kollisionen geben kann: | {
pipe=$(mktemp)
rm "$pipe"
mkfifo "$pipe"
sed 's/^/[E] /' "$pipe" &
(echo a;echo b>&2) 2>"$pipe" &
rm "$pipe" # cleanup + avoids writes from other procs
wait # for all children!
} >| test.log
echo --------
cat test.log
|
Bonus: dieser Code läuft auch in der sh .
|
frank-w
(Themenstarter)
Anmeldungsdatum: 30. September 2008
Beiträge: 408
|
danke euch...wird schon langsam komplex für eine "einfache" umleitung...wie bekomme ich jetzt noch den aktuellen zeitstempel (zeitpunkt der meldung nicht der terminierung) vor jeden eintrag? ich kanns ja nicht hinter die "äußere" subshell packen (da das ja erst bei programmende passiert),oder? Zur info: mein Befehl läuft länger (wochen-monate)... Wann wird in die log geschrieben? Permanent oder erst,wenn die innere subshell fertig ist?
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11181
Wohnort: München
|
frank-w schrieb: Zur info: mein Befehl läuft länger (wochen-monate)...
Was für ein Befehl ist das? Hast du Einfluss auf den Quellcode des Programms (dann würde ich das da direkt einbauen)?
|
frank-w
(Themenstarter)
Anmeldungsdatum: 30. September 2008
Beiträge: 408
|
|
u1000
Anmeldungsdatum: 2. Oktober 2011
Beiträge: 1850
|
frank-w schrieb: Zur info: mein Befehl läuft länger (wochen-monate)...
Wäre es da nicht auch sinvoller ein Logfile pro Tag, Woche oder Monat zu haben ?
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12837
|
frank-w schrieb: danke euch...wird schon langsam komplex für eine "einfache" umleitung...wie bekomme ich jetzt noch den aktuellen zeitstempel (zeitpunkt der meldung nicht der terminierung) vor jeden eintrag? ich kanns ja nicht hinter die "äußere" subshell packen (da das ja erst bei programmende passiert),oder?
Du ersetzt den sed -Aufruf durch eine Schleife mit while read -r line; do ... done und wertest pro Zeile den Zeitstempel aus. Oder Du kombinierst die beiden durch eine Pipe.
Wann wird in die log geschrieben? Permanent oder erst,wenn die innere subshell fertig ist?
Permanent. Du kannst Zeilen schneller schreiben lassen, wenn Du sed -u benutzt, weil es dann weniger puffert. Damit wird aber typischerweise der Durchsatz geringer. Ob das tatsächlich ein Problem ist, hängt aber davon ab, welchen Durchsatz Du am Eingang hast.
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11181
Wohnort: München
|
frank-w schrieb: Hostapd mit -dd-flags
Und die Timestamps, die er mit dem zusätzlichen Argument -t in einen Teil der Debug-Meldungen einbaut, genügen dir nicht?
|
u1000
Anmeldungsdatum: 2. Oktober 2011
Beiträge: 1850
|
frank-w schrieb: Hostapd mit -dd-flags
Wenn man den Hostapd als Systemd Unit startet ist alles inklusive. Auch die extra Option -dd läst sich in der Unit bestimmt unterbringen.
|
frank-w
(Themenstarter)
Anmeldungsdatum: 30. September 2008
Beiträge: 408
|
u1000 schrieb: frank-w schrieb: Hostapd mit -dd-flags
Wenn man den Hostapd als Systemd Unit startet ist alles inklusive. Auch die extra Option -dd läst sich in der Unit bestimmt unterbringen.
kann ich da auch mehrere Instanzen von hostapd starten und wie lege ich einen solchen Service an, dass er Zeitstempel und stderr entsprechend markiert? seahawk1986 schrieb: Und die Timestamps, die er mit dem zusätzlichen Argument -t in einen Teil der Debug-Meldungen einbaut, genügen dir nicht?
naja, er macht irgendwelche Zeitstempel hin, aber die kann ich ncht entschlüsseln 1
2
3
4
5
6
7
8
9
10
11
12
13 | 1531821530.517610: ap0: Setup of interface done.
1531821530.517633: ctrl_iface not configured!
1531821530.517708: RTM_NEWLINK: ifi_index=10 ifname=ap0 operstate=2 linkmode=0 i
fi_family=0 ifi_flags=0x11003 ([UP][LOWER_UP])
1531821530.517738: nl80211: Set IF_OPER_UP again based on ifi_flags and expected
operstate
1531821530.517758: netlink: Operstate: ifindex=10 linkmode=-1 (no change), opers
tate=6 (IF_OPER_UP)
1531821530.517846: RTM_NEWLINK: ifi_index=10 ifname=ap0 operstate=6 linkmode=0 i
fi_family=0 ifi_flags=0x11043 ([UP][RUNNING][LOWER_UP])
$ date
Tue Jul 17 09:59:52 UTC 2018
|
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4578
Wohnort: Berlin
|
Das sind Sekunden seit dem Anbeginn der Unix-Zeitrechnung und die kann man beispielsweise mit date entschlüsseln:
| $ date --utc -d @1531821530.517846
Tue Jul 17 09:58:50 UTC 2018
|
|
frank-w
(Themenstarter)
Anmeldungsdatum: 30. September 2008
Beiträge: 408
|
danke, das kam mir auch gerade in den Sinn, als ich nochmal in die Manpage geschaut habe trotzdem unpraktisch, um mal fix die Logs durchzuschauen mich wundert dass es da noch keinen Ansatz gibt logmeldungen entsprechend zu erweitern...vielleicht ist ja auch mein Ansatz falsch und es geht ganz anders
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4578
Wohnort: Berlin
|
@frank-w: Es gibt sei Ewigkeiten Syslog und neuerdings Systemd. Auf einem aktuellen System könntest Du also zum Beispiel Deine Logmeldungen in das Systemd-Journal kippen. Schau Dir beispielsweise mal systemd-cat an. Logmeldungen werden normalerweise im Programm selbst schon entsprechend gestaltet, in dem man dort Funktionen wie Log() zur Verfügung stellt, oder irgend ein Daemon kümmert sich später darum. Beispielsweise crond bei Cronjobs, systemd bei Diensten und was Systemd sonst noch so verwaltet, supervisord und wie sie alle heissen. Und wenn man das selbst machen wollen würde, dann würde ich auch den Ansatz von systemd-cat verwenden. Ein externes Programm mit dem man etwas zu loggendes startet und das dessen Standard- und Fehlerausgabe entsprechend erweitert und weg schreibt. Statt versuchen das in jedes Programm separat rein zu basteln.
|
frank-w
(Themenstarter)
Anmeldungsdatum: 30. September 2008
Beiträge: 408
|
ich möchte halt gerne nicht in die syslog reinschreiben, sondern eine eigene log anlegen...
die man-page von systemd-cat ist nicht wirklich aussagekräftig, was mein Problem angeht
auch die von "logger" bringt mich aktuell nicht wirklich weiter mit | hostapd -dd /etc/hostapd/hostapd_ap0.conf | systemd-cat -t "hostapd_ap0"
|
landen die meldungen schonmal mit zeitstempel in der syslog...aber ich sehe noch keine Unterscheidung zwischen stdin und stderr...mhm...pipe macht ja nur stin per default | (echo "stdin";echo "stderr" >&2) |& systemd-cat -t "echo-test"
Jul 17 12:52:22 bpi-r2-ubuntu echo-test[8824]: stdin
Jul 17 12:52:22 bpi-r2-ubuntu echo-test[8824]: stderr
|
|