Todos lo sabemos mkfifo
y las tuberías. El primero crea una tubería con nombre , por lo tanto, uno tiene que seleccionar un nombre, lo más probable es que mktemp
luego recuerde desvincular. El otro crea una tubería anónima, sin problemas con los nombres y la eliminación, pero los extremos de la tubería se atan a los comandos en la tubería, no es realmente conveniente obtener de alguna manera un control de los descriptores de archivos y usarlos en el resto del guión En un programa compilado, simplemente haría ret=pipe(filedes)
; en Bash hay, exec 5<>file
así que uno esperaría algo así "exec 5<> -"
o, ¿ "pipe <5 >6"
hay algo así en Bash?
38
Si bien ninguno de los proyectiles que conozco puede fabricar tuberías sin bifurcación, algunos tienen mejores que la tubería básica de proyectiles.
En bash, ksh y zsh, suponiendo que su sistema sea compatible
/dev/fd
(la mayoría lo hace hoy en día), puede vincular la entrada o la salida de un comando a un nombre de archivo: se<(command)
expande a un nombre de archivo que designa una tubería conectada a la salidacommand
y se>(command)
expande a un nombre de archivo que designa una tubería conectada a la entrada decommand
. Esta característica se llama sustitución de proceso . Su propósito principal es canalizar más de un comando dentro o fuera de otro, por ejemplo,Esto también es útil para combatir algunas de las deficiencias de los tubos básicos. Por ejemplo,
command2 < <(command1)
es equivalente acommand1 | command2
, excepto que su estado es el decommand2
. Otro caso de uso esexec > >(postprocessing)
, que es equivalente a, pero más legible que, poner todo el resto del script dentro{ ... } | postprocessing
.fuente
pipe:[123456]
). Emacs ve que el objetivo del enlace simbólico no es un nombre de archivo existente y eso lo confunde lo suficiente como para que no lea el archivo (puede haber una opción para que lo lea de todos modos, aunque a Emacs no le gusta abrir una tubería como archivo de todos modos).Bash 4 tiene coprocesos .
fuente
A partir de octubre de 2012, esta funcionalidad aún no parece existir en Bash, pero coproc se puede usar si todo lo que necesita para tuberías anónimas / sin nombre es hablar con un proceso secundario. El problema con coproc en este punto es que aparentemente solo se admite uno a la vez. No puedo entender por qué coproc tiene esta limitación. Deberían haber sido una mejora del código de fondo de tareas existente (el & op), pero esa es una pregunta para los autores de bash.
fuente
coproc THING { dothing; }
ahora sus FD están dentro${THING[*]}
y puede ejecutarcoproc OTHERTHING { dothing; }
y enviar y recibir cosas hacia y desde ambos.man bash
, debajo del título BUGS, dicen esto: puede haber solo un coproceso activo a la vez . Y recibe una advertencia si inicia un segundo coproc. Parece funcionar, pero no sé qué explota en el fondo.Si bien la respuesta de @ DavidAnderson cubre todas las bases y ofrece algunas buenas salvaguardas, lo más importante que revela es que tener una tubería anónima es tan fácil como
<(:)
permanecer en Linux.Entonces, la respuesta más corta y simple a su pregunta es:
En macOS no funcionará, entonces necesitará crear un directorio temporal para alojar el fifo nombrado hasta que lo haya redirigido. No sé sobre otros BSD.
fuente
exec
se aprueba un Fifo anónimo que se abre solo para lectura,exec
no debe permitir que este Fifo anónimo se abra para leer y escribir utilizando un descriptor de archivo personalizado. Debería esperar recibir un-bash: /dev/fd/5: Permission denied
mensaje, que es lo que emite macOS. Creo que el error es que Ubuntu no produce el mismo mensaje. Estaría dispuesto a cambiar de opinión si alguien pudiera presentar documentación diciendo queexec 5<> <(:)
se explica lo permitido.open(..., O_RDWR)
en un extremo de tubería unidireccional proporcionado por la sustitución y eso lo convierte en una tubería bidireccional en un FD. Probablemente tenga razón en que uno no debe confiar en esto. :-D Salida del uso de piperw de execline para crear la tubería, luego reutilizándola con bash<>
: libranet.de/display/0b6b25a8-195c-84af-6ac7-ee6696661765exec 5<>
, ingresefun() { ls -l $1; ls -lH $1; }; fun <(:)
.La siguiente función se probó usando
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
. El sistema operativo era Ubuntu 18. Esta función toma un único parámetro que es el descriptor de archivo deseado para el FIFO anónimo.La siguiente función se probó usando
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
. El sistema operativo era macOS High Sierra. Esta función comienza creando un FIFO con nombre en un directorio temporal conocido solo por el proceso que lo creó . A continuación, el descriptor de archivo se redirige a FIFO. Finalmente, el FIFO se desvincula del nombre de archivo eliminando el directorio temporal. Esto hace que el FIFO sea anónimo.Las funciones anteriores se pueden combinar en una sola función que funcionará en ambos sistemas operativos. A continuación se muestra un ejemplo de dicha función. Aquí, se intenta crear una FIFO verdaderamente anónima. Si no tiene éxito, se crea un FIFO con nombre y se convierte en un FIFO anónimo.
Aquí hay un ejemplo de cómo crear una FIFO anónima y luego escribir un texto en la misma FIFO.
A continuación se muestra un ejemplo de lectura de todo el contenido del FIFO anónimo.
Esto produce la siguiente salida.
El siguiente comando cierra el FIFO anónimo.
Referencias:
Crear una tubería anónima para su uso posterior Los
archivos en directorios que se pueden escribir públicamente son peligrosos.
Shell Script Security
fuente
Usando la excelente y brillante respuesta de htamas, la modifiqué un poco para usarla en un solo revestimiento, aquí está:
fuente