Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[bash] Redirection (was: bc: Umbruch und Eingabe)

0 views
Skip to first unread message

Marcel Logen

unread,
Apr 15, 2023, 5:07:40 AM4/15/23
to
Helmut Waitzmann in de.comp.os.unix.apps.misc:

> Fragment des Wrapper‐Bash‐Skripts:

Danke. Bei der Analyse Deines Codes bin ich auf ein seltsames
Verhalten der bash gestoßen:

> exec {fd}< "${tempdir%/}"/ausdruecke.bc

| user14@n14:/tmp$ cat hallo9
| hallo

| user14@n14:/tmp$ exec {asdf}< hallo9
| user14@n14:/tmp$ declare -p asdf
| declare -- asdf="10"

OK, wie zu erwarten.

| user14@n14:/tmp$ unset asdf
| user14@n14:/tmp$ declare -p asdf
| bash: declare: asdf: not found

Dann ohne "exec":

| user14@n14:/tmp$ {asdf}< hallo9

Keine (sichtbare) Reaktion der Shell. Und:

| user14@n14:/tmp$ declare -p asdf
| bash: declare: asdf: not found

Mir ist nicht klar, was da eigentlich passiert, wenn ich kein
"exec" angebe.

Mal ein wenig gespielt:

| user14@n14:/tmp$ {asdf;}< hallo9
| bash: syntax error near unexpected token `}'

| user14@n14:/tmp$ {asdf ;}< hallo9
| bash: syntax error near unexpected token `}'

