Чи є спосіб закрити всі дескриптори відкритого файлу, не маючи попереднього явного списку?
Чи є спосіб закрити всі дескриптори відкритого файлу, не маючи попереднього явного списку?
Відповіді:
Щоб відповісти буквально, закрити всі відкриті дескриптори файлів для bash
:
for fd in $(ls /proc/$$/fd); do
eval "exec $fd>&-"
done
Однак це насправді не є хорошою ідеєю, оскільки вона закриє основні дескриптори файлів, необхідні оболонці для введення та виводу. Якщо ви це зробите, жодна із запущених програм не відображатиметься на терміналі (якщо вони не записуються tty
безпосередньо на пристрій). Якщо факт у моїх тестах закриття stdin
( exec 0>&-
) просто призводить до виходу інтерактивної оболонки.
Те, що ви насправді хочете зробити, це скоріше закрити всі дескриптори файлів, які не є частиною базової операції оболонки. Це 0 за stdin
, 1 за stdout
і 2 за stderr
. Крім цього, деякі оболонки також за замовчуванням мають інші дескриптори файлів. В bash
, наприклад, у Вас є 255 (також для терміналу введення / виведення) і dash
у мене 10, що вказує на , /dev/tty
а не конкретного tty
/ pts
пристрої термінал використовує. Щоб закрити все, крім 0, 1, 2 та 255, у bash
:
for fd in $(ls /proc/$$/fd); do
case "$fd" in
0|1|2|255)
;;
*)
eval "exec $fd>&-"
;;
esac
done
Слід також зазначити , що eval
потрібно при перенаправлення дескриптора файлу , що міститься в змінній, якщо не bash
буде розширювати змінну , але розглянути його частина команди (в цьому випадку вона буде намагатися exec
команди 0
або 1
або в залежності від того дескриптора файлу , який ви намагаєтеся закрити).
ПРИМІТКА. Також використання глобула замість ls
(наприклад /proc/$$/fd/*
), здається, відкриє додатковий дескриптор файлу для глобуса, тому тут ls
здається найкращим рішенням.
Для отримання додаткової інформації про портативність /proc/$$/fd
, див. Портативність посилань дескриптора файлів . Якщо /proc/$$/fd
недоступний, то зменшення заміни на $(ls /proc/$$/fd)
, використовуючи lsof
(якщо таке є), буде $(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-)
.
/proc
доступний лише під Linux.
/proc/PID/fd
це не дуже портативно. Але твердження, що /proc
доступне лише під Linux, не є правильним твердженням.
<&-
форму, чи є вона різною / потрібною?
В останніх версіях Bash (4.1 і далі, рік 2009 і пізніші) ви можете вказати дескриптор файлу для закриття за допомогою змінної оболонки:
for fd in $(ls /proc/$$/fd/); do
[ $fd -gt 2 ] && exec {fd}<&-
done
Ця функція була в оболонці Корна (з 1993 року?), Але, мабуть, знадобилося певний час, щоб пробитися до Баша.
Очистити всі дескриптори файлів, за винятком i / o / e поточної оболонки, але також виключає ті, що надаються в якості аргументів
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
}
Ще один спосіб без "eval" - використання форми:
$ 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
Ні. Ядро може закривати лише один FD одночасно, і bash не має "групових команд" для FD.
for fd in $(ls -1 /proc/27343/fd); do echo exec $fd">&"-; done
Видаліть echo
і "
після тестування.
Якщо це не сама оболонка, а команда, яку слід запустити, ви можете використовувати nohup
.
>&-
не може бути параметром; перенаправлення аналізується перед розширенням параметра.
exec {fd}>&-
працює.