Я бы хотел, чтобы скрипт bash выводил дополнительную информацию в файловые дескрипторы (FD), большие или равные 3, когда они открыты. Чтобы проверить, открыт ли FD, я разработал следующий трюк:
if (printf '' 1>&3) 2>&-; then
# File descriptor 3 is open
else
# File descriptor 3 is not open
fi
Этого достаточно для моих нужд, но мне любопытно, есть ли более идиоматический способ проверки, действителен ли FD. Меня особенно интересует, существует ли отображение fcntl(1)
системного вызова на команду оболочки, которая позволила бы извлекать флаги FD ( O_WRONLY
и O_RDWR
проверять, является ли FD доступным для записи, и O_RDONLY
и O_RDWR
проверять, является ли FD читаемым).
источник
<>
? Оболочка не будет читать из своего stderr, почему вы хотите открыть ее в режиме чтения + записи? Что вы имеете в виду с тем, что произошло с внутренним? ?В описании использования приложения POSIX вы найдете следующее:
command
Вот почему вы можете просто сделать:
Или...
Который будет записывать строку, за которой следует электронная
\n
строка, либо в stdout, либо в 3, и все равно передавать ненулевой статус выхода, когда 3 не открыта, потому что математика, выполненная в$?
результате, не в состоянии преобразовать восьмеричный 08 в десятичный%, но обрезает до нуля вообще восьмеричное 00 .Или...
Но если вы используете
ksh93
, вы можете просто сделать:Для списка открытых файловых дескрипторов. Добавьте,
-l
чтобы увидеть, куда они идут.источник
Дескрипторы открытых файлов можно найти в
/proc/<pid>/fd
. Например, перечислить дескрипторы открытых файлов текущей оболочки,ls -l /proc/$$/fd
которые должны дать вам что-то вроде:Когда вы открываете файл с помощью:
Должен быть указан новый
ls -l /proc/$$/fd
:Если вы закроете файловый дескриптор снова,
exec 7>&-
его тоже не будет в списке/proc/$$/fd
.источник
pfiles <pid>
чтобы увидеть, какой файловый дескриптор подключен к какому файлу приls -l
отображении соединения в Linux.[ -e /proc/$$/fd/3 ]
, но я предпочитаю не полагаться на procfs, поскольку она устарела во FreeBSD и, возможно, в других un * unes.pfiles <pid>
илиlsof -p <pid>
посмотреть, какие файловые дескрипторы открыты./proc
не существует вообще на OpenBSD. В FreeBSD и NetBSD он должен бытьmount
явно задан и/proc/<PID>
не иметь подкаталогаfd
.Ваш трюк выглядит мило; но для идиоматического способа мне интересно, почему вы не использовали:
источник
{ true >&3; } 2> /dev/null
чтобы избежать вилки. Или{ command exec >&3; } 2> /dev/null
если вы хотите перенаправить стандартный вывод на него.{ true >&3; } 2> /dev/null
также не повлияет на текущую среду и не будет разветвляться (кроме как в оболочке Bourne). Я имею в виду, что(exec 1>&3) 2>&-
вернет истину для открытого файла в режиме только для чтения.exec
специальная встроенная функция выйдет из оболочки в случае ее сбоя (для bash, только в режиме соответствия POSIX).command exec
предотвращает это.true
не является специальным встроенным. Обратите внимание , чтоexec
иcommand exec
действительно влияют на текущую среду (вот почему я сказал , если вы хотите , чтобы перенаправить стандартный вывод на него ).Если вы заинтересованы в решении с низким уровнем разветвления, чтобы использовать его повторно, я бы предложил эту функцию:
И вот что он производит с
zsh
:источник
exec >&3
будет убивать оболочку, когда 3 не открыт.zsh
иbash
. Не могли бы вы предоставить оболочку , на которой неисправныйexec
вызвалаexit
?bash
делатьset -o posix
и попробуйте еще раз. Вzsh
... я думаю, что это вопрос установки переменной envPOSIX_BUILTINS
в ненулевое значение - но я забываю не случайно. В любом случае,zsh
это не оболочка, которая пытается соответствовать POSIX, и поэтому она определенно нестандартна. Обе эти оболочки избегают совместимости за то, что некоторые считают удобством.set -o posix
попытка удалась.Это кажется очень простым (см. Комментарии):
В качестве дополнительного ... Тест [-r file] не указывает, действительно ли какие-либо данные ожидают чтения (/ dev / null проходит этот тест (см. Комментарии)).
Требуется некоторое небольшое число для аргумента тайм-аута (read -t), или могут быть пропущены данные, которые требуют некоторого вычисления. Требуется читаемый тест ([-r файл]) или команда чтения будет бомбить, если файл не читается. Это на самом деле не будет читать какие-либо данные, потому что число байтов равно нулю (чтение -N 0).
источник
/proc/<pid>/fdinfo/<fd>
, в которой перечислены все режимы открытых файлов,flags:
см. здесь . Почему ваша вторая часть (даже после исправления явной ошибки):read -t .1 -N0 <&4
не скажет, есть ли данные для чтения на fd 4: просто попробуйте4</dev/null
.[ -r /proc/$$/fd/$FD ]
не сообщается, является ли дескриптор файла$FD
доступным для чтения, но если файл, из которого он был открыт, можно открыть снова , с другим дескриптором файла, для чтения:exec 7>/tmp/foo; [ -r /proc/$$/fd/7 ] && echo fd 7 can be read from && cat <&7
Вопрос довольно старый - но так или иначе - почему бы просто не использовать встроенные функции?
Выход:
Итак, чтобы ответить на вопрос - предлагаю:
источник
-t
не проверяет, является ли дескриптор файла допустимым, но подключен ли он к tty.echo yup |
Добавьте к вашему сценарию a , и он скажет, что0 is INVALID FD
, хотя на самом деле это очень правильный fd, труба.