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

发布于 2024-11-23 16:04:35 字数 525 浏览 2 评论 0原文

这里的简单脚本:

a)不断地从套接字读取并将值存储在关联数组中
b) 持续从 stdin 读取值并响应 t/f(如果它们已存在于关联数组

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

诀窍是从两个子进程访问数组(因为将一个进程放在后台会将其作为子进程生成)

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

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

Simple script here:

a) constantly read from a socket and store values in an associative array
b) constantly read values from stdin and respond t/f if they already exist in the associative array

a & b are random events, not associated in any way.

The trick is accessing the array from both subprocesses (since putting a process in the background spawns it as a subprocess)

I'm thinking through the best strategy, and a few ideas occur, but I wonder if anyone has anything better in mind:

1) redirect the input from socket to stdin as a subprocess and handle both inputs in one while loop (data sizes are small, <30 characters, so I guess they will remain atomic?).
2) read the socket, then STDIN with small (0.1?) timeout values on read so as to mimic non-blocking I/O.
3) UPDATE: write the socket data to a file (actually have the other process write it directly to a file), then each time a request comes in to check if the value exists, process the entries in the file, adding them to the array (use file locking).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

也只是曾经 2024-11-30 16:04:35

Bash 不是合适的工具。此问题通常可以使用 select(2)poll(2) 系统调用,允许您等待同时处理多个文件描述符而无需旋转。 Bash 没有与其中任何一个的接口。

我建议使用诸如 Python 或 Perl 之类的脚本语言(实际上,无论您使用哪种语言),它们提供了带有 selectpoll 的接口(例如 Python 的 select 模块)。

Bash is not the right tool for this. This problem is typically solved using the select(2) or poll(2) system calls, which allow you to wait on multiple file descriptors simultaneously without spinning. Bash does not have an interface to either of those.

I'd recommend using a scripting language such as Python or Perl (whatever you're comfortable with, really) that provides an interface with select or poll (e.g. Python's select module).

失而复得 2024-11-30 16:04:35

不知道这在所描述的上下文中是否完全实用且足够原子,但是使用客户端/服务器模型和命名管道,可以创建一个 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

Don't know if this is fully practical and atomic enough in the described context, but using a client / server model and named pipes it's possible to create a while-loop that can distinguish between lines coming from a fifo or stdin.

The server constantly reads lines from a socket (/tmp/to) as well as lines from stdin (which is being redirected to the server via /tmp/to).

However, lines from stdin get marked by the del byte (\177) to be the first byte of the line.

Then the (backgrounded) client while-loop uses this first-byte-of-line to distinguish lines of different origin.

# 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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文