Existe uma maneira de fechar todos os descritores de arquivos abertos, sem ter uma lista explícita deles previamente?
Existe uma maneira de fechar todos os descritores de arquivos abertos, sem ter uma lista explícita deles previamente?
Respostas:
Para responder literalmente, feche todos os descritores de arquivos abertos para bash
:
for fd in $(ls /proc/$$/fd); do
eval "exec $fd>&-"
done
No entanto, isso realmente não é uma boa ideia, pois fechará os descritores de arquivo básicos que o shell precisa para entrada e saída. Se você fizer isso, nenhum dos programas executados terá a saída exibida no terminal (a menos que escreva tty
diretamente no dispositivo). Se fato em meus testes, o fechamento stdin
( exec 0>&-
) apenas faz com que um shell interativo saia.
O que você realmente deseja fazer é fechar todos os descritores de arquivos que não fazem parte da operação básica do shell. Estes são 0 para stdin
, 1 para stdout
e 2 para stderr
. Além disso, alguns shells também parecem ter outros descritores de arquivos abertos por padrão. Em bash
, por exemplo, você possui 255 (também para o terminal de E / S) e em dash
10, que aponta para /dev/tty
o dispositivo tty
/ pts
dispositivo específico que o terminal está usando. Para fechar tudo além de 0, 1, 2 e 255 em bash
:
for fd in $(ls /proc/$$/fd); do
case "$fd" in
0|1|2|255)
;;
*)
eval "exec $fd>&-"
;;
esac
done
Note também que eval
é necessária quando redirecionando o descritor de arquivo contido em uma variável, se não bash
irá expandir a variável, mas considerá-lo parte do comando (neste caso, seria tentar exec
o comando 0
ou 1
ou qualquer descritor de arquivo que você está tentando fechar).
NOTA: O uso de um globo em vez de ls
(por exemplo /proc/$$/fd/*
) parece abrir um descritor de arquivo extra para o globo, assim ls
parece a melhor solução aqui.
Para obter mais informações sobre portabilidade /proc/$$/fd
, consulte Portabilidade dos links do descritor de arquivos . Se /proc/$$/fd
não estiver disponível, seria uma queda no substituto de $(ls /proc/$$/fd)
, usando lsof
(se disponível) $(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-)
.
/proc
está disponível apenas no Linux.
/proc/PID/fd
não é muito portátil. Mas dizer que /proc
só está disponível no Linux não é uma afirmação correta.
<&-
formulário, é diferente / necessário?
Nas versões recentes do Bash (4.1 e seguintes, ano de 2009 e posteriores), você pode especificar o descritor de arquivo a ser fechado usando uma variável de shell:
for fd in $(ls /proc/$$/fd/); do
[ $fd -gt 2 ] && exec {fd}<&-
done
O recurso já estava no shell Korn (desde 1993?), Mas aparentemente levou algum tempo para entrar no Bash.
Limpe todos os descritores de arquivo, exceto i / o / e do shell atual, mas também exclui os fornecidos como argumentos
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
}
Outra maneira sem "eval" é usar o formulário:
$ 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
Não. O kernel pode fechar apenas um FD por vez e o bash não possui "comandos de grupo" para FDs.
for fd in $(ls -1 /proc/27343/fd); do echo exec $fd">&"-; done
Remova o echo
e o "
após o teste.
Se não for para o próprio shell, mas para que um comando seja executado, você poderá usá-lo nohup
.
>&-
não pode ser um parâmetro; o redirecionamento é analisado antes da expansão do parâmetro.
exec {fd}>&-
funciona.