Я понимаю, что файловый дескриптор (или файловый обработчик) - это метод файлового ввода-вывода в системах Linux.
Я также знаю, что у каждого процесса есть 3 стандартных потока (а именно stdin, stdout и stderr), которые представлены файлами с дескрипторами от 0 до 3.
Однако я заметил, что у всех процессов, которые я исследовал, lsof -p <pid>
есть дополнительный файловый дескриптор 255
с разрешением на чтение.
Из этого ответа я узнал, что эта особенность специфична для оболочки Bash , однако и ответ, и источник, на который ссылаются, действительно не объясняли, для чего предназначен этот файловый дескриптор.
Мой вопрос:
- Для чего нужен файловый дескриптор 255?
- Могу ли я использовать его в своем скрипте Bash или это просто внутренний рабочий механизм, который не предполагается использовать / манипулировать вручную?
bash
file-descriptors
Чан Триет
источник
источник
Ответы:
Для последней части вашего вопроса:
я могу использовать это?
От
man bash
:Итак, если вы имеете в виду использовать как создание нового fd с этим номером, ответ - нет.
Если вы имеете в виду использовать как: "написать в этот FD":
Или читать из него:
ответ да.
Но, вероятно, это должно быть лучше (независимо от оболочки) использовать
/dev/tty
для доступа кtty
.для чего нужен файловый дескриптор 255?
Как альтернативное подключение к tty в случае fd 1 (
/dev/stdout
/dev/stdin
блокировки ) и fd 0 ( ).Подробнее .
Другие оболочки могут использовать другое число (например, 10 в zsh)
Из списка рассылки :
источник
dd bs=1 | bash -i -c 'sleep .1; ls -l /proc/$$/fd' 2>/tmp/err | tee /tmp/out
. Кроме того, этот комментарий из списка рассылки касается того, когдаbash
он запускается какbash scriptfile
(255
будучи в этом случае открытым дескриптором дляscriptfile
- и в этом случаеls -l /proc/pid/fd
будет печататься очень убедительно255 -> scriptfile
;-)), а не о том, когда он запускается в интерактивном режиме./dev/tty
, а не из fd 0 или fd 1 c) если fds 0, 1 или 2 заблокированы, bash не будет использовать эти 255 fd в качестве альтернативы для чтение ввода от пользователя или для записи вывода команды, подсказок, сообщений об ошибках и т. д.Этот
255
файловый дескриптор является открытым дескриптором для управляющего tty и используется только приbash
запуске в интерактивном режиме.Это позволяет вам перенаправить
stderr
в основную оболочку, в то же время позволяя функционировать элементам управления заданиями (т.е. иметь возможность убивать процессы с помощью ^ C, прерывать их с помощью ^ Z и т. Д.).Пример:
Если вы попробуете это в подобной оболочке
ksh93
, которая просто использует дескриптор файла 2 в качестве ссылки на управляющий терминал,sleep
процесс станет невосприимчивым к ^ C и ^ Z, и его придется убить из другого окна / сеанса. Это связано с тем, что оболочка не сможет установить группу процессовsleep
как переднюю в терминалеtcsetgrp()
, поскольку файловый дескриптор 2 больше не указывает на терминал.Это не является
bash
конкретным, оно также используетсяdash
иzsh
, только, дескриптор не перемещается так высоко (это обычно 10).zsh
также будет использовать этот fd для вывода подсказок и ввода данных пользователем, поэтому просто будет работать следующее:Это не имеет ничего общего с файловыми дескрипторами
bash
, которые используются при чтении скриптов и настройке каналов (которые также были дублированы с помощью той же функции -move_to_high_fd()
), как это было предложено в других ответах и комментариях.bash
использует такое большое число для того, чтобы разрешить fds больше, чем9
при перенаправлениях в оболочке (например,exec 87<filename
); это не поддерживается в других оболочках.Вы можете использовать этот дескриптор файла самостоятельно, но в этом нет особого смысла, потому что вы можете получить дескриптор того же управляющего терминала в любой команде с помощью
... < /dev/tty
.Анализ исходного кода bash :
В
bash
файле дескриптор управляющего терминала хранится вshell_tty
переменной. Если оболочка является интерактивной, эта переменная инициализируется (при запуске или после неудачного выполнения)jobs.c:initialize_job_control()
путем ее дублированияstderr
(еслиstderr
она подключена к терминалу) или путем непосредственного открытия/dev/tty
, а затем снова дублируется на более высокий fd сgeneral.c:move_to_high_fd()
:Если
shell_tty
это еще не управляющий tty, то это сделано так:shell_tty
затем используется дляполучить и установить группу процессов переднего плана с помощью
tc[sg]etpgrp
injobs.c:maybe_give_terminal_to()
,jobs.c:set_job_control()
иjobs.c:give_terminal_to()
получить и установить
termios(3)
параметры вjobs.c:get_tty_state()
иjobs.c:set_tty_state()
получить размер окна терминала с
ioctl(TIOCGWINSZ)
вlib/sh/winsize.c:get_new_window_size()
.move_to_high_fd()
обычно используется со всеми дескрипторами временных файлов, используемыхbash
(файлы сценариев, каналы и т. д.), поэтому путаница в большинстве комментариев, которые заметно выделяются при поиске в Google.Файловые дескрипторы, используемые внутренне
bash
, в том числеshell_tty
, установлены на close-on-exec, поэтому они не будут передаваться командам.источник