[solved] exec Umleitung wieder beenden

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
pangu
Beiträge: 1400
Registriert: 15.11.2011 20:50:52
Lizenz eigener Beiträge: GNU General Public License
Wohnort: /proc/1

[solved] exec Umleitung wieder beenden

Beitrag von pangu » 05.11.2013 21:24:43

Hi Leute,

in einem Skriptabschnitt möchte ich vermeiden, hinter jedem einzelnen Befehl noch >>$logfile 2>&1 dranzuhängen

Bsp:

Code: Alles auswählen

logfile=/var/log/beispiel.log
Befehl1 >>$logfile 2>&1
Befehl2 >>$logfile 2>&1
Befehl3 >>$logfile 2>&1
[...]usw...
Stattdessen wollte ich mit "exec" arbeiten, á-la:

Code: Alles auswählen

logfile=/var/log/beispiel.log
exec >>$logfile 2>&1
Befehl1
Befehl2
Befehl3
[...]usw...
Jetzt würde ich gerne wissen, wie ich das wieder beenden kann, damit defaultmäßig wieder die Standardausgabe erfolgt. Wie resettet man das wieder?
Zuletzt geändert von pangu am 06.11.2013 10:05:12, insgesamt 2-mal geändert.
Man gibt Geld aus, das man nicht hat, um damit Dinge zu kaufen, die man nicht braucht, um damit Leute zu beeindrucken, die man nicht mag.

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: exec Umleitung wieder beenden

Beitrag von Cae » 06.11.2013 00:48:26

Interessante Frage. Ich glaube, das geht nicht. Eine halbgare Loesung waere

Code: Alles auswählen

{
foo
bar
} 2>&1 >>$log
-- aber da geht stderr trotzdem auf stderr der Shell anstatt in's Log. Das 2>&1 ist in dem Zusammenhang wirkungslos.[Edit: siehe unten] Man koennte explizit auf /dev/tty schreiben, aber das ist unhoeflich und nur fuer interaktive (Passwort-)Eingaben zu verwenden.

Tricksereien a la

Code: Alles auswählen

exec >>/proc/$$/fd/1 2>&1
tuen ebenfalls nicht, aber man koennte sich den vorherigen Wert merken:

Code: Alles auswählen

$ cat /tmp/foo
#!/bin/sh

oldstdout="$(readlink -f "/proc/$$/fd/1")"
exec >>/tmp/bar 2>&1

echo out
echo err >&2

exec >>$oldstdout 2>&1

echo 2 out
echo 2 err >&2
$ sh /tmp/foo
2 out
2 err
$ cat /tmp/bar 
out
err
$ 
Das waere auf jeden Fall Linux-spezifisch und ich bin mir nicht sicher, wann es noch bricht.

Gruss Cae
Zuletzt geändert von Cae am 06.11.2013 14:57:18, insgesamt 1-mal geändert.
Grund: .
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Benutzeravatar
Meillo
Moderator
Beiträge: 9238
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: exec Umleitung wieder beenden

Beitrag von Meillo » 06.11.2013 09:30:50

Cae hat geschrieben:Interessante Frage. Ich glaube, das geht nicht.
So sehe ich das auch. `exec' *ersetzt* eigentlich den momentanen Prozess. Wenn man es fuer die Umleitungen verwendet, dann wuerde ich davon ausgehen, dass hierbei auch etwas *ersetzt* wird. Damit waere es nicht rueckgaengig machbar.
Cae hat geschrieben: Eine halbgare Loesung waere

Code: Alles auswählen

{
foo
bar
} 2>&1 >>$log
-- aber da geht stderr trotzdem auf stderr der Shell anstatt in's Log.
Ich denke (ohne es geprueft zu haben), dass wenn man hier die geschweiften Klammern, die ja nur gruppieren, runde Klammern verwendet, die eine Subshell aufmachen, dann sollte die Umleitung wie gewuenscht funktionieren. Wenn nicht, wuerde es mich doch sehr wundern.
Use ed once in a while!

Benutzeravatar
pangu
Beiträge: 1400
Registriert: 15.11.2011 20:50:52
Lizenz eigener Beiträge: GNU General Public License
Wohnort: /proc/1

Re: exec Umleitung wieder beenden

Beitrag von pangu » 06.11.2013 10:04:55

Hi Leute,

hab mich grad eingelesen und wieder etwas dazugelernt. Das möchte ich euch natürlich als Lösung hier nicht vorenthalten. Und zwar geht das folgenderweisse in meinem Fall:

Wir duplizieren den standard out auf einen neuen Filedescriptor mit der Nummer 6. Das ist so eine Art "Sicherheitskopie" wenn ich das mal so nennen darf. Wir sehen später warum wir das noch brauchen werden...

Code: Alles auswählen

exec 6>&1
und dann leite ich die Standardausgabe+Standardfehlerausgabe auf meine gewünschte Logdatei um, mit dem Befehl:

Code: Alles auswählen

exec >$logfile 2>&1
und wenn ich das wieder innerhalb meines Scripts rückgängig machen möchte, dann hol ich mir die Settings von dem zuvor gespeicherten Filedescriptor 6 zurück, und anschließend schließe ich den Filedescriptor 6 komplett, so dass es ihn nicht mehr gibt:

Code: Alles auswählen

exec 1>&6 6>&-
Mit &- schließt man also wieder einen File-Descriptor.

[Link1] "exec" Erklärung auf englisch auf tldp.org
[Link2] Ein sehr gutes "redirection" Tutorial auf englisch

Grüße,
Pangu.
Man gibt Geld aus, das man nicht hat, um damit Dinge zu kaufen, die man nicht braucht, um damit Leute zu beeindrucken, die man nicht mag.

newdeb
Beiträge: 134
Registriert: 03.02.2011 11:11:21
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Frankfurt

Re: exec Umleitung wieder beenden

Beitrag von newdeb » 06.11.2013 12:50:34

Cae hat geschrieben:Eine halbgare Loesung waere

Code: Alles auswählen

{
foo
bar
} 2>&1 >>$log
-- aber da geht stderr trotzdem auf stderr der Shell anstatt in's Log. Das 2>&1 ist in dem Zusammenhang wirkungslos.
Manpage lesen hilft beim Garen:
Note that the order of redirections is significant. For example, the command

ls > dirlist 2>&1

directs both standard output and standard error to the file dirlist, while the command

ls 2>&1 > dirlist

directs only the standard output to file dirlist, because the standard error was duplicated from the standard output before the standard output was redi‐
rected to dirlist.
Im Eingangspost war's ja bereits korrekt.

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: [solved] exec Umleitung wieder beenden

Beitrag von Cae » 06.11.2013 14:56:27

Stimmt, damit hab' ich mir natuerlich selbst in's Knie geschossen. Keine Ahnung, warum ich ausgerechnet dort die Reihenfolge umgekehrt habe, zumal es im selben Post an drei anderen Stellen richtig steht... :mrgreen:

Jedenfalls tut's damit wie erwartet:

Code: Alles auswählen

$ {
> echo out
> echo err >&2
> } >/dev/null 2>&1
$ 
Wie man sieht, sieht man nix (auf'm TTY).

Die Variante mit geklontem FD ist natuerlich auch nett, da bin ich bisher nie durchgestiegen...

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Antworten