Gibt es eine Möglichkeit, alle geöffneten Dateideskriptoren zu schließen, ohne vorher eine explizite Liste zu haben?
Gibt es eine Möglichkeit, alle geöffneten Dateideskriptoren zu schließen, ohne vorher eine explizite Liste zu haben?
Antworten:
Wörtlich antworten, alle geöffneten Dateideskriptoren schließen für bash:
for fd in $(ls /proc/$$/fd); do
eval "exec $fd>&-"
done
Dies ist jedoch keine gute Idee, da dadurch die grundlegenden Dateideskriptoren geschlossen werden, die die Shell für die Eingabe und Ausgabe benötigt. Wenn Sie dies tun, wird bei keinem der von Ihnen ausgeführten Programme die Ausgabe auf dem Terminal angezeigt (es sei denn, sie schreiben ttydirekt auf das Gerät). Wenn in meinen Tests durch das Schließen von stdin( exec 0>&-) nur eine interaktive Shell beendet wird.
Möglicherweise möchten Sie tatsächlich alle Dateideskriptoren schließen, die nicht Teil der Grundoperation der Shell sind. Dies sind 0 für stdin, 1 für stdoutund 2 für stderr. Darüber hinaus scheinen in einigen Shells standardmäßig andere Dateideskriptoren geöffnet zu sein. In bashhaben Sie beispielsweise 255 (auch für Terminal-E / A) und in dashI 10, was /dev/ttyeher auf das spezifische tty/ ptsGerät zeigt, das das Terminal verwendet. So schließen Sie alles außer 0, 1, 2 und 255 in bash:
for fd in $(ls /proc/$$/fd); do
case "$fd" in
0|1|2|255)
;;
*)
eval "exec $fd>&-"
;;
esac
done
Beachten Sie auch, dass dies evalerforderlich ist, wenn Sie den in einer Variablen enthaltenen Dateideskriptor umleiten. Wenn dies nicht bashder Fall ist, wird die Variable erweitert, aber als Teil des Befehls betrachtet (in diesem Fall wird versucht, execden Befehl 0oder den 1zu schließenden Dateideskriptor zu verwenden).
HINWEIS: Auch die Verwendung eines Globs anstelle von ls(z. B. /proc/$$/fd/*) scheint einen zusätzlichen Dateideskriptor für den Glob zu öffnen, daher lsscheint dies hier die beste Lösung zu sein.
Weitere Informationen zur Portabilität von /proc/$$/fdfinden Sie unter Portabilität von Dateideskriptor-Links . Wenn dies /proc/$$/fdnicht verfügbar ist, wird ein Ersatz für die $(ls /proc/$$/fd)Verwendung von lsof(falls verfügbar) verwendet $(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-).
/procist nur unter Linux verfügbar.
/proc/PID/fddas nicht sehr portabel ist. Zu sagen, dass dies /procnur unter Linux verfügbar ist, ist jedoch keine korrekte Aussage.
<&-Formular. Ist es anders / erforderlich?
In der letzten Versionen von Bash (4.1 und weiter, Jahr 2009 und später) Sie können den Dateideskriptor angeben zu schließen , um einen Shell - Variable mit:
for fd in $(ls /proc/$$/fd/); do
[ $fd -gt 2 ] && exec {fd}<&-
done
Das Feature war bereits in Korn Shell (seit 1993?), Hat aber anscheinend einige Zeit gebraucht, um in Bash einzudringen.
Löschen Sie alle Dateideskriptoren mit Ausnahme von i / o / e der aktuellen Shell, schließen Sie jedoch auch die als Argumente angegebenen aus
clear_fds() {
for fd in $(compgen -G "/proc/$BASHPID/fd/*"); do
fd=${fd/*\/}
if [[ ! " $* " =~ " ${fd} " ]]; then
case "$fd" in
0|1|2|255)
;;
*)
eval "exec $fd>&-"
;;
esac
fi
done
}
Ein anderer Weg ohne "Auswertung" ist die Verwendung des Formulars:
$ exec {var_a}>> file.txt
$ echo $var_a
10
$ ls -l /proc/self/fd/10
l-wx------ 1 0 0 64 Dec 11 18:32 /proc/self/fd/10 -> /run/user/0/tmp/file.txt
$ echo "aaaaa" >&$var_a
$ cat file.txt
aaaaa
$ exec {var_a}>&-
$ ls /proc/self/fd/10
ls: cannot access '/proc/self/fd/10': No such file or directory
Nein. Der Kernel kann jeweils nur einen FD schließen, und bash verfügt nicht über "Gruppenbefehle" für FDs.
for fd in $(ls -1 /proc/27343/fd); do echo exec $fd">&"-; done
Entfernen Sie das echound das "nach dem Testen.
Wenn dies nicht für die Shell selbst ist, sondern für die Ausführung eines Befehls, können Sie verwenden nohup.
>&-kann kein Parameter sein. Die Umleitung wird vor der Parametererweiterung analysiert.
exec {fd}>&-funktioniert heutzutage .