Remplacer le processus actuel par son coprocessus / enfant

10

J'ai un programme Pqui s'attend à recevoir "Bonjour" et à afficher "Pourquoi?" avant de fournir une fonctionnalité. Cette fonctionnalité est utilisée par d'autres programmes qui ne savent pas qu'il est courant de commencer une conversation avec "Bonjour". Je veux donc écrire un wrapper pour Pça fonctionne comme ça (syntaxe 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'utilisation de catou dddans la Replace...pièce (quelque chose comme cat <&p &; exec cat >&p) entraîne une mise en mémoire tampon inutile. Quelles sont mes options?

Michael
la source
Voulez-vous une zshsolution ou une bashsolution est-elle acceptable?
roaima
1
Je serais déçu par une bashsolution qui n'est pas applicable dans zsh, mais qui l'accepterait certainement ☺
Michaël
Est-il connu quels autres programmes exécuteraient ce script? S'agit-il d'une liste finie, ou pourrait-il s'agir d'un nombre quelconque? Il est clair que l'autre programme doit connaître celui-ci pour l'appeler.
Lizardx
Mon utilisation typique était avec sshet son option ProxyCommand.
Michaël
1
catne tamponne généralement pas. Si c'est le cas sur votre système, essayez cat -u.
Stéphane Chazelas

Réponses:

1

Le problème que vous avez indiqué ne concerne pas vraiment le remplacement d'un processus , mais le remplacement des flux d' un processus existant . Le but est d'interagir un peu avec le processus puis de transmettre son entrée / sortie à une autre paire de flux connectés.

Il n'y a aucun moyen de le faire directement (au moins, dans le shell; à l'intérieur du processus, un dup2appel pourrait éventuellement fonctionner). Vous devrez épisser les flux. C'est à dire:

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

Utiliser coproccomme dans votre exemple est également OK. Notez que la commande enregistre les descripteurs de fichiers dans un tableau et que vous pouvez les utiliser ultérieurement pour les redirections.

Cela ne devrait pas provoquer de mise en mémoire tampon supplémentaire (au moins avec GNU cat), sauf si P inspecte les flux d'entrée / sortie auxquels il est connecté et prend une décision de mise en mémoire tampon en fonction de cela. Par exemple, la bibliothèque standard C active la mise en mémoire tampon sur stdout/ stderrs'ils sont connectés à un fichier, mais n'effectue la mise en mémoire tampon de ligne que s'ils sont connectés à un terminal.

Vladimir Panteleev
la source
-1

Capable de tester avec le code ci-dessous en utilisant perl pour éviter la mise en mémoire tampon, essayez si cela fonctionne pour vous

Exemple de version 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"

Le programme 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

Essai

$ /tmp/wrapper 
Got Hello from client, working ...
Need to read some input
hi there P!   <== Typed in at teminal
Got: hi there P!
VenkatC
la source
C'est la même chose que l'utilisation dd ibs=1, par exemple. Je ne suis pas d'accord avec ça. D'une certaine manière, le coproc a sa propre mise en mémoire tampon, et c'est celui-ci que je veux utiliser.
Michaël