BASH: Best architecture for reading from two input streams

后端 未结 2 1901
长情又很酷
长情又很酷 2020-12-21 00:42

Simple script here:

a) constantly read from a socket and store values in an associative array
b) constantly read values from s

相关标签:
2条回答
  • 2020-12-21 00:52

    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).

    0 讨论(0)
  • 2020-12-21 01:03

    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
    
    0 讨论(0)
提交回复
热议问题