En informática, la sustitución de procesos es una forma de comunicación entre procesos que permite que la entrada o salida de un comando esté disponible como una ruta de archivo. El comando se sustituye en línea, donde normalmente aparecería un nombre de archivo, por el intérprete de comandos . Esto permite que los programas que normalmente solo aceptan rutas de archivo puedan leer o escribir directamente en otro programa.
Historia
La sustitución de procesos fue introducida por primera vez por KornShell de Bell Labs y documentada por primera vez en ksh861986 [ 1 ] inicialmente solo disponible en sistemas con soporte para archivos de dispositivos de caracteres. El shell rc proporciona la característica como "ramificación de tubería" en la versión 10 de Unix , lanzada en 1990 con una sintaxis diferente [ 2 ] . El Z Shell ha tenido la característica desde su versión inicial 1.0 lanzada en 1990 [ 3 ] y el shell Bash desde la versión 1.13.4, lanzada en 1993 [ 4 ] ambos usando la sintaxis de Korn Shell./dev/fd/n
Zsh (desde su primera versión en 1990) añadió una tercera forma de sustitución de procesos ( =(cmd)) que utiliza un archivo temporal en lugar de una tubería. El intérprete de comandos fish añadió su propia sustitución de procesos con otra sintaxis en 2005, utilizando tuberías, y luego una variante que utilizaba archivos temporales en 2007, que luego se convirtió en la predeterminada (inicialmente de forma inadvertida) ya que la variante de tuberías sufría de interbloqueos [ 5 ] .
Sintaxis
Ejemplos
Los siguientes ejemplos utilizan la sintaxis de KornShell.
El comando diff de Unix normalmente acepta los nombres de dos archivos para comparar, o un nombre de archivo y la entrada estándar. La sustitución de procesos permite comparar directamente la salida de dos programas:
$ diff < ( ordenar archivo1 ) < ( ordenar archivo2 )La <(command)expresión le indica al intérprete de comandos que ejecute el comando y que su salida aparezca como un archivo. El comando puede ser cualquier código de shell, por complejo que sea.
Sin sustitución de procesos, las alternativas son:
- Guarda el resultado del/de los comando(s) en un archivo temporal y, a continuación, lee el/los archivo(s) temporal(es).
$ ordenar archivo2 > archivo2.ordenado $ ordenar archivo1 | diff - archivo2.ordenado $ eliminar archivo2.ordenado
- Cree una tubería con nombre (también conocida como FIFO ), inicie un comando que escriba en la tubería con nombre en segundo plano y, a continuación, ejecute el otro comando utilizando la tubería con nombre como entrada.
$ mkfifo sort2.fifo $ sort file2 > sort2.fifo & $ sort file1 | diff - sort2.fifo $ rm /tmp/sort2.fifo
- En sistemas compatibles, realice el método KornShell manualmente:
/dev/fd/n$ ordenar archivo1 | { ordenar archivo2 3 < & - | diff /dev/fd/3 - ; } 3 < & 0
Todo ello resulta más engorroso.
La sustitución de procesos también se puede usar para capturar la salida que normalmente iría a un archivo y redirigirla a la entrada de un proceso. La sintaxis de KornShell para escribir en un proceso es >(command). Aquí hay un ejemplo usando los comandos tee, wcy gzipque cuenta las líneas en un archivo con wc -ly lo comprime con gzipen una sola pasada:
$ tee > ( wc -l > & 2 ) < bigfile | gzip > bigfile.gz Ventajas
Las principales ventajas de la sustitución de procesos frente a sus alternativas son:
- Sencillez : Los comandos se pueden introducir directamente; no es necesario guardar archivos temporales ni crear tuberías con nombre previamente.
- Rendimiento : Leer directamente desde otro proceso suele ser más rápido que tener que escribir un archivo temporal en el disco y luego volver a leerlo. Esto también ahorra espacio en disco.
- Paralelismo : El proceso sustituido puede ejecutarse simultáneamente con el comando que lee su salida o escribe su entrada, aprovechando el multiprocesamiento para reducir el tiempo total de cálculo.
Mecanismo
Internamente, las variantes de sustitución de procesos donde los comandos se ejecutan simultáneamente tienen dos posibles implementaciones. En sistemas que lo admiten /dev/fd(la mayoría de los sistemas tipo Unix), la mayoría de las implementaciones funcionan llamando a la pipe()llamada al sistema , que devuelve un descriptor de archivo$fd para una nueva tubería anónima, luego creando la cadena /dev/fd/$fdy sustituyéndola en la línea de comandos. En sistemas sin /dev/fdsoporte, llaman mkfifo()con un nuevo nombre de archivo temporal para crear una tubería con nombre y sustituyen este nombre de archivo en la línea de comandos. Para ilustrar los pasos involucrados, considere la siguiente sustitución de comando simple en un sistema con /dev/fdsoporte:
$ diff archivo1 < ( ordenar archivo2 )Los pasos que realiza el intérprete de comandos son:
- Crea una nueva tubería anónima. Esta tubería será accesible con algo como
/dev/fd/63; puedes verla con un comando comoecho <(true). - Ejecuta el comando sustituido en segundo plano (
sort file2en este caso), redirigiendo su salida a la tubería anónima. - Simultáneamente, ejecute el comando principal, reemplazando el comando sustituido con una ruta a la tubería anónima. En este caso, el comando completo podría expandirse a algo como
diff file1 /dev/fd/63. - Cuando finalice la ejecución, cierre la tubería anónima.
Para las tuberías con nombre, la ejecución difiere únicamente en la creación y eliminación de la tubería; se crean con mkfifo()(al que se le asigna un nuevo nombre de archivo temporal) y se eliminan con unlink(). Todos los demás aspectos permanecen iguales.
Las variantes que utilizan archivos temporales como Zsh cmd1 =(cmd2)o Fish cmd1 (cmd2|psub -f)primero ejecutan cmd2su salida redirigida a un archivo temporal, luego ejecutan cmd1sustituyendo =(cmd2)la ruta con la de ese archivo temporal y eliminan automáticamente ese archivo después de cmd1que finaliza.
Limitaciones
Excepto en las variantes que utilizan archivos temporales, los "archivos" creados no son ni buscables ni mapeables mediante mmap , lo que significa que el proceso que lee o escribe en el archivo no puede realizar accesos aleatorios ; debe leer o escribir una sola vez de principio a fin. Los programas que comprueban explícitamente el tipo de un archivo antes de abrirlo pueden negarse a funcionar con la sustitución de procesos, porque el "archivo" resultante de la sustitución de procesos no es un archivo regular . Además, en KornShell, versiones de Bash anteriores a la 4.4 (2016) y versiones de Zsh anteriores a la 5.6 (2018), no es posible obtener el estado de salida de un comando de sustitución de procesos desde el intérprete de comandos que creó la sustitución de procesos. [ 6 ]
Véase también
Referencias
- ↑ Korn, David. "Notas de lanzamiento de Ksh86" . GitHub . Bell Labs USG . Consultado el 11 de marzo de 2026 .
- ↑ Duff, Tom (1990). Rc — Un shell para Plan 9 y sistemas UNIX . CiteSeerX 10.1.1.41.3287 .
- ↑ Falstad, Paul. "Publicación de zsh 1.0 o grupo de noticias alt.sources" . Archivos de Usenet de Google Groups . Consultado el 11 de marzo de 2026 .
- ↑ Ramey, Chet. "Anuncio de Usenet de Bash 1.13.4" . Archivo de Usenet de Google Groups . Consultado el 11 de marzo de 2026 .
- ↑ "Problema 1040 de fish shell: encontrar una manera de hacer que psub --fifo sea seguro contra interbloqueos" . Problemas de fish-shell en GitHub . Consultado el 11 de marzo de 2026 .
- ↑ "ProcessSubstitution" . Wiki de Greg . 22 de septiembre de 2016. Consultado el 6 de febrero de 2021 .
Lecturas adicionales
- "Manual de referencia de Bash" . El Proyecto GNU . Fundación del Software Libre. 23 de diciembre de 2009. Consultado el 1 de octubre de 2011 .
- Cooper, Mendel (30 de agosto de 2011). "Guía avanzada de scripting de Bash" . El proyecto de documentación de Linux . Recuperado el 1 de octubre de 2011 .
- Frazier, Mitch (22 de mayo de 2008). "Sustitución de procesos Bash" . Linux Journal . Recuperado el 1 de octubre de 2011 .
- Temas de lenguajes de programación
- Herramientas de programación Unix