【问题标题】:BASH: Best architecture for reading from two input streamsBASH:从两个输入流中读取的最佳架构
【发布时间】:2011-10-05 20:37:05
【问题描述】:

这里是简单的脚本:

a) 不断地从套接字读取并将值存储在关联数组中
b) 不断地从标准输入读取值并响应 t/f(如果它们已经存在)在关联数组中

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

诀窍是从两个子进程访问数组(因为将进程置于后台会生成子进程)

我正在考虑最佳策略,并且出现了一些想法,但我想知道是否有人有更好的想法:

1) 将输入从套接字重定向到标准输入作为子进程,并在一个 while 循环中处理两个输入(数据大小很小,2) 读取套接字,然后读取 STDIN,读取时具有小的 (0.1?) 超时值,以模拟非阻塞 I/O。
3) UPDATE:将socket数据写入文件(实际上是让其他进程直接写入文件),然后每次有请求进来检查值是否存在,处理文件中的条目,将它们添加到数组中(使用文件锁定)。

【问题讨论】:

  • 听起来你的想法是对的。是否有理由使用 bash 而不是另一种语言?
  • 好问题。不,没有充分的理由在另一种语言上使用 bash。 Bash 既简单又小,这是唯一的原因(我还有 5 个其他 bash 脚本执行类似的身份验证/日志记录/用户管理任务,所以维护一个统一的平台很好)

标签: linux multithreading bash io subprocess


【解决方案1】:

Bash 不是解决此问题的正确工具。此问题通常使用select(2)poll(2) 系统调用来解决,它们允许您同时等待多个文件描述符而无需旋转。 Bash 没有这些接口。

我建议使用一种脚本语言,例如 Python 或 Perl(无论你喜欢什么,真的),它提供与 selectpoll 的接口(例如 Python 的 select 模块)。

【讨论】:

  • 感谢您让我明白这一点。你说得对。在对此进行了更多研究之后,作为一名 java 人,我将学习 groovy 并努力在 groovy 中完成这项任务。一段时间以来,它一直在我的愿望清单上。
【解决方案2】:

不知道这在所描述的上下文中是否完全实用且足够原子,但是使用客户端/服务器模型和命名管道,可以创建一个 while 循环来区分来自 fifo 或 @987654321 的行@。

服务器不断地从套接字 (/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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-16
    • 2012-03-19
    • 1970-01-01
    • 2013-06-03
    • 2020-05-28
    • 2016-04-22
    相关资源
    最近更新 更多