Apakah ada cara untuk menutup semua deskriptor file terbuka, tanpa memiliki daftar eksplisit sebelumnya?
Apakah ada cara untuk menutup semua deskriptor file terbuka, tanpa memiliki daftar eksplisit sebelumnya?
Jawaban:
Untuk menjawab secara harfiah, untuk menutup semua deskriptor file terbuka untuk bash:
for fd in $(ls /proc/$$/fd); do
eval "exec $fd>&-"
done
Namun ini sebenarnya bukan ide yang baik karena akan menutup deskriptor file dasar yang dibutuhkan oleh input dan output. Jika Anda melakukan ini, tidak ada program yang Anda jalankan akan menampilkan hasilnya di terminal (kecuali jika mereka langsung menulis ke ttyperangkat). Jika kenyataannya dalam tes saya menutup stdin( exec 0>&-) hanya menyebabkan shell interaktif untuk keluar.
Apa yang sebenarnya ingin Anda lakukan adalah menutup semua deskriptor file yang bukan bagian dari operasi dasar shell. Ini adalah 0 untuk stdin, 1 untuk stdoutdan 2 untuk stderr. Selain itu, beberapa shell juga tampaknya memiliki deskriptor file lain yang terbuka secara default. Di bash, misalnya, Anda memiliki 255 (juga untuk terminal I / O) dan di dashI memiliki 10, yang mengarah ke /dev/ttydaripada spesifik tty/ ptsperangkat yang digunakan terminal. Untuk menutup semuanya kecuali 0, 1, 2 dan 255 di bash:
for fd in $(ls /proc/$$/fd); do
case "$fd" in
0|1|2|255)
;;
*)
eval "exec $fd>&-"
;;
esac
done
Perhatikan juga bahwa evaldiperlukan ketika mengarahkan kembali deskriptor file yang terdapat dalam variabel, jika tidak bashakan memperluas variabel tetapi anggap itu bagian dari perintah (dalam hal ini akan mencoba execperintah 0atau 1atau deskriptor file mana pun yang Anda coba tutup).
CATATAN: Juga menggunakan glob bukannya ls(misalnya /proc/$$/fd/*) tampaknya membuka deskriptor file tambahan untuk glob, jadi lssepertinya solusi terbaik di sini.
Untuk informasi lebih lanjut tentang portabilitas /proc/$$/fd, silakan lihat Portabilitas tautan deskriptor file . Jika /proc/$$/fdtidak tersedia, maka penggantian untuk $(ls /proc/$$/fd), menggunakan lsof(jika tersedia) akan menjadi $(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-).
/prochanya tersedia di Linux.
/proc/PID/fdtidak terlalu portabel. Tetapi mengatakan bahwa /prochanya tersedia di Linux bukanlah pernyataan yang benar.
<&-formulir, apakah ada bedanya / diperlukan?
Dalam versi terbaru dari Bash (4.1 dan seterusnya, tahun 2009 dan yang lebih baru), Anda dapat menentukan deskriptor file untuk ditutup menggunakan variabel shell:
for fd in $(ls /proc/$$/fd/); do
[ $fd -gt 2 ] && exec {fd}<&-
done
Fitur itu sudah ada di shell Korn (sejak 1993?) Tetapi tampaknya butuh waktu untuk masuk ke Bash.
Hapus semua deskriptor file kecuali i / o / e dari shell saat ini, tetapi juga mengecualikan yang disediakan sebagai argumen
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
}
Cara lain tanpa "eval" sama sekali, adalah dengan menggunakan formulir:
$ 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
Tidak. Kernel hanya dapat menutup satu FD pada satu waktu, dan bash tidak memiliki "perintah grup" untuk FD.
for fd in $(ls -1 /proc/27343/fd); do echo exec $fd">&"-; done
Hapus echodan "setelah pengujian.
Jika ini bukan untuk shell itu sendiri tetapi untuk menjalankan perintah maka Anda dapat menggunakan nohup.
>&-tidak bisa menjadi parameter; pengalihan diuraikan sebelum ekspansi parameter.
exec {fd}>&-berfungsi.