Zastąp bieżący proces jego koprocessem / dzieckiem

10

Mam program, Pktóry oczekuje na otrzymanie „Cześć” i wyjście „Dlaczego?” przed udostępnieniem funkcji. Ta funkcja jest używana przez inne programy, które nie zdają sobie sprawy z tego, że rozpoczęcie rozmowy z „Cześć” jest powszechne. Dlatego chcę napisać opakowanie, Pktóre działa w ten sposób (składnia 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.

Użycie catlub ddw Replace...części (coś podobnego cat <&p &; exec cat >&p) powoduje niepotrzebne buforowanie. Jakie są moje opcje?

Michał
źródło
Czy chcesz zshrozwiązanie, czy rozwiązanie jest do bashprzyjęcia?
roaima,
1
Byłbym rozczarowany bashrozwiązaniem, które nie ma zastosowania zsh, ale na pewno bym je zaakceptował ☺
Michaël,
Czy wiadomo, jakie inne programy uruchomiłyby ten skrypt? Czy jest to lista skończona, czy może to być dowolna liczba? Oczywiście drugi program musi wiedzieć o tym, aby go wywołać.
Lizardx,
Moim typowym zastosowaniem było sshi jego opcja ProxyCommand.
Michaël,
1
catgeneralnie nie buforuje. Jeśli działa w twoim systemie, spróbuj cat -u.
Stéphane Chazelas,

Odpowiedzi:

1

Podany problem nie dotyczy zastąpienia procesu , ale zastąpienia istniejących strumieni procesu . Celem jest trochę interakcji z procesem, a następnie przekazanie jego wejścia / wyjścia innej parze połączonych strumieni.

Nie ma sposobu, aby to zrobić bezpośrednio (przynajmniej w powłoce; wewnątrz procesu możliwe jest, że dup2wywołanie może działać). Będziesz musiał podzielić strumienie. To znaczy:

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

Używanie coprocjak w twoim przykładzie jest również OK. Zauważ, że polecenie zapisuje deskryptory plików w tablicy i możesz później użyć ich do przekierowań.

Nie powinno to powodować dodatkowego buforowania (przynajmniej w przypadku GNU cat), chyba że P sprawdzi strumienie wejściowe / wyjściowe, do których jest podłączony, i na tej podstawie podejmie decyzję o buforowaniu. Na przykład standardowa biblioteka C włączy buforowanie na stdout/ stderrjeśli są podłączone do pliku, ale buforowanie linii będzie wykonywane tylko wtedy, gdy jest podłączone do terminala.

Vladimir Panteleev
źródło
-1

W stanie przetestować poniższy kod za pomocą perla, aby uniknąć buforowania, spróbuj, czy to działa dla Ciebie

Przykładowa wersja 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"

Program owijania

$ 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

Testowe uruchomienie

$ /tmp/wrapper 
Got Hello from client, working ...
Need to read some input
hi there P!   <== Typed in at teminal
Got: hi there P!
VenkatC
źródło
To tak samo, jak dd ibs=1na przykład używanie . Nie czuję się z tym dobrze. W pewnym sensie coproc ma swoje własne buforowanie i właśnie tego chcę użyć.
Michaël,