ubuntuusers.de

Logfile für eigene Scripte

Status: Gelöst | Ubuntu-Version: Lubuntu 12.10 (Quantal Quetzal)
Antworten |

u1000

Anmeldungsdatum:
2. Oktober 2011

Beiträge: 1850

Hallo,

ich möchte, dass meine Scripte, z.b. das folgende Update, ein Logfile erzeugen.

#!/bin/sh
/usr/bin/apt-get --yes update
/usr/bin/apt-get --yes upgrade
/usr/bin/apt-get --yes dist-upgrade
/usr/bin/apt-get --yes autoclean
/usr/bin/apt-get --yes clean
/usr/bin/apt-get --yes autoremove
exit 0

Ich möchte das Rad nicht neu erfinden und suche eine wiederverwendbare universelle Lösung, um auch meine anderen Scripte automatisch Loggen zu lassen.

Gibt es einen Mechanismus in Ubuntu, wo ich meine Logs automatisch mit nach /var/log/... schreiben lassen kann ?

Momentan habe ich mir folgende Möglichkeiten überlegt:

1. sich selbst mit-Loggendes Script, nur eine Zeile mehr in jedem Script:

#!/bin/sh
[ ! "$1" = "log" ] && sh $0 log 2>&1 | tee -a $0.log && exit 0;
...

2. mit Pipe:

mein_script 2>&1 | mein_logger

mein_logger macht dabei ein tee -a $log

3. als Unterprozess:

mein_logger mein_script

mein_logger macht dann ein sh $1 2>&1 | tee -a $log

Was ist nun die beste Lösung ? Momentane Probleme bei mein_logger sind dabei:

  • manche Scripte müssen per sudo aufgerufen werden,

  • der Default User kann unter /var/log/ keine Files anlegen,

  • jedes mein_script soll automatisch ein eigenes Logfile bekommen, ohne dass ich es spezifizieren muss

Vielen Dank u1000

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2510

Servus,

mir würden da zwei Wege einfallen:

1) Skript nochmal mit der Pipe ausführen, also deine zweite Variante, aber automatisiert. Wenn du dein Originalskript mit Root ausführst, wird das auch beibehalten.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash

if [[ $1 != BEING_RUN_INSIDE ]]
then
	"$0" BEING_RUN_INSIDE "$@" 2>&1 | tee -a output.log
	exit
fi
shift

# Tue irgendwas beispielhaftes ...

echo "My arguments:"
for i
do
	echo "'$i'"
done

ls -al
ls -al /nein

2) „tee“ als Hintergrundprozess laufen lassen, Redirection von stderr und stdout dort hin, Kommunikation über eine Named Pipe. Hat je nach Anwendungsfall auch den Vorteil, dass du stdout und stderr trennen kannst (muss man aber nicht).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash

tmpdir=$(mktemp -d)
mkfifo "$tmpdir"/stdout.fifo
mkfifo "$tmpdir"/stderr.fifo
tee -a stdout.log <"$tmpdir"/stdout.fifo &
tee -a stderr.log <"$tmpdir"/stderr.fifo >&2 &
trap 'rm -Rf "$tmpdir"' EXIT
exec 1>"$tmpdir"/stdout.fifo
exec 2>"$tmpdir"/stderr.fifo

# Tue irgendwas beispielhaftes ...

echo "My arguments:"
for i
do
	echo "'$i'"
done

ls -al
ls -al /nein

Ich persönlich würde mich wahrscheinlich für die erste Variante entscheiden, weil sie mir einfacher erscheint.



Man könnte sich auch noch überlegen, ob man vielleicht automatisiert Timestamps schreibt. Bei Variante 1 könnte das so aussehen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/bash

logging()
{
	while read -r
	do
		echo "[$(date +%F\ %T)] $REPLY" | tee -a output.log
	done
}

if [[ $1 != BEING_RUN_INSIDE ]]
then
	"$0" BEING_RUN_INSIDE "$@" 2>&1 | logging
	exit
fi
shift

# Tue irgendwas beispielhaftes ...

echo "My arguments:"
for i
do
	echo "'$i'"
done

ls -al
ls -al /nein

diesch Team-Icon

Avatar von diesch

Anmeldungsdatum:
18. Februar 2009

Beiträge: 5072

Wohnort: Brandenburg an der Havel

Du kannst logger benutzen, um Logmeldungen an Syslog weiteruugeben, und den so konfigurieren, dass eer deine Meldungen in ein eigenes Logfile schreibt

Wenn du z.B. /etc/rsyslog.d/99-local.conf anlegst mit dem Inhalt

1
:programname, isequal, "update" /var/log/update.log

Kannst du mit

1
logger -t update 'Update completed'

eine Meldung in /var/log/update.log schreiben (die zusätzlich auch in /var/log/syslog auftaucht)

Vain

Avatar von Vain

Anmeldungsdatum:
12. April 2008

Beiträge: 2510

Ah, genau, und den logger kann man auch gut mit meiner ersten Variante verbinden:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash

if [[ $1 != BEING_RUN_INSIDE ]]
then
	"$0" BEING_RUN_INSIDE "$@" 2>&1 | tee >(logger -t update)
	exit
fi
shift

# ... Rest des Skriptes ...

u1000

(Themenstarter)

Anmeldungsdatum:
2. Oktober 2011

Beiträge: 1850

Super - Vielen Dank für die Tipps.

Ich werde ausgiebig testen und berichten.

u1000

(Themenstarter)

Anmeldungsdatum:
2. Oktober 2011

Beiträge: 1850

logger ist eine Interesannte Sache, einmal als root konfiguriert, kann man dann auch als normaler User Logs schreiben, die aber wie üblich dann nur von root gelesen werden dürfen.

diesch schrieb:

1
logger -t update 'Update completed'

eine Meldung in /var/log/update.log schreiben (die zusätzlich auch in /var/log/syslog auftaucht)

Habt ihr schon gefunden, wie man verhindert, dass die Sachen nicht doppelt nach /var/log/syslog kommen ?

Die momentane Variante enspricht meiner ursprünglichen "sich selbst mit-Loggendes Script" mit euren Korrekturen, kurz

#!/bin/sh
[ "$1" != 2ndCall ] && "$0" 2ndCall "$@" 2>&1 | tee >(logger -t update) && exit 0
...
..update..

Vielen Dank u1000

diesch Team-Icon

Avatar von diesch

Anmeldungsdatum:
18. Februar 2009

Beiträge: 5072

Wohnort: Brandenburg an der Havel

u1000 schrieb:

Habt ihr schon gefunden, wie man verhindert, dass die Sachen nicht doppelt nach /var/log/syslog kommen ?

Was standardmäßig in /var/log/syslog landet, wird in /etc/rsyslog.d/50-default.conf festgelegt in der Zeile

1
*.*;auth,authpriv.none         -/var/log/syslog

Das einfachste ist, mit einer eigenen facility zu loggen, z.B. local1, z.B.:

1
logger -t update -p local1.info 'Update completed'

Dann kannst du rsyslog sagen, dass die nicht nach /var/log/syslog soll, indem du die Zeile von oben durch

1
*.*;auth,authpriv.none;!=local1.*               -/var/log/syslog

ersetzt.

Das Paket rsyslog-doc enthält die Doku zu rsyslog in /usr/share/doc/rsyslog-doc/html/index.html, es lohnt sich, da mal reinzuschauen, wenn du dich mit dem Logging beschäftigen willst.

Antworten |