Проверка допустимости файлового дескриптора

Идеальное решение является тем, представленным BriGuy

pgrep fnord 

Но если Вы не хотите делать это, можно просто исключить все строки, который соответствует grep с:

ps aux | grep -v grep | grep "fnord"
12
01.06.2015, 21:48
8 ответов

В 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
12
27.01.2020, 19:55

Открытые файловые дескрипторы можно найти в / proc / / fd . Чтобы перечислить, например, дескрипторы открытых файлов текущей оболочки вы можете выдать 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 .

3
27.01.2020, 19:55

Если вы заинтересованы в низком раздумном решении, чтобы использовать его 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
$
-1
27.01.2020, 19:55

Ваш трюк выглядит мило; Но для идиоматического способа интересно, почему вы не использовали:

if ( exec 1>&3 ) 2>&-
3
27.01.2020, 19:55

В описании команды 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 , чтобы увидеть, куда они направляются.

7
27.01.2020, 19:55

Это кажется очень простым (см. комментарии):

[ -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 ).

0
27.01.2020, 19:55

Вопрос довольно старый -но все же -почему бы просто не использовать встроенные функции?

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
-1
25.02.2020, 03:48

Для 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'
0
29.05.2021, 07:20

Теги

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