Замініть поточний процес його спільним процесом / дочірньою


10

У мене є програма, Pяка очікує отримання "Привіт" та виведення "Чому?" перед наданням функції. Ця функція використовується іншими програмами, які не усвідомлюють, що розпочати розмову з "Привіт" є загальною люб'язністю. Таким чином, я хочу написати обгортку, 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рішення прийнятне?
roaima

1
Я був би розчарований bashрішенням, яке не застосовується в zsh, але, безумовно, прийме його ☺
Michaël

Чи відомо, які інші програми будуть запускати цей сценарій? Це обмежений список чи це може бути будь-яке число? Очевидно, що інша програма повинна знати про цю програму, щоб викликати її.
Лізардкс

Моє типове використання було з sshйого варіантом ProxyCommand.
Michaël

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, наприклад, використовувати. Я з цим не в порядку. Певним чином, копрок має власну буферизацію, і саме цей я хочу використовувати.
Michaël
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.