Warum funktioniert das Lesen, wenn stdin auf fd4 umgeleitet wird?

Warum funktioniert das Lesen, wenn stdin auf fd4 umgeleitet wird?

Was bedeutet das folgende Skript?

exec 4<&0 0</etc/XX/cfg
read line1
exec 0<&4

Es leitet fd0 zu fd4 und „/etc/XX/cfg“ zu fd0 um.

Warum funktioniert es also readimmer noch, sollte das nicht leer sein?

Antwort1

Es leitet stdin (FD0) zu FD4 um, leitet von dort /etc/XX/cfgzu FD0 um, liest eine Zeile von FD0 und verschiebt dann FD4 zurück zu FD0. Kurz gesagt, es speichert, ersetzt und stellt stdin wieder her, während es zwischendurch eine Zeile aus einer Datei liest.

read line1 < /etc/XX/cfgwäre viel einfacher, aber es ist unmöglich, nur anhand des angezeigten Codes zu sagen, ob es sich um einen gültigen Ersatz handelt.

Antwort2

So formulieren Sie dies in Systemaufrufen um (mit C):

exec 4<&0 0</etc/XX/cfg

/* Duplicate fd0 as fd4.  */
dup2 (0, 4);

/* Open file on fd0.
   "open" always uses lowest available descriptor, so we don't need to check it. */
close (0);
open ("/etc/XX/cfg", O_RDONLY);

exec 0<&4

/* Close fd0 and duplicate fd4 as fd0.  */
dup2 (4, 0);

Antwort3

So wie ich das verstehe – basierend auf dem Abschnitt zur UMLEITUNG auf der Bash-Manpage – wird stdin(fd0) in fd4 umgeleitet, dann wird die Eingabe von /etc/XX/cfginto übernommen stdin, was auf fd4 endet.

read line1sollte dann von fd4 nehmen, was dann wieder zu fd0 zurückgesetzt wird.

Eine Demo könnte das, was ich meine, besser verdeutlichen und die Frage beantworten, warum Sie das tun. Fügen Sie dazu eine weitere Zeile hinzu und packen Sie sie in einen Wrapper:

$ vim ./test.sh
#!/bin/bash
exec 4<&0 0</etc/XX/cfg
read line1    # reads from fd4
exec 0<&4
read line2    # reads from fd0

echo $line1 
echo $line2

Sie können über test.sh weiterleiten oder umleiten, stdinaber auch die Konfiguration per Umleitung einlesen. Im obigen Code habe ich also Werte aus der „Konfiguration“ übernommen (Annahme meinerseits aufgrund des Dateinamens – falsch :)), ich kann die Verarbeitung aber auch über stdin durchführen.

z.B:

$ ./test.sh < somefile
$ cat somefile | ./test.sh

Hoffentlich erklärt das es.

verwandte Informationen