How do I use exec 3>myfifo in a script, and not have echo foo>&3 close the pipe?

夙愿已清 提交于 2019-11-29 11:55:43

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

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!