| user14@n14:/tmp$ {asdf ; }< hallo9
| bash: syntax error near unexpected token `}'

| user14@n14:/tmp$ { asdf ; }< hallo9
| bash: asdf: command not found

Mit der ksh unter OpenBSD wird ohne "exec" das Terminalfenster
geschlossen, was für mich auf das erwartete Verhalten hindeutet:
Der Befehl nach "exec" ersetzt die laufende Shell.

Noch zwei Punkte, die mir auffielen (oder gehören die besser
in die Ursprungsgruppe dcouam? Grübel):

> {
> rm -Rf -- "$tempdir"
> ok &&
^^ Wozu ist das nötig?

> } 3<&-
^^^^ Und wozu das? (Der file descriptor 3 wird offenbar
geschlossen.)

Marcel

f'up2 de.comp.os.unix.shell

Christian Weisgerber

unread,
Apr 15, 2023, 9:30:05 AM4/15/23
to
On 2023-04-15, Marcel Logen <33320000...@ybtra.de> wrote:

>| user14@n14:/tmp$ {asdf}< hallo9
>
> Keine (sichtbare) Reaktion der Shell. Und:

Die Umleitung wird aber ausgeführt, wie eine Ausgabeumleitung belegt,
die dann die entsprechende Datei auf Nulllänge stutzt oder neu
anlegt.

>| user14@n14:/tmp$ declare -p asdf
>| bash: declare: asdf: not found
>
> Mir ist nicht klar, was da eigentlich passiert, wenn ich kein
> "exec" angebe.

Für externe Befehle wird erst eine Subshell geforkt, dort die
Umleitung ausgeführt, dann der Befehl geexect. Offenbar behandelt
bash eine Befehlszeile nur aus Umleitung nicht wie einen internen,
sondern wie einen externen Befehl.

Bei internen Befehlen entfällt die Subshell und die Zuweisung der
Filedeskriptornummer an die Variable verschwindet nicht:

bash$ type true
true is a shell builtin
bash$ true {fd}</dev/null
bash$ echo $fd
10

> Mit der ksh unter OpenBSD wird ohne "exec" das Terminalfenster
> geschlossen, was für mich auf das erwartete Verhalten hindeutet:

Diese {varname}-Umleitungen sind eine ksh93-Erfindung.
OpenBSD /bin/ksh unterstützt das nicht.

Was du ausgeführt hast, um damit die Shell zu beenden, weiß ich
nicht.
$ {asdf}<foo
ksh: {asdf}: not found

> Der Befehl nach "exec" ersetzt die laufende Shell.

exec ohne Befehl, nur mit Umleitungen, wird benutzt, um die
Filedeskriptoren im gegenwärtigen Shellprozess zu manipulieren.

--
Christian "naddy" Weisgerber na...@mips.inka.de

Marcel Logen

unread,
Apr 15, 2023, 12:34:36 PM4/15/23
to
Christian Weisgerber in de.comp.os.unix.shell:

>On 2023-04-15, Marcel Logen <33320000...@ybtra.de> wrote:

>>| user14@n14:/tmp$ {asdf}< hallo9
>>
>> Keine (sichtbare) Reaktion der Shell. Und:
>
>Die Umleitung wird aber ausgeführt, wie eine Ausgabeumleitung belegt,
>die dann die entsprechende Datei auf Nulllänge stutzt oder neu
>anlegt.

Du meinst ein "{asdf}> foo"? Ja, das tut, was Du sagst.

>> Mir ist nicht klar, was da eigentlich passiert, wenn ich kein
>> "exec" angebe.
>
>Für externe Befehle wird erst eine Subshell geforkt, dort die
>Umleitung ausgeführt, dann der Befehl geexect. Offenbar behandelt
>bash eine Befehlszeile nur aus Umleitung nicht wie einen internen,
>sondern wie einen externen Befehl.
>
>Bei internen Befehlen entfällt die Subshell und die Zuweisung der
>Filedeskriptornummer an die Variable verschwindet nicht:

Danke, das ist dann wohl die Erklärung für das Verhalten. Ich kann
es jetzt nachvollziehen.

>> Mit der ksh unter OpenBSD wird ohne "exec" das Terminalfenster
>> geschlossen, was für mich auf das erwartete Verhalten hindeutet:
>
>Diese {varname}-Umleitungen sind eine ksh93-Erfindung.
>OpenBSD /bin/ksh unterstützt das nicht.

So hatte ich die man page von OpenBSD-ksh auch verstanden.

>Was du ausgeführt hast, um damit die Shell zu beenden, weiß ich
>nicht.

Das weiß ich (jetzt) auch nicht mehr. ;-)

Ich kann es jedenfalls nicht mehr nachstellen.

>exec ohne Befehl, nur mit Umleitungen, wird benutzt, um die
>Filedeskriptoren im gegenwärtigen Shellprozess zu manipulieren.

Ja, so ähnlich hatte ich mir das schon gedacht, als ich mir Hel-
muts Code anschaute.

Marcel

Helmut Waitzmann

unread,
Apr 15, 2023, 8:00:38 PM4/15/23
to
Marcel Logen <33320000...@ybtra.de>:
> Helmut Waitzmann in de.comp.os.unix.apps.misc:
>
>> Fragment des Wrapper‐Bash‐Skripts:
>
> Danke. Bei der Analyse Deines Codes bin ich auf ein seltsames
> Verhalten der bash gestoßen:
>
>> exec {fd}< "${tempdir%/}"/ausdruecke.bc
>
> | user14@n14:/tmp$ cat hallo9
> | hallo
>
> | user14@n14:/tmp$ exec {asdf}< hallo9
> | user14@n14:/tmp$ declare -p asdf
> | declare -- asdf="10"
>
> OK, wie zu erwarten.
>
> | user14@n14:/tmp$ unset asdf
> | user14@n14:/tmp$ declare -p asdf
> | bash: declare: asdf: not found
>
> Dann ohne "exec":
>
> | user14@n14:/tmp$ {asdf}< hallo9
>
> Keine (sichtbare) Reaktion der Shell.
>

Da bin ich mir auch nicht sicher, was das bewirkt.  Ich bin mir
auch nicht sicher, ob Umlenkungen ohne Kommando überhaupt möglich
sind, und, was sie dann bedeuten.  Und weil ich mich im
Allgemeinen – außer, es lässt sich nicht (mit erträglichem
Aufwand) vermeiden – auf den POSIX‐Standard beschränke, kann es
durchaus sein, dass ich irgendwelche Spezialitäten heutiger
Shells nicht kenne.

Aber Christians Vermutung, dass der Shell das als ein externes
Null‐Kommando versteht, würde zum gezeigten Verhalten passen:  Es
wird dasselbe ausgeführt wie mit «exec», nur mit dem Unterschied,
dass sich der Shell vorher in einen neuen Prozess forkt.  Damit
ist natürlich alles, was in dem neuen Prozess geschieht, nach
dessen Ende im alten nicht vorhanden: weder der File‐Descriptor
noch die Shell‐Variable:

>
> | user14@n14:/tmp$ declare -p asdf
> | bash: declare: asdf: not found
>
> Mir ist nicht klar, was da eigentlich passiert, wenn ich kein
> "exec" angebe.
>
> Mal ein wenig gespielt:
>
> | user14@n14:/tmp$ {asdf;}< hallo9
> | bash: syntax error near unexpected token `}'

