Substituir o processo atual pelo seu coprocesso / filho

10

Eu tenho um programa Pque espera receber "Olá" e emitir "Por quê?" antes de fornecer um recurso. Esse recurso é usado por outros programas que não sabem que é uma cortesia comum iniciar uma conversa com "Olá". Assim, eu quero escrever um wrapper para Pque funcione assim (sintaxe 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 catou ddna Replace...parte (algo como cat <&p &; exec cat >&p) resulta em buffer desnecessário. Quais são as minhas opções?

Michael
fonte
Você quer uma zshsolução ou é uma bashsolução aceitável?
roaima
1
Eu ficaria desapontado por uma bashsolução que não é aplicável no zsh, mas certamente aceito-☺
Michaël
Sabe-se que outros programas estariam executando esse script? É uma lista finita ou poderia ser qualquer número? Claramente, o outro programa precisa saber sobre este para chamá-lo.
Lizardx
Meu uso típico era com sshe sua opção ProxyCommand.
Michaël
1
catgeralmente não faz buffer. Se isso ocorrer no seu sistema, tente cat -u.
Stéphane Chazelas

Respostas:

1

O problema que você declarou não é realmente sobre substituir um processo , mas substituir os fluxos de um processo existente . O objetivo é interagir um pouco com o processo e então entregar sua entrada / saída para outro par de fluxos conectados.

Não há como fazer isso diretamente (pelo menos no shell; dentro do processo, é possível que uma dup2chamada funcione). Você precisará unir os fluxos. Ou seja:

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

Usar coproccomo no seu exemplo também é bom. Observe que o comando salva os descritores de arquivo em uma matriz e você pode usá-los posteriormente para redirecionamentos.

Isso não deve causar buffer adicional (pelo menos com GNU cat), a menos que P inspecione os fluxos de entrada / saída aos quais está conectado e tome uma decisão de buffer com base nisso. Por exemplo, a biblioteca padrão C ativará o buffer em stdout/ stderrse eles estiverem conectados a um arquivo, mas somente realizará o buffer de linha se estiver conectado a um terminal.

Vladimir Panteleev
fonte
-1

Capaz de testar com o código abaixo usando perl para evitar buffer, tente se isso funcionar para você

Versão de exemplo 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"

O programa 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

Execução de teste

$ /tmp/wrapper 
Got Hello from client, working ...
Need to read some input
hi there P!   <== Typed in at teminal
Got: hi there P!
VenkatC
fonte
É o mesmo que usar dd ibs=1, por exemplo. Eu não estou bem com isso. De certa forma, o coproc possui seu próprio buffer e é esse que eu quero usar.
Michaël