Me gustaría hacer que un script bash genere información adicional para los descriptores de archivo (FD) mayores o iguales a 3, cuando están abiertos. Para probar si un FD está abierto, ideé el siguiente truco:
if (printf '' 1>&3) 2>&-; then
# File descriptor 3 is open
else
# File descriptor 3 is not open
fi
Esto es suficiente para mis necesidades, pero tengo curiosidad por saber si hay una forma más idiomática de probar si un FD es válido. Estoy especialmente interesado en saber si existe un mapeo de fcntl(1)syscall a un comando de shell, lo que permitiría la recuperación de banderas FD ( O_WRONLYy O_RDWRpara probar si el FD es editable, O_RDONLYy O_RDWRpara probar si el FD es legible).
fuente

<>? El shell no va a leer desde su stderr, ¿por qué querrías abrirlo en lectura + escritura? ¿Qué quieres decir con lo que pasó con intrínseco? ?En la descripción del uso de la aplicación POSIX encontrará lo siguiente:
commandEs por eso que solo puedes hacer:
O...
Que escribirá una cadena seguida de una línea
\nelectrónica ya sea stdout o 3 y aún así pasará un estado de salida distinto de cero cuando 3 no esté abierto porque la matemática realizada al$?terminar no logra convertir el octal 08 a % decimal pero se trunca a nada el octal 00 .O...
Pero si está usando
ksh93, puede hacer lo siguiente:Para obtener una lista de descriptores de archivos abiertos. Agregue
-lpara ver a dónde van.fuente
Los descriptores de archivos abiertos se pueden encontrar en
/proc/<pid>/fd. Para enumerar, por ejemplo, los descriptores de archivos abiertos del shell actual que puede emitir,ls -l /proc/$$/fdque deberían proporcionarle algo como:Cuando abres un archivo usando:
Debería estar listado por un nuevo
ls -l /proc/$$/fd:Si vuelve a cerrar el descriptor de archivo con el uso
exec 7>&-, tampoco aparecerá en la lista/proc/$$/fd.fuente
pfiles <pid>para ver qué descriptor de archivo está conectado a qué archivo mientrasls -lmuestra la conexión en Linux.[ -e /proc/$$/fd/3 ], pero prefiero no confiar en procfs, ya que está en desuso en FreeBSD y posiblemente también en otras unidades *.pfiles <pid>olsof -p <pid>ver qué descriptores de archivo están abiertos./procno existe en absoluto en OpenBSD. En FreeBSD y NetBSD tiene que sermounteditado explícitamente y/proc/<PID>no tiene un subdirectoriofd.Tu truco se ve lindo; pero por una forma idiomática me pregunto por qué no usaste:
fuente
{ true >&3; } 2> /dev/nullpara evitar el tenedor. O{ command exec >&3; } 2> /dev/nullsi desea redirigir stdout a él.{ true >&3; } 2> /dev/nulltampoco afectará el entorno actual y no se bifurcará (excepto en el shell Bourne). Quiero decir que(exec 1>&3) 2>&-volverá verdadero para un fd abierto en modo de solo lectura.execAl ser un generador especial, saldrá del shell si falla (para bash, solo cuando está en modo de cumplimiento POSIX).command execevita eso.trueNo es una construcción especial. Tenga en cuenta queexecycommand execafecta el entorno actual (es por eso que dije si desea redirigir stdout a él ).Si está interesado en una solución de baja bifurcación para usarla repetidamente, le sugiero esta función:
checkfd () { exec 2> / dev / null si exec> & 3; entonces exec 1> / dev / tty echo "fd3 OK" más echo "fd3 KO" fi exec 2> / dev / tty }Y esto es lo que produce con un
zsh:fuente
exec >&3matará al proyectil cuando 3 no esté abierto.zshybash. ¿Podría proporcionar el caparazón en el queexeccausó la fallaexit?bashhacerset -o posixe intentar de nuevo. Enzsh... creo que es una cuestión de configurar la var varPOSIX_BUILTINSa un valor no nulo, pero lo olvido de improviso. En cualquier caso,zshno es un shell que intenta cumplir con POSIX, por lo que definitivamente no es estándar. Ambas cáscaras evitan la compatibilidad para lo que algunos creen que es conveniencia.set -o posixun intento es exitoso.Esto parece súper fácil (ver comentarios):
Como extra ... La prueba [-r file] no indica si algún dato está esperando ser leído (/ dev / null pasa esta prueba (ver comentarios)).
Se requiere algún número pequeño para el argumento de tiempo de espera (read -t) o se pueden perder los datos que necesitan algún cálculo. Se requiere la prueba legible ([-r archivo]) o el comando de lectura bombardeará si el archivo no es legible. En realidad, esto no leerá ningún dato porque el recuento de bytes es cero (leer -N 0).
fuente
/proc/<pid>/fdinfo/<fd>, que enumera todos los modos de archivos abiertos enflags:- vea aquí . Por qué su segunda parte (incluso después de corregir el error evidente):read -t .1 -N0 <&4no dirá si hay datos para leer en fd 4: solo intente4</dev/null.[ -r /proc/$$/fd/$FD ]no le dice si el descriptor de archivo$FDes legible, pero si el archivo desde el que estaba abierto podría abrirse nuevamente , con otro descriptor de archivo, para leer:exec 7>/tmp/foo; [ -r /proc/$$/fd/7 ] && echo fd 7 can be read from && cat <&7La pregunta es bastante antigua, pero de todos modos, ¿por qué simplemente no usar builtins?
Salida:
Entonces, para responder la pregunta, sugeriría:
fuente
-tno prueba si un descriptor de archivo es válido, pero si está conectado a un tty. Anteponga unecho yup |a su secuencia de comandos, y dirá que0 is INVALID FD, aunque en realidad es muy válido fd, una tubería.