I would like to run a child process that can read and write data from/to the parent process, in a way that the child process uses standard stdin/stdout, and doesn't use named pipes.
I wrote simple programs for testing, and this is what it's supposed to do:
start
to the parent;yes
to the parent if the number equals 3
, or no
otherwise;yes
is received, or sends an other random number to the child otherwise;#!/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
#!/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
I execute the parent script with the child script as a parameter (parent.sh ./child.sh
), then I open the logger in another terminal (tail -f ./logger
).
It seems that the child is never executed:
[parent] Start
[parent] Starting child
[parent] Reading child output...
Why?
If I replace the line $1 > $INPUT < $OUTPUT &
by $1 > $INPUT &
, the script is executed, but ends without entering in the main loop.
edit: fixed the echo answer
mistake
There are two issues. One is minor: in the child, you've accidentally written echo answer
instead of echo $answer
. The other is significant. By writing echo $number > $OUTPUT
in the parent, you are closing and reopening the fifo on every iteration of the loop. Instead, you want to keep it open and move the redirection outside the loop. That is:
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