La mayoría de los comandos tienen un solo canal de entrada (entrada estándar, descriptor de archivo 0) y un solo canal de salida (salida estándar, descriptor de archivo 1) o bien operan en varios archivos que se abren solos (por lo que les pasa un nombre de archivo). (Además del error estándar (fd 2), que generalmente se filtra hasta el usuario). Sin embargo, a veces es conveniente tener un comando que actúe como filtro de varias fuentes o de varios objetivos. Por ejemplo, aquí hay un script simple que separa las líneas impares en un archivo de las líneas pares
while IFS= read -r line; do
printf '%s\n' "$line"
if IFS= read -r line; then printf '%s\n' "$line" >&3; fi
done >odd.txt 3>even.txt
Ahora suponga que desea aplicar un filtro diferente a las líneas de números impares y a las líneas de números pares (pero no volver a ponerlas juntas, eso sería un problema diferente, no factible desde el shell en general). En el shell, solo puede canalizar la salida estándar de un comando a otro comando; para canalizar otro descriptor de archivo, primero debe redirigirlo a fd 1.
{ while … done | odd-filter >filtered-odd.txt; } 3>&1 | even-filter >filtered-even.txt
Otro caso de uso más simple es filtrar la salida de error de un comando .
exec M>&N
redirige un descriptor de archivo a otro para el resto del script (o hasta que otro comando cambie los descriptores de archivo nuevamente). Existe cierta superposición en la funcionalidad entre exec M>&N
y somecommand M>&N
. La exec
forma es más poderosa porque no tiene que estar anidada:
exec 8<&0 9>&1
exec >output12
command1
exec <input23
command2
exec >&9
command3
exec <&8
Otros ejemplos que pueden ser de interés:
Y para aún más ejemplos:
PD: ¡Esta es una pregunta sorprendente que proviene del autor de la publicación más votada en el sitio que utiliza la redirección a través de fd 3 !
Gilles 'SO- deja de ser malvado'
fuente
while IFS= read -r line;
? A mi modo de ver, IFS no tiene ningún efecto aquí ya que asigna valor a solo una variable ( línea ). Ver esta preguntaIFS
hace la diferencia incluso si estás leyendo una variable individual (es para retener el espacio en blanco principal).sed -ne 'w odd.txt' -e 'n;w even.txt'
?Aquí hay un ejemplo del uso de FD adicionales como control de chattiness de script bash:
fuente
En el contexto de canalizaciones con nombre (fifos), el uso de un descriptor de archivo adicional puede habilitar el comportamiento de canalización sin bloqueo.
Ver: ¿La tubería con nombre se cierra prematuramente en el script?
fuente
Un descriptor de archivo adicional es bueno para cuando desea capturar el stdout en una variable pero aún desea escribir en la pantalla, por ejemplo, en una interfaz de usuario de script bash
fuente
Aquí hay otro escenario cuando parece apropiado usar un descriptor de archivo adicional (en Bash):
Shell script de seguridad de contraseña de parámetros de línea de comandos
fuente
Ejemplo: uso de flock para forzar que los scripts se ejecuten en serie con bloqueos de archivos
Un ejemplo es hacer uso del bloqueo de archivos para forzar que los scripts se ejecuten en serie en todo el sistema. Esto es útil si no desea que dos scripts del mismo tipo operen en los mismos archivos. De lo contrario, los dos scripts interferirían entre sí y posiblemente dañarían los datos.
Use el lote funcionalmente definiendo bloquear y desbloquear
También puede incluir esta lógica de bloqueo / desbloqueo en funciones reutilizables. El siguiente
trap
shell incorporado liberará automáticamente el bloqueo del archivo cuando salga el script (ya sea error o éxito).trap
ayuda a limpiar tus bloqueos de archivos. La ruta/tmp/file.lock
debe ser una ruta codificada para que varios scripts puedan intentar bloquearla.La
unlock
lógica anterior es eliminar el archivo antes de liberar el bloqueo. De esta manera, limpia el archivo de bloqueo. Debido a que el archivo fue eliminado, otra instancia de este programa puede obtener el bloqueo del archivo.Uso de funciones de bloqueo y desbloqueo en scripts
Puede usarlo en sus scripts como en el siguiente ejemplo.
Si desea que su código espere hasta que pueda bloquearse, puede ajustar el script como:
fuente
Como ejemplo concreto, acabo de escribir un script que necesita la información de tiempo de un subcomando. El uso de un descriptor de archivo adicional me permitió capturar el
time
stderr del comando sin interrumpir el stdout o stderr del subcomando.Lo que esto hace es apuntar
ls
stderr a fd 3, apuntar fd 3 a stderr del script y apuntartime
stderr a un archivo. Cuando se ejecuta el script, su stdout y stderr son los mismos que los del subcomando, que se pueden redirigir como de costumbre. Solotime
el resultado se redirige al archivo.fuente