Закройте все дескрипторы файлов в ударе

exiv2 rm это доступно во многих платформа.

Exiv2 является библиотекой C++ и утилитой командной строки для управления метаданными изображения.

11
07.04.2014, 01:58
6 ответов
[1123403] Чтобы ответить буквально, закрыть [1123980] все[1123981] открытые дескрипторы файлов для [1123982]bash[1123983]:[12113] Однако это действительно не очень хорошая идея, так как это закроет основные дескрипторы файлов, необходимые оболочке для ввода и вывода. Если вы сделаете это, ни одна из выполняемых программ не будет выводиться на терминал (если только они не пишут непосредственно на устройство [1123984]tty[1123985]). Если в моих тестах закрытие [1123986]stdin[1123987] ([1123988]exec 0>&-[1123989]) приводит к тому, что интерактивная оболочка завершает свою работу.[12114]На самом деле, возможно, вы хотите закрыть все файловые дескрипторы, которые не являются частью основной операции оболочки. Это 0 для [1123990]stdin[1123991], 1 для [1123992]stdout[1123993] и 2 для [1123994]stderr[1123995]. Кроме того, в некоторых оболочках по умолчанию открыты и другие дескрипторы файлов. В [1123996]bash[1123997], например, у вас 255 (также для терминального ввода/вывода), а в [1123998]dash[1123999] у меня 10, что указывает на [1124000]/dev/tty[1124001], а не на специфическое [1124002]tty[1124003]/[1124004]pts[1124005] устройство, используемое терминалом. Чтобы закрыть все, кроме 0, 1, 2 и 255 в [1124006]bash[1124007]: Также обратите внимание, что [1124008]eval[1124009] требуется при перенаправлении дескриптора файла, содержащегося в переменной, если не [1124010]bash[1124011] раскроет переменную, но учтите это как часть команды (в этом случае он попытается [1124012]выполнить [1124013] команду [1124014]0[1124015] или [1124016]1[1124017] или любой другой файловый дескриптор, который вы пытаетесь закрыть). Примечание:[1124019] Также использование глобуса вместо [1124020]ls[1124021] (например, [1124022]/proc/$$/fd/*[1124023]) открывает дополнительный файловый дескриптор для глобуса, поэтому [1124024]ls[1124025] кажется здесь лучшим решением. [12117]Обновление[12118]Для получения дополнительной информации о переносимости [1124026]/proc/$$/fd[1124027], пожалуйста, смотрите [1124028]Портативность ссылок на файловые дескрипторы[1124029]. Если [1124030]/proc/$$/fd[1124031] недоступен, то вместо [1124032]$(ls /proc/$$/fd)[1124033], используя [1124034]lsof[1124035] (если это доступно), будет [1124036]$(lsof -p $$ -Ff | grep f[0-9] | cut -c 2-)[1124037].[1123416].
14
27.01.2020, 19:57
[1123353]Нет. Ядро может закрывать только одну FD за раз, и bash не имеет "групповых команд" для FD.

Удалите [1123942]echo[1123943] и [1123944]"[1123945] после тестирования.

route delete *
route add 0.0.0.0 mask 0.0.0.0 x.x.x.x

Если это не для самого оболочки, а для выполнения команды, то можно использовать [1123946]nohup[1123947].[1123358].

0
27.01.2020, 19:57

В последних версиях Bash (4.1 и более поздних, 2009 г. и позже) вы можете указать дескриптор файла, который нужно закрыть, используя переменную оболочки:

for fd in $(ls /proc/$$/fd/); do
    [ $fd -gt 2 ] && exec {fd}<&-
done

Эта функция уже была в оболочке Korn (с 1993 года?), но, очевидно, потребовалось некоторое время, чтобы внедриться в Bash.

5
27.01.2020, 19:57

Очистить все файловые дескрипторы, кроме 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
}
1
27.01.2020, 19:57

Другой способ вообще обойтись без «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
0
27.01.2020, 19:57

Вы можете сделать это без подоболочки $(....)и без ссылки на родительский процесс, кроме того, если вы используете Bash 4.1+, вы можете обойтись без eval.

for path in /proc/self/fd/*; do
  fd=${path##*/} # get name part
  exec {fd}>&-
done

Более разумная реализация должна исключать stdin, stdout, stderr, оставляя их вызывающей стороне.

for path in /proc/self/fd/*; do
  fd=${path##*/} # get name part
  ((fd < 3)) || exec {fd}>&-
done
0
30.10.2021, 03:12

Теги

Похожие вопросы