【发布时间】:2020-08-04 20:09:23
【问题描述】:
我想运行一个可以从/向父进程读取数据和向父进程写入数据的子进程,其方式是子进程使用标准 stdin/stdout,并且不使用命名管道。
我编写了简单的测试程序,这是它应该做的:
- 父母启动孩子,然后听它;
- 孩子向父母发送
start; - 父母向孩子发送一个介于 1 和 5 之间的随机数;
- 孩子读取这个号码,如果号码等于
3,则发送yes给父母,否则发送no; - 父母读取答案,如果收到
yes则退出,否则向孩子发送另一个随机数; - 将日志打印到文件中以便更好地理解。
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
$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
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
我以子脚本作为参数 (parent.sh ./child.sh) 执行父脚本,然后在另一个终端 (tail -f ./logger) 中打开记录器。
似乎永远不会执行孩子:
[parent] Start
[parent] Starting child
[parent] Reading child output...
为什么?
如果我将$1 > $INPUT < $OUTPUT & 行替换为$1 > $INPUT &,脚本会执行,但不会进入主循环就结束。
编辑:修复了echo answer 错误
【问题讨论】:
-
你说你不想使用命名管道,但你正在使用
mkfifo。 -
将“回显答案”更改为
echo $answer -
另外,您可能希望将父级的重定向移出循环并写入:
... done < $INPUT > $OUTPUT -
@Barmar 我不想在子脚本中使用命名管道,但在父脚本中可以。
-
@WilliamPursell 谢谢!这是公认的答案。
标签: bash named-pipes