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 tty
perangkat). 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 stdout
dan 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 dash
I memiliki 10, yang mengarah ke /dev/tty
daripada spesifik tty
/ pts
perangkat 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 eval
diperlukan ketika mengarahkan kembali deskriptor file yang terdapat dalam variabel, jika tidak bash
akan memperluas variabel tetapi anggap itu bagian dari perintah (dalam hal ini akan mencoba exec
perintah 0
atau 1
atau 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 ls
sepertinya solusi terbaik di sini.
Untuk informasi lebih lanjut tentang portabilitas /proc/$$/fd
, silakan lihat Portabilitas tautan deskriptor file . Jika /proc/$$/fd
tidak tersedia, maka penggantian untuk $(ls /proc/$$/fd)
, menggunakan lsof
(jika tersedia) akan menjadi $(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-)
.
/proc
hanya tersedia di Linux.
/proc/PID/fd
tidak terlalu portabel. Tetapi mengatakan bahwa /proc
hanya 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 echo
dan "
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.