Идеальное решение является тем, представленным BriGuy
pgrep fnord
Но если Вы не хотите делать это, можно просто исключить все строки, который соответствует grep с:
ps aux | grep -v grep | grep "fnord"
В ksh
(варианты AT&T и pdksh) или zsh
вы можете:
if print -nu3; then
echo fd 3 is writeable
fi
Они не будут ничего писать на этот fd, но все равно проверят, доступен ли для записи fd (используя fcntl (3, F_GETFL)
), и сообщат об ошибке в противном случае:
$ ksh -c 'print -nu3' 3< /dev/null
ksh: print: -u: 3: fd not open for writing
(который вы можете перенаправить / dev / null
).
С bash
, я думаю, ваш единственный вариант - проверить, успешно ли выполняется dup ()
, как в вашем подходе, хотя это не гарантирует, что fd доступен для записи (или вызовите внешнюю утилиту ( zsh
/ perl
...) для выполнения fcntl ()
).
Обратите внимание, что в bash
(как и в большинстве оболочек), если вы используете (...)
вместо {...;}
, это приведет к развить дополнительный процесс. Вместо этого вы можете использовать:
if { true >&3; } 2<> /dev/null
, чтобы избежать вилки (за исключением оболочки Bourne, где перенаправление составных команд всегда вызывает подоболочку). Не используйте :
вместо true
, поскольку это специальная встроенная функция , поэтому оболочка завершится, когда bash находится в режиме соответствия POSIX.
Вы можете, однако, сократить его до:
if { >&3; } 2<> /dev/null
Открытые файловые дескрипторы можно найти в / proc /
. Чтобы перечислить, например, дескрипторы открытых файлов текущей оболочки вы можете выдать LS -L / proc / $$ / fd
, который должен дать вам что-то вроде:
total 0
lrwx------ 1 testuser testuser 64 jun 1 09:11 0 -> /dev/pts/3
lrwx------ 1 testuser testuser 64 jun 1 09:11 1 -> /dev/pts/3
lrwx------ 1 testuser testuser 64 jun 1 09:11 2 -> /dev/pts/3
lrwx------ 1 testuser testuser 64 jun 1 09:39 255 -> /dev/pts/3
, когда вы открываете файл, используя:
touch /tmp/myfile
exec 7</tmp/myfile
Это должно быть перечислено новым LS -L / proc / $$ / fd
:
lr-x------ 1 testuser testuser 64 jun 1 09:11 7 -> /tmp/myfile
Если вы закроете дескриптор файла снова, используя Exec 7> & -
также не указан в / proc / $$ / fd
.
Если вы заинтересованы в низком раздумном решении, чтобы использовать его Reputdly, я бы предложил эту функцию:
checkfd() { exec 2>/dev/null if exec >&3 ; then exec 1>/dev/tty echo "fd3 OK" else echo "fd3 KO" fi exec 2>/dev/tty }
и вот что он производит с ZSH
:
$ checkfd fd3 KO $ checkfd 3>/dev/null fd3 OK $
Ваш трюк выглядит мило; Но для идиоматического способа интересно, почему вы не использовали:
if ( exec 1>&3 ) 2>&-
В описании команды POSIX
Application Usage вы найдете следующее:
Временное подавление особых характеристик специальных встроенных модулей дает некоторые преимущества. Например:
команда exec> unwritable-file
не вызывает прерывания неинтерактивного сценария, так что состояние вывода может быть проверено сценарием.
Вот почему вы можете просто сделать:
if command >&3
then echo 3 is open >&3
else ! echo 3 is not open
fi 2<>/dev/null
Или ...
{ command >&3
printf %s\\n%.0d string "0$(($??8:0))" >&"$(($??1:3))"
} 2<>/dev/null
Что запишет строку , за которой следует \ n
ewline либо в стандартный вывод, либо в 3 и все равно передать ненулевой статус выхода, когда 3 не открыто, потому что математика, выполненная на $?
, завершается неудачей при преобразовании восьмеричного 08 в % decimal , но обрезает до нуля восьмеричное 00 .
Или ...
command exec >&3 || handle_it
Но если вы используете ksh93
, вы можете просто сделать:
fds
Для получения списка дескрипторов открытых файлов. Добавьте -l
, чтобы увидеть, куда они направляются.
Это кажется очень простым (см. комментарии):
[ -r /proc/$$/fd/$FD ] && echo "File descriptor $FD is readable"
[ -w /proc/$$/fd/$FD ] && echo "File descriptor $FD is writable"
В качестве дополнения... Тест [-r file ] не показывает, действительно ли какие-либо данные ожидают чтения (/dev/null проходит этот тест (см. комментарии )).
[ -r /proc/$$/fd/4 ] \
&& [ read -t 0.0001 -N 0 <&4 ] \
&& echo "Data is waiting to be read from file descriptor 4"
Требуется некоторое небольшое число для аргумента тайм-аута (read -t ), иначе могут быть пропущены данные, требующие некоторых вычислений. Требуется проверка на чтение ([-r файл] ), иначе команда чтения сработает, если файл не читается. На самом деле это не приведет к чтению каких-либо данных, потому что счетчик байтов равен нулю (read -N 0 ).
Вопрос довольно старый -но все же -почему бы просто не использовать встроенные функции?
for i in {0..5} ; do if [ -t $i ]; then echo "$i is a valid FD"; else echo "$i is INVALID FD"; fi; done
Выход:
0 is a valid FD
1 is a valid FD
2 is a valid FD
3 is INVALID FD
4 is INVALID FD
5 is INVALID FD
Итак, ответ на вопрос -предполагает:
if [ -t 3 ]; then
# File descriptor 3 is open
else
# File descriptor 3 is not open
fi
Для Linux по крайней мере подойдет [[ -e /dev/fd/${FD} ]]
, где FD — это переменная bash -, в которой хранится FD, который вы хотите протестировать. Команда выполняется успешно, когда FD открыт, в противном случае завершается ошибкой.
Демо:
exec 3<>/tmp/some-file
[[ -e /dev/fd/3 ]] && echo 'FD is open' || echo 'FD is closed'
exec 3<&- ; exec 3>&-
[[ -e /dev/fd/3 ]] && echo 'FD is open' || echo 'FD is closed'