Why can\'t I use exec 3>myfifo in the same manner in a bash script as I can in my terminal?
I\'m using named pipes to turn an awk filter into a simple \"se
Here's a somewhat different version that processes (client-side) input in five-line blocks.
# using gawk for Mac OS X from: http://rudix.org/packages-ghi.html#gawk
# server
rm -v to_server from_server
mkfifo to_server from_server
(
while true; do
(exec gawk '{sub("wrong", "correct");print;} /\0/ {fflush();}' <to_server >from_server) &
bgpid=$!
exec 3>to_server; exec 4<from_server
wait "$bgpid"
echo "restarting..."
done
) &
# client.sh
#!/bin/bash
exec 3>to_server
exec 4<from_server
n=0
clientserver() {
n=0
(
while read -rd '' <&4; do echo -n "$REPLY"; break; done;
IFS="" read -r -d $'\n' <&4 lines && printf 'found a trailing newline in from_server fifo \n' "$lines"
) &
bgpid=$!
printf '%s\n' "${lines[@]}" >&3
printf '%b' '\000\n' >&3
wait $bgpid
unset -v lines
return 0
}
while IFS="" read -r -d $'\n' line; do
n=$((n+=1))
lines[$((n-1))]="$line"
if [[ $n -eq 5 ]]; then
clientserver
fi
done
if [[ ${#lines[@]} -gt 0 ]]; then
clientserver
fi
exit 0
# test
serverpid=$!
echo This is wrong | bash client.sh
printf '%s\n' {1..1007} | bash client.sh
kill -TERM $serverpid
I think I figured it out!
The exec commands do work, but bash itself closes all open file descriptors on exiting from the script. Adding sleep 5 to the end of the client shows that it takes 5 seconds for the server to finally shut down.
So the solution is just to open some file descriptor to my named pipes from some other terminal, and just keep them open, e.g. in terminal 3:
$ exec 3>to_server; exec 4<from_server
$ # keep open for as long as server is open
or, in the server terminal/script itself:
while true; do
# Really, this awk script BEGIN's with reading in a huge file,
# thus the client-server model
awk '{sub("wrong", "correct");print;} /\0/ {fflush();}' <to_server >from_server &
AWKPID=$!
exec 3>to_server; exec 4<from_server
wait "$AWKPID"
echo "restarting...";
done