Ersetzen Sie den aktuellen Prozess durch seinen Coprozess / Kind

10

Ich habe ein Programm P, das erwartet, "Hallo" zu empfangen und "Warum?" bevor Sie eine Funktion bereitstellen. Diese Funktion wird von anderen Programmen verwendet, die nicht wissen, dass es üblich ist, ein Gespräch mit "Hallo" zu beginnen. Ich möchte also einen Wrapper dafür schreiben P, der so funktioniert (zsh-Syntax):

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.

Die Verwendung von catoder ddin dem Replace...Teil (so etwas wie cat <&p &; exec cat >&p) führt zu unnötiger Pufferung. Was sind meine Optionen?

Michaël
quelle
Möchten Sie eine zshLösung oder ist eine bashLösung akzeptabel?
Roaima
1
Ich wäre enttäuscht von einer bashLösung, die in nicht anwendbar ist zsh, aber sie sicherlich akzeptieren würde ☺
Michaël
Ist bekannt, welche anderen Programme dieses Skript ausführen würden? Ist es eine endliche Liste oder könnte es eine beliebige Zahl sein? Natürlich muss das andere Programm über dieses Programm Bescheid wissen, um es aufrufen zu können.
Lizardx
Meine typische Verwendung war mit sshund seine Option ProxyCommand.
Michaël
1
catpuffert im Allgemeinen nicht. Wenn dies auf Ihrem System der Fall ist, versuchen Sie es cat -u.
Stéphane Chazelas

Antworten:

1

Das Problem, das Sie angegeben haben, besteht nicht darin, einen Prozess zu ersetzen, sondern die Streams eines vorhandenen Prozesses zu ersetzen . Das Ziel ist es, ein wenig mit dem Prozess zu interagieren und dann seine Eingabe / Ausgabe an ein anderes Paar verbundener Streams zu übergeben.

Es gibt keine Möglichkeit, dies direkt zu tun (zumindest in der Shell; innerhalb des Prozesses dup2könnte ein Aufruf möglicherweise funktionieren). Sie müssen die Streams spleißen. Dh:

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

Die Verwendung coprocwie in Ihrem Beispiel ist ebenfalls in Ordnung. Beachten Sie, dass der Befehl die Dateideskriptoren in einem Array speichert und Sie sie später für Umleitungen verwenden können.

Dies sollte keine zusätzliche Pufferung verursachen (zumindest bei GNU cat), es sei denn, P überprüft die Eingangs- / Ausgangsströme, mit denen es verbunden ist, und trifft eine Entscheidung, basierend darauf zu puffern. Beispielsweise aktiviert die C-Standardbibliothek die Pufferung für stdout/, stderrwenn sie mit einer Datei verbunden sind, führt jedoch nur eine Zeilenpufferung durch, wenn sie mit einem Terminal verbunden sind.

Vladimir Panteleev
quelle
-1

Versuchen Sie, mit dem folgenden Code mit Perl zu testen, um Pufferung zu vermeiden. Versuchen Sie, ob dies für Sie funktioniert

Beispielversion von 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"

Das Wrapper-Programm

$ 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

Testlauf

$ /tmp/wrapper 
Got Hello from client, working ...
Need to read some input
hi there P!   <== Typed in at teminal
Got: hi there P!
VenkatC
quelle
Dies entspricht beispielsweise der Verwendung dd ibs=1. Ich bin damit nicht einverstanden. In gewisser Weise hat der Coproc eine eigene Pufferung, und diese möchte ich verwenden.
Michaël