BASH:读取两个输入流的最佳架构

5

以下是简单的脚本:

a) 不断读取socket中的数据并将其存储在一个关联数组中
b) 不断从标准输入中读取值,如果它们已经存在于关联数组中,则回应t/f

a和b是随机事件,没有任何关联。

问题是如何从两个子进程访问该数组(因为将进程放入后台会生成子进程)

我正在思考最佳策略,有一些想法,但不知道有没有更好的办法:

1) 将socket中的输入重定向到标准输入作为子进程,并在一个while循环中处理两个输入(数据大小很小,小于30个字符,所以我猜它们会保持原子性?)。
2) 先读取socket,然后使用小的(0.1?)超时值在STDIN上读取,以模拟非阻塞I/O。
3) 更新:将socket数据写入文件(实际上让另一个进程直接将其写入文件),然后每次收到检查值是否存在的请求时,处理文件中的条目,将它们添加到数组中(使用文件锁定)。


听起来你的想法是正确的。有没有特别的原因要用bash而不是其他编程语言呢? - Slartibartfast
好问题。没有什么好的理由使用Bash而不是其他语言。Bash简单而小巧,这是唯一的原因(而且我还有5个其他的Bash脚本执行类似的身份验证/日志记录/用户管理任务,所以保持统一的平台很好)。 - David Parks
2个回答

4
Bash并不是解决这个问题的正确工具。通常使用select(2)poll(2)系统调用来解决此类问题,这允许您同时等待多个文件描述符而不会旋转。Bash没有与它们中的任何一个接口。我建议使用脚本语言,例如Python或Perl(无论您对哪种语言感到舒适),这些语言提供了与selectpoll的接口(例如Python的select模块)。

谢谢你纠正我。你是对的。经过更深入的研究,作为一个Java程序员,我将学习Groovy并努力用它来完成这个任务。学习Groovy已经在我的愿望清单上有一段时间了。 - David Parks

3
不知道在所描述的上下文中是否完全实用和原子化,但使用客户端/服务器模型和命名管道可以创建一个while循环,可以区分来自fifo或stdin的行。服务器不断从套接字(/tmp/to)读取行以及从stdin读取行(通过/tmp/to重定向到服务器)。然而,stdin的行由del字节(\177)标记为该行的第一个字节。然后,(后台)客户机while循环使用此行的第一个字节来区分不同来源的行。
# terminal window 1

# server
(
rm -f /tmp/to /tmp/from
mkfifo /tmp/to /tmp/from
while true; do 
  while IFS="" read -r -d $'\n' line; do 
    printf '%s\n' "${line}"
  done </tmp/to >/tmp/from &
  bgpid=$!
  exec 3>/tmp/to
  exec 4</tmp/from
  trap "kill -TERM $bgpid; exit" 0 1 2 3 13 15
  wait "$bgpid"
  echo "restarting..."
done
) &
serverpid=$!

# client
(
exec 3>/tmp/to;
exec 4</tmp/from;
while IFS="" read -r -d $'\n' <&4 line; do
  if [[ "${line:0:1}" == $'\177' ]]; then 
    printf 'line from stdin: %s\n' "${line:1}"
  else       
    printf 'line from fifo: %s\n' "$line"
  fi
done &
trap "kill -TERM $"'!; exit' 1 2 3 13 15
while IFS="" read -r -d $'\n' line; do
  # can we make it atomic?
  # sleep 0.5
  # dd if=/tmp/to iflag=nonblock of=/dev/null  # flush fifo
  printf '\177%s\n' "${line}"
done >&3
) 
#kill -TERM $serverpid


# terminal window 2
echo hello > /tmp/to

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接