Reemplazar el proceso actual por su coproceso / hijo


10

Tengo un programa Pque espera recibir "Hola" y mostrar "¿Por qué?" antes de proporcionar una función. Esta función es utilizada por otros programas que no son conscientes de que es una cortesía común iniciar una conversación con "Hola". Por lo tanto, quiero escribir un contenedor para Pque funcione así (sintaxis zsh):

coproc P
print -p Hello  # Send Hello to P
read -pr line   # Read what P has to say
[[ "$line" = "Why?" ]] && Replace current process with the coprocess.
echo Could not get P's attention.

Usar cato dden la Replace...parte (algo así como cat <&p &; exec cat >&p) da como resultado un almacenamiento en búfer innecesario. ¿Cuáles son mis opciones?


¿Quieres una zshsolución o es una bashsolución aceptable?
roaima

1
Me decepcionaría una bashsolución que no es aplicable zsh, pero que ciertamente la aceptaría ☺
Michaël

¿Se sabe qué otros programas ejecutarían este script? ¿Es una lista finita, o podría ser cualquier número? Claramente, el otro programa necesita saber sobre este para poder llamarlo.
Lizardx

Mi uso típico era con sshy su opción ProxyCommand.
Michaël

1
catgeneralmente no amortigua. Si lo hace en su sistema, intente cat -u.
Stéphane Chazelas

Respuestas:


1

El problema que ha declarado no se trata realmente de reemplazar un proceso , sino de reemplazar las secuencias de un proceso existente . El objetivo es interactuar un poco con el proceso y luego entregar su entrada / salida a otro par de flujos conectados.

No hay forma de hacer esto directamente (al menos, en el shell; dentro del proceso, una dup2llamada podría funcionar). Tendrá que empalmar las corrientes. Es decir:

( echo Hello ; cat ) | P | ( read ; cat )

Usar coproccomo en su ejemplo también está bien. Tenga en cuenta que el comando guarda los descriptores de archivo en una matriz, y luego puede usarlos para redireccionamientos.

Esto no debería causar almacenamiento en búfer adicional (al menos con GNU cat), a menos que P inspeccione los flujos de entrada / salida a los que está conectado y tome la decisión de usar el búfer en función de eso. Por ejemplo, la biblioteca estándar de C habilitará el almacenamiento en búfer en stdout/ stderrsi están conectados a un archivo, pero solo realizará el almacenamiento en búfer de línea si están conectados a un terminal.


-1

Capaz de probar con el siguiente código usando Perl para evitar el almacenamiento en búfer, pruebe si esto funciona para usted

Versión de muestra de P

$ cat /tmp/P
#!/bin/bash
read input
if [[ $input = "Hello" ]]
then
    echo "Why?"
else
    exit 1
fi
echo "Got Hello from client, working ..."
sleep 10
echo "Need to read some input"
read x
echo "Got: $x"

El programa envoltorio

$ cat /tmp/wrapper 
#!/usr/bin/zsh
coproc /tmp/P
print -p Hello  # Send Hello to P
read -pr line   # Read what P has to say
if [[ "$line" = "Why?" ]]; then
    perl -e '$|=1;print $_ while(<>);' <& p &
    perl -e '$|=1;print $_ while(<>);' >& p
else
    echo "Could not get P's attention."
fi

Prueba de funcionamiento

$ /tmp/wrapper 
Got Hello from client, working ...
Need to read some input
hi there P!   <== Typed in at teminal
Got: hi there P!

Esto es lo mismo que usar dd ibs=1, por ejemplo. No estoy bien con esto. En cierto modo, el coproc tiene su propio almacenamiento en búfer, y es este el que quiero usar.
Michaël
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.