Die meisten Befehle haben einen einzelnen Eingabekanal (Standardeingabe, Dateideskriptor 0) und einen einzelnen Ausgabekanal (Standardausgabe, Dateideskriptor 1) oder bearbeiten mehrere Dateien, die sie selbst öffnen (Sie übergeben ihnen einen Dateinamen). (Dies ergibt sich zusätzlich aus dem Standardfehler (fd 2), der normalerweise bis zum Benutzer gefiltert wird.) Manchmal ist es jedoch zweckmäßig, einen Befehl zu haben, der als Filter für mehrere Quellen oder für mehrere Ziele fungiert. Hier ist beispielsweise ein einfaches Skript, das die ungeradzahligen Zeilen in einer Datei von den geradzahligen trennt
while IFS= read -r line; do
printf '%s\n' "$line"
if IFS= read -r line; then printf '%s\n' "$line" >&3; fi
done >odd.txt 3>even.txt
Angenommen, Sie möchten einen anderen Filter auf die ungeradzahligen und die geradzahligen Zeilen anwenden (aber nicht wieder zusammensetzen, das wäre ein anderes Problem, das von der Shell im Allgemeinen nicht realisierbar wäre). In der Shell können Sie die Standardausgabe eines Befehls nur an einen anderen Befehl weiterleiten. Um einen anderen Dateideskriptor weiterzuleiten, müssen Sie ihn zuerst auf fd 1 umleiten.
{ while … done | odd-filter >filtered-odd.txt; } 3>&1 | even-filter >filtered-even.txt
Ein anderer, einfacherer Anwendungsfall ist das Filtern der Fehlerausgabe eines Befehls .
exec M>&N
Leitet einen Dateideskriptor für den Rest des Skripts auf einen anderen um (oder bis ein anderer solcher Befehl die Dateideskriptoren erneut ändert). Es gibt einige Überlappungen in der Funktionalität zwischen exec M>&N
und somecommand M>&N
. Das exec
Formular ist insofern mächtiger, als es nicht verschachtelt werden muss:
exec 8<&0 9>&1
exec >output12
command1
exec <input23
command2
exec >&9
command3
exec <&8
Weitere interessante Beispiele:
Und noch mehr Beispiele:
PS Dies ist eine überraschende Frage des Autors des am häufigsten bewerteten Beitrags auf der Website, der die Umleitung durch fd 3 verwendet !
while IFS= read -r line;
? So wie ich es sehe, hat IFS hier keine Auswirkung, da Sie nur einer Variablen ( Zeile ) einen Wert zuweisen . Siehe diese Frage.IFS
einen Unterschied macht, auch wenn Sie eine einzelne Variable lesen (um das führende Leerzeichen beizubehalten).sed -ne 'w odd.txt' -e 'n;w even.txt'
?Hier ist ein Beispiel für die Verwendung zusätzlicher FDs als Chat-Kontrolle für Bash-Skripte:
quelle
Im Kontext von Named Pipes (FIFOS) kann die Verwendung eines zusätzlichen Dateideskriptors ein blockierungsfreies Piping-Verhalten ermöglichen.
Siehe: Named Pipe wird im Skript vorzeitig geschlossen?
quelle
Ein zusätzlicher Dateideskriptor ist hilfreich, wenn Sie die Standardausgabe in einer Variablen abfangen und dennoch auf den Bildschirm schreiben möchten, beispielsweise in einer Bash-Skript-Benutzeroberfläche
quelle
Hier ist noch ein anderes Szenario, wenn die Verwendung eines zusätzlichen Dateideskriptors angemessen erscheint (in Bash):
Shell-Skript-Kennwortsicherheit für Befehlszeilenparameter
quelle
Beispiel: Verwenden von Flock, um die serielle Ausführung von Skripten mit Dateisperren zu erzwingen
Ein Beispiel ist die Verwendung der Dateisperrung, um zu erzwingen, dass Skripts systemweit seriell ausgeführt werden. Dies ist nützlich, wenn Sie nicht möchten, dass zwei Skripte derselben Art mit denselben Dateien arbeiten. Andernfalls würden sich die beiden Skripte gegenseitig stören und möglicherweise Daten beschädigen.
Verwenden Sie Flock funktional, indem Sie Sperren und Entsperren definieren
Sie können diese Sperr- / Entsperrlogik auch in wiederverwendbare Funktionen einbinden. Die folgende integrierte
trap
Shell hebt die Dateisperre automatisch auf, wenn das Skript beendet wird (entweder Fehler oder Erfolg).trap
Bereinigen Sie Ihre Dateisperren. Der Pfad/tmp/file.lock
sollte fest codiert sein, damit mehrere Skripte versuchen können, ihn zu sperren.Die
unlock
obige Logik besteht darin, die Datei zu löschen, bevor die Sperre aufgehoben wird. Auf diese Weise wird die Sperrdatei bereinigt. Da die Datei gelöscht wurde, kann eine andere Instanz dieses Programms die Dateisperre erhalten.Verwendung von Sperr- und Entsperrfunktionen in Skripten
Sie können es in Ihren Skripten wie im folgenden Beispiel verwenden.
Wenn Sie möchten, dass Ihr Code wartet, bis er gesperrt werden kann, können Sie das Skript wie folgt anpassen:
quelle
Als konkretes Beispiel habe ich gerade ein Skript geschrieben, das die Timing-Informationen eines Unterbefehls benötigt. Durch die Verwendung eines zusätzlichen Dateideskriptors konnte ich den
time
Befehl stderr erfassen, ohne den Unterbefehl stdout oder stderr zu unterbrechen.Dies bewirkt, dass der Punkt
ls
"stderr" auf "fd 3", der Punkt "fd 3" auf "stderr" des Skripts und der Punkttime
"stderr" auf eine Datei verweist. Wenn das Skript ausgeführt wird, stimmen stdout und stderr mit den Unterbefehlen überein, die wie gewohnt umgeleitet werden können. Nurtime
die Ausgabe von wird in die Datei umgeleitet.quelle