Заменить текущий процесс его сопроцессом / потомком


10

У меня есть программа, Pкоторая ожидает получить «Hello» и вывод «Почему?» перед предоставлением функции. Эта функция используется другими программами, которые не знают, что общение с «Hello» является обычной вежливостью. Таким образом, я хочу написать оболочку для Pэтого работает так (синтаксис 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.

Использование catили ddв Replace...части (что-то вроде cat <&p &; exec cat >&p) приводит к ненужной буферизации. Какие у меня варианты?


Вы хотите zshрешение или bashрешение приемлемо?
— Ройма

1
Я был бы разочарован bashрешением, которое не применимо zsh, но, безусловно, примет его »
— Микаэль

Известно ли, какие другие программы будут запускать этот скрипт? Это конечный список, или это может быть любое число? Очевидно, что другая программа должна знать об этом, чтобы вызвать его.
— Lizardx

Мое типичное использование было с sshи его вариантом ProxyCommand.
— Михаэль

1
catкак правило, не буферизуется. Если это происходит в вашей системе, попробуйте cat -u.
— Стефан Шазелас

Ответы:


1

Проблема, которую вы указали, заключается не в замене процесса , а в замене потоков существующего процесса . Цель состоит в том, чтобы немного поработать с процессом, а затем передать его ввод / вывод другой паре связанных потоков.

Нет никакого способа сделать это напрямую (по крайней мере, в оболочке; внутри процесса dup2вызов может работать). Вам нужно будет склеить потоки. То есть:

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

Использование coprocкак в вашем примере тоже нормально. Обратите внимание, что команда сохраняет файловые дескрипторы в массив, и вы можете позже использовать их для перенаправлений.

Это не должно вызывать дополнительную буферизацию (по крайней мере, для GNU cat), если P не проверяет входные / выходные потоки, к которым он подключен, и не принимает решение о буферизации на основе этого. Например, стандартная библиотека C включит буферизацию на stdout/, stderrесли они подключены к файлу, но выполнит буферизацию строки, только если они подключены к терминалу.


-1

Можно протестировать с приведенным ниже кодом, используя Perl, чтобы избежать буферизации, попробуйте, если это работает для вас

Образец версии 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"

Программа-обертка

$ 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

Тестовый забег

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

Это то же самое, что и использование dd ibs=1, например. Я не в порядке с этим. В некотором смысле, у coproc есть своя собственная буферизация, и именно эту я хочу использовать.
— Микаэль
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.