Das sieht mir danach aus, dass der Shell hier wegen des
Strichpunkts die Kommandozeile in zwei Teile zerlegt:  Der
erste ist das Kommando «{asdf», beendet mit einem Strichpunkt,
und der zweite enthält als erstes die schließende Schweifklammer,
und da fehlt dem Shell die dazu gehörende öffnende.

Probiere im Unterschied dazu mal die folgende Kommandozeile:


{ asdf;}< hallo9

Ob die allerdings funktioniert, bin ich mir auch nicht sicher: 
Bedenke, unmittelbar vor die Umleitungsoperatoren darf – ohne
Leerraum dazwischen – (im POSIX‐Standard) eine
File‐Descriptor‐Nummer und (im Bash) alternativ ein Variablenname
in Schweifklammern gesetzt werden.

Allem anderen, was ich vor einen Umlenkungsoperator schreibe, was
aber nichts damit zu tun haben soll, spendiere ich immer einen
Sicherheitsabstand: ein Leerzeichen.

>
> | user14@n14:/tmp$ {asdf ;}< hallo9
> | bash: syntax error near unexpected token `}'

Hier liegt dasselbe wie oben vor:  Der Strichpunkt trennt zwei
Kommandos, egal, ob vor ihm Leerraum steht oder nicht.
>
> | user14@n14:/tmp$ {asdf ; }< hallo9
> | bash: syntax error near unexpected token `}'

Das ist ebenfalls das gleiche:  Auch nach einem Strichpunkt muss
kein Leerraum stehen, damit er seine Funktion hat.
>
> | user14@n14:/tmp$ { asdf ; }< hallo9
> | bash: asdf: command not found

Ah, hier folgt dieser Fall ja!  Der Shell findet die öffnende
Schweifklammer, die nur ihre syntaktische Wirkung für
Kommandolisten hat, wenn an ihr weder vorne noch hinten etwas
dranklebt, was nicht selbsttrennend ist.

> Mit der ksh unter OpenBSD wird ohne "exec" das Terminalfenster
> geschlossen, was für mich auf das erwartete Verhalten hindeutet:
> Der Befehl nach "exec" ersetzt die laufende Shell.

Dass das Terminalfenster geschlossen wird, deutet für mich darauf
hin, dass der in ihm laufende Shell sich beendet.  Insofern
verstehe ich jetzt nicht, warum das Terminalfenster gerade ohne
«exec» geschlossen wird.  Ich hätte jetzt eher das Gegenteil
erwartet.

> Noch zwei Punkte, die mir auffielen (oder gehören die besser in
> die Ursprungsgruppe dcouam? Grübel):
>
>> {
>> rm -Rf -- "$tempdir"
>> ok &&
> ^^ Wozu ist das nötig?

Das ist nicht nur nicht nötig, sondern sogar falsch.  Der Shell
wird sicher einen Syntaxfehler spucken.  Du siehst, ich habe das
nicht ausprobiert, ehe ich es abgeschickt habe.  Es ist im Eifer
des Gefechts («Wie schreibe ich am besten, damit geschieht, was
ich will?») stehen geblieben.

>> } 3<&-
> ^^^^ Und wozu das? (Der file descriptor 3 wird offenbar
> geschlossen.)

Das ist ebenfalls falsch:  Ich hatte das Skript zuerst mit
File‐Descriptor 3 aufgesetzt, mich dann aber entschieden, die
Fähigkeiten des Bashs, sich selber einen File‐Descriptor
auszusuchen und den in einer Variablen bekannt zu machen, zu
nutzen.  Es muss richtig also

} {fd}<&-

heißen.  Das hat den Vorteil, dass das Skript auch dann noch
funktioniert, wenn du von irgendwoher den File‐Descriptor 3
bereits geöffnet hast und dem «bc» den Parameter «/dev/fd/3»
übergeben willst.  Das Skript (und ich als Ersteller) kann ja
nicht wissen, in welcher Umgebung es eingesetzt werden soll.

Diese Möglichkeit, den Shell einen noch freien File‐Descriptor
mittels «{variable}» vor Umlenkungsoperatoren selber aussuchen zu
lassen, sollte unbedingt in den POSIX‐Standard aufgenommen
werden.


Die Umlenkoperation

{fd}<&-

bedeutet, dass der in der Variablen «fd» genannte File‐Descriptor
geschlossen wird.  Das ist in diesem Fall vielleicht nicht
unbedingt nötig, weil weder «rm» noch die Shell‐Funktion «ok»
etwas mit ihm anfangen wird.

Aber ich bemühe mich in Shell‐Skripten generell um vorbeugende
File‐Descriptor‐Hygiene:  Da, wo ich weiß, dass ich einen
File‐Descriptor, den ich selbst geöffnet habe, nicht brauche,
schließe ich ihn.  Das ist wichtig in den Fällen, wo so ein
offengelassener File‐Descriptor von jemandem missbraucht werden
könnte.  Stell dir beispielsweise vor, an der Stelle, wo das
«rm»‐Kommando steht, wäre außerdem noch ein Aufruf etwa eines
Texteditors, das Skript also zur interaktiven Verwendung
gedacht.  Da könnte man ja dann im Texteditor die Datei
«/dev/fd/3» öffnen, obwohl das nicht im Sinn des
Shell‐Skript‐Erfinders ist.

