двунаправленная труба с дочерним процессом - PullRequest
1 голос
/ 04 августа 2020

Я хотел бы запустить дочерний процесс, который может читать и записывать данные из / в родительский процесс таким образом, чтобы дочерний процесс использовал стандартный stdin / stdout и не использовал именованные каналы.

Я написал простые программы для тестирования, и вот что он должен делать:

  • родитель запускает ребенка, затем слушает его;
  • ребенок отправляет start в родитель;
  • родитель отправляет случайное число от 1 до 5 ребенку;
  • ребенок читает это число и отправляет yes родителю, если число равно 3 , или no в противном случае;
  • родитель читает ответ, затем выходит, если получено yes, или отправляет другое случайное число дочернему элементу в противном случае;
  • журналы печатаются в файл для лучшего понимания.

родитель. sh

#!/usr/bin/env bash
# Usage: parent.sh ./child.sh

INPUT="/tmp/input"
OUTPUT="/tmp/output"
LOG_FILE="./logger"

echo "[parent] Start" >> $LOG_FILE

rm -f $INPUT $OUTPUT
mkfifo $INPUT $OUTPUT

echo "[parent] Starting child" >> $LOG_FILE
$1 > $INPUT < $OUTPUT &

echo "[parent] Reading child output..." >> $LOG_FILE
while read answer; do
    echo "[parent] Received from child: $answer" >> $LOG_FILE
    if [ "$answer" = "yes" ]; then
        break
    else
        number=$(( ( RANDOM % 5 )  + 1 ))
        echo "[parent] Sending to child: $number" >> $LOG_FILE
        echo "$number" > $OUTPUT
    fi
done < "$INPUT"

echo "[parent] end" >> $LOG_FILE

дочерний. sh

#!/usr/bin/env bash

LOG_FILE="./logger"
SECRET_NUMBER=3

echo "[child] Start" >> $LOG_FILE
echo "start"

while read line; do
    echo "[child] Received from parent: $line" >> $LOG_FILE
    if [ "$line" == "$SECRET_NUMBER" ]; then
        answer="yes"
    else
        answer="no"
    fi
    echo "[child] Sending to parent: $answer" >> $LOG_FILE
    echo $answer
done

echo "[child] End" >> $LOG_FILE

Я выполняю родительский скрипт с дочерний скрипт в качестве параметра (parent.sh ./child.sh), затем я открываю регистратор в другом терминале (tail -f ./logger). * 1 032 *

Кажется, что потомок никогда не запускается:

[parent] Start
[parent] Starting child
[parent] Reading child output...

Почему?

Если я заменяю строку $1 > $INPUT < $OUTPUT & на $1 > $INPUT &, скрипт выполняется, но заканчивается без входа в основной l oop.

edit: исправлена ​​echo answer ошибка

Ответы [ 2 ]

1 голос
/ 04 августа 2020

Есть две проблемы. Один из них второстепенный: у ребенка вы случайно написали echo answer вместо echo $answer. Другой важный. Записывая echo $number > $OUTPUT в родительский объект, вы закрываете и снова открываете fifo на каждой итерации l oop. Вместо этого вы хотите оставить его открытым и переместить перенаправление за пределы l oop. То есть:

while read answer; do
    echo "[parent] Received from child: $answer" >> $LOG_FILE
    if [ "$answer" = "yes" ]; then
        break
    else
        number=$(( ( RANDOM % 5 )  + 1 ))
        echo "[parent] Sending to child: $number" >> $LOG_FILE
        echo "$number"
    fi
done < "$INPUT" > $OUTPUT
0 голосов
/ 04 августа 2020

Я не могу говорить ни за кого другого, но если бы мне когда-нибудь понадобилось сделать что-то подобное, я бы запустил локальный сервер IR C и написал бы двух ботов (запрограммированных клиентов; в основном запускал XChat со сценарием), представляющих родитель и ребенок. Это был бы самый простой способ сделать это, о чем я могу думать.

С IR C вы можете использовать каналы чата или входящие личные сообщения в качестве триггеров событий. Таким образом, в тот момент, когда ребенок отправил «start» каналу, в котором они оба были, родитель немедленно обнаружил бы это. Вы можете использовать эти триггеры для выполнения кода вне самого клиента IR C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...