Önceden açık bir liste olmadan tüm açık dosya tanımlayıcılarını kapatmanın bir yolu var mı?
Önceden açık bir liste olmadan tüm açık dosya tanımlayıcılarını kapatmanın bir yolu var mı?
Yanıtlar:
Kelimenin tam anlamıyla cevaplamak için aşağıdakiler için tüm açık dosya tanımlayıcılarını kapatın bash
:
for fd in $(ls /proc/$$/fd); do
eval "exec $fd>&-"
done
Ancak bu gerçekten iyi bir fikir değildir, çünkü kabuğun girdi ve çıktı için ihtiyaç duyduğu temel dosya tanımlayıcılarını kapatacaktır. Bunu yaparsanız, çalıştırdığınız programların hiçbiri çıktılarını terminalde göstermez ( tty
cihaza doğrudan yazmadıkları sürece ). Eğer testlerimde gerçeği closing stdin
( exec 0>&-
) sadece interaktif bir kabuk çıkmak neden olur.
Aslında yapmak isteyebileceğiniz şey, kabuğun temel işleminin bir parçası olmayan tüm dosya tanımlayıcılarını kapatmaktır. Bunlar için 0 stdin
, 1 için stdout
ve 2 için stderr
. Bunun üzerine bazı kabuklar varsayılan olarak açık olan diğer dosya tanımlayıcılarına sahip gibi görünüyor. Olarak bash
, örneğin, 255 (aynı zamanda, terminal I / O için) ve var dash
I olan 10, puan /dev/tty
yerine belirli daha tty
/ pts
cihazın uç kullanıyor. 0, 1, 2 ve 255 dışında her şeyi kapatmak için bash
:
for fd in $(ls /proc/$$/fd); do
case "$fd" in
0|1|2|255)
;;
*)
eval "exec $fd>&-"
;;
esac
done
Ayrıca Not eval
bir değişken içerdiği dosya tanımlayıcısı yönlendirme yaparken değilse, gerekli bash
değişkeni genişletmek ancak komuta parçası bunu dikkate alacaktır (bu durumda çalışacaklarını exec
komuta 0
veya 1
veya hangisi dosya tanıtıcı size yakın çalıştığınız).
NOT: Ayrıca ls
(örneğin /proc/$$/fd/*
) yerine bir glob kullanmak glob için ekstra bir dosya tanımlayıcı açmak ls
gibi görünüyor , bu yüzden burada en iyi çözüm gibi görünüyor.
Taşınabilirliği hakkında daha fazla bilgi için /proc/$$/fd
lütfen Dosya tanımlayıcı bağlantılarının taşınabilirliği konusuna bakın . Kullanılamıyorsa /proc/$$/fd
, (varsa) $(ls /proc/$$/fd)
kullanarak, yerine bir damla lsof
olur $(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-)
.
/proc
yalnızca Linux altında kullanılabilir.
/proc/PID/fd
çok taşınabilir olmadığını söyleseydin haklısın . Ancak bunun /proc
sadece Linux altında mevcut olduğunu söylemek doğru bir ifade değildir .
<&-
formu kullanıyor, farklı / gerekli mi?
Bash son sürümlerinde (daha sonra 4.1 ve sonrası, 2009 yılı ve) size olabilir bir kabuk değişkeni kullanarak kapatmak için dosya tanımlayıcısı belirtin:
for fd in $(ls /proc/$$/fd/); do
[ $fd -gt 2 ] && exec {fd}<&-
done
Özellik zaten Korn kabuğundaydı (1993'ten beri?) Ama görünüşe göre Bash'a girmesi biraz zaman aldı.
Geçerli kabuğun i / o / e dışındaki tüm dosya tanımlayıcılarını temizler, ancak bağımsız değişken olarak sağlananları da hariç tutar
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
}
Hiç "eval" olmadan başka bir yolu, formu kullanmaktır:
$ 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
Hayır. Çekirdek aynı anda yalnızca bir FD'yi kapatabilir ve bash'ın FD'ler için "grup komutları" yoktur.
for fd in $(ls -1 /proc/27343/fd); do echo exec $fd">&"-; done
Testten sonra echo
ve "
testini kaldırın .
Bu, kabuğun kendisi için değil, bir komutun çalıştırılması içinse kullanabilirsiniz nohup
.
>&-
bir parametre olamaz; yeniden yönlendirme, parametre genişletmeden önce ayrıştırılır.
exec {fd}>&-
çalışıyor.