具有 children 个进程的双向管道
bidirectional pipe with children process
我想运行一个可以读写数据的child进程 from/to parent进程,child进程使用标准 stdin/stdout,不使用命名管道。
我编写了简单的测试程序,这就是它应该做的:
- parent开始child,然后听;
- child 发送
start
到 parent;
- parent 发送一个 1 到 5 之间的随机数到 child;
- child读取这个数字,如果数字等于
3
,则发送yes
到parent,否则no
;
- parent读取答案,如果收到
yes
则退出,否则发送另一个随机数给child;
- 日志被打印到一个文件中以便更好地理解。
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 客户端之外执行代码。
我想运行一个可以读写数据的child进程 from/to parent进程,child进程使用标准 stdin/stdout,不使用命名管道。
我编写了简单的测试程序,这就是它应该做的:
- parent开始child,然后听;
- child 发送
start
到 parent; - parent 发送一个 1 到 5 之间的随机数到 child;
- child读取这个数字,如果数字等于
3
,则发送yes
到parent,否则no
; - parent读取答案,如果收到
yes
则退出,否则发送另一个随机数给child; - 日志被打印到一个文件中以便更好地理解。
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 客户端之外执行代码。