Bash: дескрипторы файлов - программирование

Bash: дескрипторы файлов

Я начинаю новичком Bash, но я пытаюсь изучить этот инструмент для работы на компьютерах на днях.

Сейчас я пытаюсь научиться описать файлы. Позвольте мне поделиться некоторыми из моих экспериментов:


#!/bin/bash

# Some dummy multi-line content
read -d '' colours <<- 'EOF'
        red
        green
        blue
EOF

# File descriptor 3 produces colours
exec 3< <(echo "$colours")

# File descriptor 4 filters colours
exec 4> >(grep --color=never green)

# File descriptor 5 is an unlimited supply of violet
exec 5< <(yes violet)

echo Reading colours from file descriptor 3...
cat <&3
echo ... done.

echo Reading colours from file descriptor 3 again...
cat <&3
echo ... done.

echo Filtering colours through file descriptor 4...
echo "$colours" >&4
echo ... done. # Race condition?

echo Dipping into some violet...
head <&5
echo ... done.

echo Dipping into some more violet...
head <&5
echo ... done.

Некоторые вопросы spring, поскольку я вижу вывод, исходящий из вышеперечисленного:

  • fd3 кажется "истощенным" после "потребления", автоматически ли он закрывается после первого использования?
  • Как fd3 отличается от именованного канала? (что-то я уже посмотрел)
  • когда команда yes начинает выполнять? после объявления fd? позже?
  • делает yes stop (CTRL-Z или другое) и перезапускается, когда требуется больше фиолетового?
  • Как я могу получить PID yes?
  • Можно ли получить список "активных" fds?
  • Очень интересное состояние гонки при фильтрации через fd4, можно ли его избежать?
  • будет yes останавливаться только при я exec 5>&-?
  • Имеет ли значение, закрываюсь ли я с >&- или <&-?

Я остановлюсь здесь, пока.

Спасибо!

PS: частичные (пронумерованные) ответы в порядке. Я сам собираю разные кусочки. (хотя всеобъемлющий ответ от одного человека будет впечатляющим!)

4b9b3361

Ответ 1

fd3 кажется "истощенным" после "потребления", автоматически ли он закрывается после первого использования?

Нет, он не закрыт. Это связано с тем, как работает exec. В режиме, в котором вы использовали exec (без аргументов), его функция состоит в том, чтобы упорядочить собственные файловые дескрипторы оболочки в соответствии с запросами, указанными самим перенаправлением ввода/вывода, , а затем оставить их таким образом до тех пор, пока script не будет завершен или они будут изменены позже.

Позже cat получает копию этого файлового дескриптора 3 на своем стандартном вводе (дескриптор файла 0). cat стандартный ввод неявно закрывается, когда cat завершается (или, возможно, хотя и маловероятно, cat закрывает его до его существования, но это не имеет значения). Исходная копия этого файла, являющегося дескриптором файла оболочки 3, остается. Хотя фактический файл достиг EOF, и дальше ничего не будет прочитано.

как fd3 отличается от именованного канала? (что-то я уже посмотрел)

Синтаксис оболочки <(some command) (который не является стандартным синтаксисом оболочки bourne и, я считаю, доступен только в zsh и bash, кстати), может быть фактически реализован с использованием именованных каналов. Вероятно, это не под Linux, потому что есть лучший способ (используя /dev/fd), но он, вероятно, находится в других операционных системах.

В этом смысле этот синтаксис может быть или не быть помощником для настройки именованных каналов.

когда именно команда yes начнет выполнение? после объявления fd? позже?

Как только вычисляется конструкция <(yes violet) (что происходит, когда оценивается exec 5< <(yes violet)).

делает остановку (CTRL-Z или другое) и перезапускается, когда требуется больше фиолетового?

Нет, это не останавливается. Тем не менее, он будет блокироваться достаточно быстро, когда он начнет производить больше выходных данных, чем все, что читает другой конец трубы. Другими словами, буфер трубы будет заполнен.

как я могу получить ПИД-код "да"?

Хороший вопрос! $!, как представляется, содержит его сразу после выполнения yes. Однако, кажется, существует промежуточная подоболочка, и вы действительно получаете pid этой подоболочки. Попробуйте <(exec yes violet), чтобы избежать промежуточного процесса.

Можно ли получить список "активных" fds?

Не из оболочки. Но если вы используете операционную систему, такую ​​как Linux, которая имеет /proc, вы можете просто обратиться к /proc/self/fd.

очень интересное состояние гонки при фильтрации через fd4, можно ли его избежать?

Чтобы избежать этого, вы, вероятно, хотите дождаться завершения процесса grep, прежде чем продолжить через script. Если вы получите идентификатор процесса этого процесса (как указано выше), я думаю, вы должны иметь wait для него.

будет только останавливаться, когда я выполняю 5 > & -?

Да. Тогда произойдет то, что yes будет продолжать пытаться выводить вывод навсегда, но когда другой конец дескриптора файла закрыт, он либо получит ошибку записи (EPIPE), либо сигнал (SIGPIPE), который по умолчанию является фатальным.

имеет значение, закрываю ли я s > & - или < & -?

Нет. Оба синтаксиса доступны для обеспечения согласованности.