Sostituisci il processo corrente con il suo coprocesso / figlio


10

Ho un programma Pche si aspetta di ricevere "Hello" e produrre "Why?" prima di fornire una funzione. Questa funzione è utilizzata da altri programmi che non sono consapevoli del fatto che è comunemente cortesia iniziare una conversazione con "Ciao". Voglio quindi scrivere un wrapper perché funzioni in Pquesto modo (sintassi 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.

L'uso cato ddnella Replace...parte (qualcosa del genere cat <&p &; exec cat >&p) comporta un buffering non necessario. Quali sono le mie opzioni?


Vuoi una zshsoluzione o è una bashsoluzione accettabile?
roaima,

1
Sarei deluso da una bashsoluzione che non è applicabile in zsh, ma certamente lo accetterei ☺
Michaël

È noto quali altri programmi eseguiranno questo script? È un elenco finito o potrebbe essere un numero qualsiasi? Chiaramente l'altro programma deve conoscere questo per poterlo chiamare.
Lizardx,

Il mio uso tipico era con sshe la sua opzione ProxyCommand.
Michaël,

1
catgeneralmente non buffer. Se funziona sul tuo sistema, prova cat -u.
Stéphane Chazelas,

Risposte:


1

Il problema che hai affermato non riguarda in realtà la sostituzione di un processo , ma la sostituzione dei flussi di un processo esistente . L'obiettivo è interagire un po 'con il processo, quindi consegnare il suo input / output a un'altra coppia di flussi collegati.

Non c'è modo di farlo direttamente (almeno, nella shell; all'interno del processo, una dup2chiamata potrebbe concepibilmente funzionare). Sarà necessario unire i flussi. Vale a dire:

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

Anche usare coproccome nell'esempio è OK. Si noti che il comando salva i descrittori di file in un array e in seguito è possibile utilizzarli per i reindirizzamenti.

Ciò non dovrebbe causare buffer aggiuntivi (almeno con GNU cat), a meno che P non controlli i flussi di input / output a cui è collegato e prenda una decisione di buffer in base a quello. Ad esempio, la libreria standard C abiliterà il buffering su stdout/ stderrse sono collegati a un file, ma eseguirà il buffering di linea solo se sono collegati a un terminale.


-1

In grado di testare con il codice seguente usando perl per evitare il buffering, prova se questo funziona per te

Versione di esempio di 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"

Il programma wrapper

$ 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

Prova

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

È lo stesso che usare dd ibs=1, per esempio. Non sto bene con questo. In un certo senso, il coproc ha il suo buffering, ed è questo che voglio usare.
Michaël,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.