benitzer
Anmeldungsdatum: 1. August 2016
Beiträge: Zähle...
|
Hallo ubuntuusers, ich habe ein Problem beim Schreiben eines (Bash-)Skripts. Und zwar möchte ich in einer if-Anweisung die Standardbefehlsausgabe und die Standardfehlerausgabe in eine Datei leiten und diese Ausgaben aber auch auf der Konsole zu Gesicht bekommen. Es soll der exit code von tar gepfrüft werden, um Ausgeben zu können, ob alles geklappt hat oder nicht. So sieht der Teil meines Skripts aktuell aus:
| if tar -vvczf archiv.tar.gz /tmp/test/ > /tmp/tar_log.txt 2>&1
then
echo "Verzeichnis /tmp/test/ wurde erfolgreich gepackt"
else
echo "Fehler: Verzeichnis /tmp/test/ konnte nicht gepackt werden"
fi
|
Jetzt möchte ich allerdings, dass ich auch Ausgaben in die Konsole bekomme. Mittlerweile weiß ich, dass das am besten mit dem Befehl tee und dem Pipe-Operator zu machen ist. Wenn ich das jetzt allerdings in der if-Anweisung mache, wird vermutlich dann der exit code von tee durch die Bash abgefragt und nicht der von tar. Ist das so? Wenn ja, welche Alternative gäbe es, damit Bash den exit code von tar abfragt, aber ich die Ausgabe im Log und auf der Konsole habe?
|
Benno-007
Anmeldungsdatum: 28. August 2007
Beiträge: 29240
Wohnort: Germany
|
Willkommen! Ich probier mich auch mal dran... Ist vv Absicht, bringt das mehr Ausgaben? Das "-" KANN bei tar auch weg. Davon abgesehen, die Zeile müsste dann so aussehen:
| if (tar vczf archiv.tar.gz /tmp/test/ 2>&1 | tee /tmp/tar_log.txt)
then
|
Du hast aber Recht, tee wird hier keine Fehler von tar übernehmen. Bei anderen Programmen könnte es hier Folgefehler geben, dann könnte man sich sogar die Klammer sparen und es würde funktionieren. Also fällt mir nur die umständliche Variante ein, den Rückgabecode $? zwischenzuspeichern:
| tar vczf archiv.tar.gz /tmp/test; check="$?" 2>&1 | tee /tmp/tar_log.txt
if [ $check == "0" ]
then
|
Oder auch via Extrascript, welches dein script aufruft:
| ./script 2>&1 | tee /tmp/tar_log.txt)
|
Extrashell im Hintergrund, Anzeige im Vordergrund:
(tar vczf archiv.tar.gz /tmp/test; check="$?" 2>&1 > /tmp/tar_log.txt) & cat /tmp/tar_log.txt
if [ $check == "0" ]
then
Oder man loggt über die ganze Datei:
| (
if tar vczf archiv.tar.gz /tmp/test
then
...
) 2>&1 | tee /tmp/tar_log.txt
|
Die letzte Variante ist vielleicht am "besten".
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12822
|
benitzer schrieb:
ich habe ein Problem beim Schreiben eines (Bash-)Skripts. Und zwar möchte ich in einer if-Anweisung die Standardbefehlsausgabe und die Standardfehlerausgabe in eine Datei leiten und diese Ausgaben aber auch auf der Konsole zu Gesicht bekommen. Es soll der exit code von tar gepfrüft werden, um Ausgeben zu können, ob alles geklappt hat oder nicht. So sieht der Teil meines Skripts aktuell aus:
| if tar -vvczf archiv.tar.gz /tmp/test/ > /tmp/tar_log.txt 2>&1
then
echo "Verzeichnis /tmp/test/ wurde erfolgreich gepackt"
else
echo "Fehler: Verzeichnis /tmp/test/ konnte nicht gepackt werden"
fi
|
Jetzt möchte ich allerdings, dass ich auch Ausgaben in die Konsole bekomme.
In der bash kannst Du das so machen - allerdings mit dem Problem des Exit-Codes, wie Du richtig erkannt hast: | if tar -vvczf archiv.tar.gz /tmp/test/ |& tee /tmp/tar_log.txt
then
echo "Verzeichnis /tmp/test/ wurde erfolgreich gepackt"
else
echo "Fehler: Verzeichnis /tmp/test/ konnte nicht gepackt werden"
fi
|
Mittlerweile weiß ich, dass das am besten mit dem Befehl tee und dem Pipe-Operator zu machen ist. Wenn ich das jetzt allerdings in der if-Anweisung mache, wird vermutlich dann der exit code von tee durch die Bash abgefragt und nicht der von tar. Ist das so?
Ja.
Wenn ja, welche Alternative gäbe es, damit Bash den exit code von tar abfragt, aber ich die Ausgabe im Log und auf der Konsole habe?
Willst Du die Ausgabe immer sehen? | tar -vvczf archiv.tar.gz /tmp/test/ >| /tmp/tar_log.txt 2>&1
code=$?
cat /tmp/tar_log.txt
if [ $code -eq 0 ]
then
echo "Verzeichnis /tmp/test/ wurde erfolgreich gepackt"
else
echo "Fehler: Verzeichnis /tmp/test/ konnte nicht gepackt werden"
fi
|
Der ">|" bewirkt nur, dass die Datei auf jeden Fall überschrieben wird. Es geht auch einfach ">". Man könnte sich auch damit behelfen, dass man etwas in die Datei schreibt, wenn tar erfolgreich war: | { tar -vvczf archiv.tar.gz /tmp/test/ && echo OK; } |& tee /tmp/tar_log.txt
if tail -1 /tmp/tar_log.txt | fgrep -qx OK
then
echo "Verzeichnis /tmp/test/ wurde erfolgreich gepackt"
else
echo "Fehler: Verzeichnis /tmp/test/ konnte nicht gepackt werden"
fi
|
|
Benno-007
Anmeldungsdatum: 28. August 2007
Beiträge: 29240
Wohnort: Germany
|
Bei meinem zweiten Codeblock müsste wohl doch noch eine Klammerung um tar und check zusammen.
|
benitzer
(Themenstarter)
Anmeldungsdatum: 1. August 2016
Beiträge: 8
|
Erst einmal vielen Dank für die Antworten! Ich hatte leider heute Vormittag keine Zeit. Ja, vv ist Absicht (soweit ich weiß heißt das very verbose; es zeigt jedenfalls zusätzlich die Dateiberechtigungen an) Ich habe mich für die 1. Variante von Benno-007 entschieden, weil diese mir am plausibelsten erscheint:
| tar vczf archiv.tar.gz /tmp/test; check="$?" 2>&1 | tee /tmp/tar_log.txt
if [ $check == "0" ]
then
|
rklm: Willst Du die Ausgabe immer sehen?
Ja ich will die Ausgabe immer sehen. Benno-007: Bei meinem zweiten Codeblock müsste wohl doch noch eine Klammerung um tar und check zusammen.
Also soll der Block dann mit Klammern so aussehen:
| (tar vczf archiv.tar.gz /tmp/test; check="$?") 2>&1 | tee /tmp/tar_log.txt
if [ $check == "0" ]
then
|
Ist das richtig oder muss ich andere Klammern verwenden oder diese Klammern anders setzen? Da mein Skript ein Backup-Skript ist, welches zusammengefasst Server stoppt, dann alle Dateien aller Server in ein temporäres Verzeichnis kopiert, die Server startet, die Daten vom Tempverzeichnis packt und komprimiert und zum Schluss das Archiv und das tar-Log auf einen FTP-Server legt, wäre es auch nicht schlecht, wenn die komplette Datei/das komplette Skript geloggt werden würde (, um diese "komplette" Log-Datei dann auch mit auf dem FTP-Server abzulegen). Ich will also ein tar-Log, in dem nur die Einträge von tar sind und ein Log, in dem alle Ausgaben (und mögliche Fehlerausgaben) zu finden sind. Benno-007 schrieb: Oder man loggt über die ganze Datei:
| (
if tar vczf archiv.tar.gz /tmp/test
then
...
) 2>&1 | tee /tmp/tar_log.txt
|
Kann ich jetzt also einfach eine öffnende Klammer ganz am Anfang meines Backup-Skripts setzen und zum Schluss
| ) 2>&1 | tee /tmp/log.txt
|
einfügen oder ist das aus einem Grund nicht sinnvoll/clever? MfG benitzer P.S.: Natürlich werden die durch das Skript erstellten Dateien mit Datum und Zeit im Namen versehen, dann auf den FTP-Server geladen und dann sowieso wieder aus dem Temp-Verzeichnis gelöscht, sodass es nie zum Überschreiben wichtiger Daten/Dateien kommen könnte.
|
Benno-007
Anmeldungsdatum: 28. August 2007
Beiträge: 29240
Wohnort: Germany
|
Für das Gesamtlog kannst du auch nur Teile vom Script klammern - wie du willst. Nachteile musst du mal die anderen Meinungen abwarten. Ob die Klammer für tar so notwendig ist, würde ich meinen - ich hab's nicht getestet, damit du auch noch was zu tun hast. 😉
|
benitzer
(Themenstarter)
Anmeldungsdatum: 1. August 2016
Beiträge: 8
|
Vielen Dank! Ich kann gerne auch selber noch ein bisschen mehr testen. ☺ Allerdings habe ich noch eine Frage: Benno-007 schrieb: Ob die Klammer für tar so notwendig ist, würde ich meinen - ich hab's nicht getestet, damit du auch noch was zu tun hast. 😉
Wozu sollen die Klammern eigentlich dienen bzw. wozu dienen die Klammern eigentlich? Und wenn die Klammern nicht notwendig sind, aber auch nicht stören, wäre es ja auch nicht so schlimm, wenn sie einfach da stehen. MfG benitzer
|
Benno-007
Anmeldungsdatum: 28. August 2007
Beiträge: 29240
Wohnort: Germany
|
Die Frage geb ich einfach mal in die Runde oder an eine Suchmaschine weiter - ohne zu gucken würde ich schätzen, es geht damit eine Subshell auf (oder sowas). Ich bin ein Praktiker und kein Theoretiker. Ich teste, wenn's läuft - fein. Und die Klammerung sorgt dafür, dass alle Ausgaben der Klammerinhalte an tee weitergeleitet werden - denn nur die von der Variable check wären dir sicherlich etwas zu wenig, oder? 😉 Ohne Klammer dürfte da ja nur
check="$?" 2>&1 | tee /tmp/tar_log.txt
ausgewertet werden - reichlich sinnlos.
|
benitzer
(Themenstarter)
Anmeldungsdatum: 1. August 2016
Beiträge: 8
|
Ich habe es mir fast schon gedacht, dass die Klammern dazu dienen, dass auch die Ausgabe von tar an tee übergeben wird - was ich jetzt nach testen auch bestätigen kann (–> setzte ich keine Klammern ist das tar-Log einfach leer). Mein Code ist jetzt:
| (tar vvczf archiv.tar.gz /tmp/test; check="$?") 2>&1 | tee /tmp/tar_log.txt
if [ "$check" == "0" ]
then
echo "Verzeichnis /tmp/test/ wurde erfolgreich gepackt"
else
echo "Fehler: Verzeichnis /tmp/test/ konnte nicht gepackt werden"
fi
|
Jetzt wird allerdings, obwohl in Realität tar fehlerfrei funktioniert, der else-Zweig gegangen und ich bekomme somit die (Fehler-)Meldung "Fehler: Verzeichnis /tmp/test/ konnte nicht gepackt werden" Also habe ich mir mal check ausgeben lassen:
| (tar vvczf archiv.tar.gz /tmp/test; check="$?") 2>&1 | tee /tmp/tar_log.txt
echo $check
if [ "$check" == "0" ]
then
echo "Verzeichnis /tmp/test/ wurde erfolgreich gepackt"
else
echo "Fehler: Verzeichnis /tmp/test/ konnte nicht gepackt werden"
fi
|
Die Ausgabezeile von echo $check ist leer. Lasse ich mir den Rückkehr-Code direkt ausgeben mit:
| (tar vvczf archiv.tar.gz /tmp/test; echo $?) 2>&1 | tee /tmp/tar_log.txt
if [ "$check" == "0" ]
then
echo "Verzeichnis /tmp/test/ wurde erfolgreich gepackt"
else
echo "Fehler: Verzeichnis /tmp/test/ konnte nicht gepackt werden"
fi
|
bekomme ich 0 ausgegeben - wie es in die Variable aufgenommen werden soll. Woran liegt es, dass die Variable nicht den Wert 0 bzw. im Falle eines Fehlers einen anderen aufnimmt, sondern einfach leer bleibt?
|
Benno-007
Anmeldungsdatum: 28. August 2007
Beiträge: 29240
Wohnort: Germany
|
Also zunächst mal dürfen um "$check" keine Anführungszeichen sein, habe ich auch bewusst nicht gemacht - um $? dürfen wohl auch keine sein, rklm machte es zudem auch ohne. Probier beides zusammen mal.
|
benitzer
(Themenstarter)
Anmeldungsdatum: 1. August 2016
Beiträge: 8
|
Nun habe ich den Code:
| (tar vvczf archiv.tar.gz /tmp/test; check=$?) 2>&1 | tee /tmp/tar_log.txt
if [ $check == "0" ]
then
echo "Verzeichnis /tmp/test/ wurde erfolgreich gepackt"
else
echo "Fehler: Verzeichnis /tmp/test/ konnte nicht gepackt werden"
fi
|
Ich hoffe ich habe Dich, was den Code angeht, jetzt richtig verstanden. Meine Ausgabe ist jetzt folgende:
tar: Removing leading `/' from member names
drwxrwxr-x mcserver/mcserver 0 2016-08-02 00:35 /tmp/test/
-rwxrwxrwx mcserver/mcserver 6 2016-08-02 00:27 /tmp/test/test1
-rw-rw-r-- mcserver/mcserver 6 2016-08-02 00:27 /tmp/test/test3
-rw-rw-r-- mcserver/mcserver 6 2016-08-02 00:27 /tmp/test/test2
./test.sh: line 11: [: ==: unary operator expected
Fehler: Verzeichnis /tmp/test/ konnte nicht gepackt werden Leider hat das, wenn ich Dich richtig verstanden habe, auch nicht geklappt.
|
Benno-007
Anmeldungsdatum: 28. August 2007
Beiträge: 29240
Wohnort: Germany
|
Da steht ja, ein = zuviel - also mach mal eins raus. Wobei es bei mir meist mit zwei ging - sicher. Ist das auch tatsächlich
#!/bin/bash
am Anfang?
|
benitzer
(Themenstarter)
Anmeldungsdatum: 1. August 2016
Beiträge: 8
|
Mit dem einen = wäre mir neu - habe es natürlich trotzdem probiert, hat aber auch nichts daran geändert. (Natürlich wird jetzt in der Fehlermeldung auch nur ein = angezeigt) ☹ Benno-007 schrieb: Ist das auch tatsächlich
#!/bin/bash
am Anfang?
Ja, ist es.
|
Benno-007
Anmeldungsdatum: 28. August 2007
Beiträge: 29240
Wohnort: Germany
|
Wahrscheinlich muss der Rückgabewert wieder raus aus der Subshell, also schau dir mal die Variante von rklm an - das Grundsprinzip ist dort dasselbe.
|
benitzer
(Themenstarter)
Anmeldungsdatum: 1. August 2016
Beiträge: 8
|
Benno-007 schrieb: also schau dir mal die Variante von rklm an - das Grundsprinzip ist dort dasselbe.
Habe ich auch schon gesehen. Morgen werde ich seine Variante probieren. MfG benitzer
|