Das ist übrigens auch der Grund, warum «sudo» in der
Standard‐Konfiguration alle File‐Descriptors (außer 0, 1 und 2)
schließt, aus Sorge davor, dass der «sudo»‐Anwender beim Aufruf
vergessen haben könnte, noch irgendwelche File‐Descriptors, die
er geöffnet hatte, zu schließen, weil der von «sudo» gestartete
Prozess, der unter einer anderen Benutzerkennung läuft, auf
keinen Fall Zugriff aus sie erhalten darf, weil sonst
Sicherheitslücken entstehen.

Christian Weisgerber

unread,
Apr 16, 2023, 10:30:05 AM4/16/23
to
On 2023-04-15, Helmut Waitzmann <nn.th...@xoxy.net> wrote:

> Da bin ich mir auch nicht sicher, was das bewirkt.  Ich bin mir
> auch nicht sicher, ob Umlenkungen ohne Kommando überhaupt möglich
> sind, und, was sie dann bedeuten.  Und weil ich mich im
> Allgemeinen – außer, es lässt sich nicht (mit erträglichem
> Aufwand) vermeiden – auf den POSIX‐Standard beschränke,

Umleitungen ohne Befehl sind von der POSIX-Shell-Sprache abgedeckt:

A "simple command" is a sequence of optional variable assignments and
redirections, in any sequence, optionally followed by words and
redirections, terminated by a control operator.

Auch die angegebene Shell-Grammatik deckt das ab.

Laurenz Trossel

unread,
Apr 17, 2023, 2:55:24 PM4/17/23
to
On 2023-04-15, Marcel Logen <33320000...@ybtra.de> wrote:
> Christian Weisgerber in de.comp.os.unix.shell:

>>exec ohne Befehl, nur mit Umleitungen, wird benutzt, um die
>>Filedeskriptoren im gegenwärtigen Shellprozess zu manipulieren.
>
> Ja, so ähnlich hatte ich mir das schon gedacht, als ich mir Hel-
> muts Code anschaute.

$ help exec
exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
...
If COMMAND is not specified, any redirections take effect in the
current shell

Marcel Logen

unread,
Apr 29, 2023, 7:08:02 PM4/29/23
to
Helmut Waitzmann in de.comp.os.unix.shell:

>Marcel Logen <33320000...@ybtra.de>:

[...]

>>Mit der ksh unter OpenBSD wird ohne "exec" das Terminalfenster
>>geschlossen, was für mich auf das erwartete Verhalten hindeutet: Der
>>Befehl nach "exec" ersetzt die laufende Shell.
>
>Dass das Terminalfenster geschlossen wird, deutet für mich darauf hin,
>dass der in ihm laufende Shell sich beendet.  Insofern verstehe ich
>jetzt nicht, warum das Terminalfenster gerade ohne «exec» geschlossen
>wird.  Ich hätte jetzt eher das Gegenteil erwartet.

Ja, richtig! Ich hatte das flacsh in Erinnerung, und weil
mich das unerwartete Schließen des Terminalfensters etwas
beunruhigt hatte, habe ich es auch nicht ein weiteres Mal
probiert.

Letzte Woche konnte ich es allerdings auf dem OpenBSD-PC
noch einmal nachstellen: Es ist, wie wie von Dir und Chri-
stian gesagt.

Sorry für die Verwirrung.

[...]

Marcel
--
Debian GNU/Linux 10.13

Marcel Logen

unread,
Apr 29, 2023, 7:10:35 PM4/29/23
to
Laurenz Trossel in de.comp.os.unix.shell:

>On 2023-04-15, Marcel Logen <33320000...@ybtra.de> wrote:
>> Christian Weisgerber in de.comp.os.unix.shell:

[...]

>$ help exec
>exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
> ...
> If COMMAND is not specified, any redirections take effect in the
> current shell

Danke.

BTW: Dein Artikel hat keine References.

Marcel
--
...9..╭──────╮ ╭─────╮ ╭──────────╮ ╭───╮ ╭────╮ ╭──╮
╰──╮ │ ╰─╮ │ ╰──╮ ..41..│ ╭─╯ ╰───╯ ╭─╯ │ ╰
╮ ╭─────╮ ╭─╮ │ ╰─╮ ╭──╯ │ ╭─╯ ╭─╯ ╭─╯ ╭─────────╯ ╭──╯
╰─╯ ╰───╯ ╰──╯ ╰─╯ ╰───╯ ╰───╯ ╰───────────╯..67..
0 new messages