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 tty
direkt 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 stdout
und 2 für stderr
. Darüber hinaus scheinen in einigen Shells standardmäßig andere Dateideskriptoren geöffnet zu sein. In bash
haben Sie beispielsweise 255 (auch für Terminal-E / A) und in dash
I 10, was /dev/tty
eher auf das spezifische tty
/ pts
Gerä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 eval
erforderlich ist, wenn Sie den in einer Variablen enthaltenen Dateideskriptor umleiten. Wenn dies nicht bash
der Fall ist, wird die Variable erweitert, aber als Teil des Befehls betrachtet (in diesem Fall wird versucht, exec
den Befehl 0
oder den 1
zu 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 ls
scheint dies hier die beste Lösung zu sein.
Weitere Informationen zur Portabilität von /proc/$$/fd
finden Sie unter Portabilität von Dateideskriptor-Links . Wenn dies /proc/$$/fd
nicht 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-)
.
/proc
ist nur unter Linux verfügbar.
/proc/PID/fd
das nicht sehr portabel ist. Zu sagen, dass dies /proc
nur 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 echo
und 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 .