具有 children 个进程的双向管道

bidirectional pipe with children process

我想运行一个可以读写数据的child进程 from/to parent进程,child进程使用标准 stdin/stdout,不使用命名管道。

我编写了简单的测试程序,这就是它应该做的:

parent.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
 > $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

child.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

我使用 child 脚本作为参数执行 parent 脚本 (parent.sh ./child.sh),然后我在另一个终端 (tail -f ./logger) 中打开记录器。

似乎 child 从未执行过:

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

为什么?

如果我用 > $INPUT & 替换行 > $INPUT < $OUTPUT &,脚本会执行,但没有进入主循环就结束了。

编辑:修复了 echo answer 错误

有两个问题。一个是次要的:在 child 中,您不小心写了 echo answer 而不是 echo $answer。另一个很重要。通过在 parent 中写入 echo $number > $OUTPUT,您将在循环的每次迭代中关闭并重新打开 fifo。相反,您希望保持它打开并将重定向移到循环之外。即:

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

我不能代表任何人,但如果我需要做这样的事情,我会 运行 一个本地 IRC 服务器并编写两个机器人(编程客户端;基本上 运行 XChat 用脚本)代表 parent 和 child。这是我能想到的最简单的方法了。

使用 IRC,您可以使用聊天频道或传入的私人消息作为事件触发器。所以当 child 向他们所在的频道发送“开始”时,parent 会立即检测到它。您可以使用这些触发器在 IRC 客户端之外执行代码。