2011-10-01, 06:54(-05), Dan Douglas: [...] > f() { > local -i x y > while read -rN1 "x[y++]"; do > printf '%d ' "${1}" >&2 # keep track of which job this is. > done > printf "${#x[@]} " # Print the total number of reads by each > job.
if you add a echo >&2 "[done $1]" here. > } > > g() { # Used in ex 6 > f 1 <${1} & > f 2 <${1} > } > > # This works as I expect, f is backgrounded and two readers of one pipe each > get about half the input: > exincr # 1 > > read -ra x < <({ f 1 & f 2; } < <(zeros)) > printf '%b\n' "\n${x[@]}\n" > > # Equivalent to above, except with piped output. Now f is not backgrounded. > One reader consumes all the input: > exincr # 2 > > { f 1 & f 2; } < <(zeros) | { You'll notice that f 1 terminates straight away. And if you do a strace, you'll notice that bash does a dup2(open("/dev/null"), 0), that is redirecting "f 1"'s stdin to /dev/null. ~$ bash -c '{ cat; } < c | cat' test ~$ bash -c '{ cat & } < c | cat' ~$ bash -c '{ lsof -ac lsof -d0; } < c | cat' COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME lsof 5005 chazelas 0r REG 253,2 5 58785638 /home/chazelas/c ~$ bash -c '{ lsof -ac lsof -d0 & } < c | cat' COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME lsof 5010 chazelas 0r CHR 1,3 0t0 973 /dev/null That behavior is required by POSIX and occurs for ash and pdksh and its derivatives as well: POSIX> command1 & [command2 & ... ] POSIX> POSIX> The standard input for an asynchronous list, before any POSIX> explicit redirections are performed, shall be considered to POSIX> be assigned to a file that has the same properties as POSIX> /dev/null. If it is an interactive shell, this need not POSIX> happen. In all cases, explicit redirection of standard input POSIX> shall override this activity. However, I don't know why bash does it only in the "pipe" case. ~$ ash -c '{ lsof -ac lsof -d0 & } < c' COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME lsof 5188 chazelas 0r CHR 1,3 0t0 973 /dev/null ~$ bash -c '{ lsof -ac lsof -d0 & } < c' COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME lsof 5191 chazelas 0r REG 253,2 5 58785638 /home/chazelas/c To work around, this <&0 trick seems to work: ~$ bash -c '{ lsof -ac lsof -d0 <&0 & } < c | cat' COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME lsof 5247 chazelas 0r REG 253,2 5 58785638 /home/chazelas/c -- Stephane