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_WRONLY
y O_RDWR
para probar si el FD es editable, O_RDONLY
y O_RDWR
para 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:
command
Es por eso que solo puedes hacer:
O...
Que escribirá una cadena seguida de una línea
\n
electró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
-l
para 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/$$/fd
que 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 -l
muestra 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./proc
no existe en absoluto en OpenBSD. En FreeBSD y NetBSD tiene que sermount
editado 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/null
para evitar el tenedor. O{ command exec >&3; } 2> /dev/null
si desea redirigir stdout a él.{ true >&3; } 2> /dev/null
tampoco 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.exec
Al ser un generador especial, saldrá del shell si falla (para bash, solo cuando está en modo de cumplimiento POSIX).command exec
evita eso.true
No es una construcción especial. Tenga en cuenta queexec
ycommand exec
afecta 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:
Y esto es lo que produce con un
zsh
:fuente
exec >&3
matará al proyectil cuando 3 no esté abierto.zsh
ybash
. ¿Podría proporcionar el caparazón en el queexec
causó la fallaexit
?bash
hacerset -o posix
e intentar de nuevo. Enzsh
... creo que es una cuestión de configurar la var varPOSIX_BUILTINS
a un valor no nulo, pero lo olvido de improviso. En cualquier caso,zsh
no 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 posix
un 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 <&4
no 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$FD
es 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 <&7
La pregunta es bastante antigua, pero de todos modos, ¿por qué simplemente no usar builtins?
Salida:
Entonces, para responder la pregunta, sugeriría:
fuente
-t
no 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.