最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

while loop - How to read piped output produced in background subshell - Stack Overflow

programmeradmin3浏览0评论

I'm creating a script where multiple outputs from background processes are captured through while-read loop. However, it only works if I capture output directly to while loop. Trimmed down version of script is below where subscribe_audio_v1 does not work. I'm guessing its because of subshell that gets created during | however the same pipe works in v2 of function.

#!/bin/sh

# This version doesn't work.
function subscribe_audio_v1() {
  pactl subscribe | awk '/change/{print "event_audio_v1"}'
}

# This version works
function subscribe_audio_v2() {
  pactl subscribe | while read -r x
  do
    case "$x" in
      *change*) echo event_audio_v2 ;;
    esac
  done
}

function event_container() {
  subscribe_audio_v1 &
  subscribe_audio_v2 &
}

function loop() {
  while read -r x
  do
    case $x in
      event_audio*) echo "Working on ${x}..." ;;
    esac
  done
}

event_container | loop

Edit: I'm trying to circumvent default full buffer allocation of pipe process with a new descriptor. This makes both v1 and v2 function print their string however I'm unable to capture that output as input for loop function

exec 3>&1
event_container >&3
loop <&3

I'm creating a script where multiple outputs from background processes are captured through while-read loop. However, it only works if I capture output directly to while loop. Trimmed down version of script is below where subscribe_audio_v1 does not work. I'm guessing its because of subshell that gets created during | however the same pipe works in v2 of function.

#!/bin/sh

# This version doesn't work.
function subscribe_audio_v1() {
  pactl subscribe | awk '/change/{print "event_audio_v1"}'
}

# This version works
function subscribe_audio_v2() {
  pactl subscribe | while read -r x
  do
    case "$x" in
      *change*) echo event_audio_v2 ;;
    esac
  done
}

function event_container() {
  subscribe_audio_v1 &
  subscribe_audio_v2 &
}

function loop() {
  while read -r x
  do
    case $x in
      event_audio*) echo "Working on ${x}..." ;;
    esac
  done
}

event_container | loop

Edit: I'm trying to circumvent default full buffer allocation of pipe process with a new descriptor. This makes both v1 and v2 function print their string however I'm unable to capture that output as input for loop function

exec 3>&1
event_container >&3
loop <&3
Share Improve this question edited Mar 17 at 10:36 decepticlown asked Mar 16 at 19:53 decepticlowndecepticlown 112 bronze badges 11
  • please define "does not work". what should happen? what does happen? – jhnc Commented Mar 16 at 20:31
  • Both v1 and v2 print string event_audio_v1 and event_audio_v2 respectively. Function loop captures it and prints the output. But it only works for v2. – decepticlown Commented Mar 16 at 20:59
  • what happens if you add fflush() in awk? – jhnc Commented Mar 16 at 21:04
  • Writing from my phone so I can't test it right now. I'll get back as soon as I can. Reading in fflush tells me it forcefully empties the buffer even before it's full. – decepticlown Commented Mar 16 at 21:15
  • Does that mean awk will indifinetly hold back output untill it's buffer gets full? – decepticlown Commented Mar 16 at 21:16
 |  Show 6 more comments

1 Answer 1

Reset to default -1

First capture output of all background processes:

data=$( event_container )

Than process it:

loop <<< "$data"
发布评论

评论列表(0)

  1. 暂无评论