0

On OSX, while attempting to expose a service implemented as a bash script, and started with coproc, to a client implemented as a bash script, by passing the IO streams of the service to the client, I discovered I could use variables 5 and 6, but not 3 and 4 to hold the streams. I expected to be able to use any number 3 or above.

For example, the following works:

If service ./capitalize is

#!/usr/bin/env bash
while true; do 
    read line
    echo "${line^}"
done

and ./client is

#!/usr/bin/env bash
lsof -p $$ | grep PIPE
echo $1 >&6
read line <&5
echo Result: "${line}"

and we check our bash version, start the service, and reflect on the exposed pipes

$ bash --version
GNU bash, version 5.0.18(1)-release (x86_64-apple-darwin19.5.0)
$ coproc SVC { ./capitalize; }
$ echo ${SVC[@]}
63 60
$ lsof -p $$ | grep PIPE
bash    30833 Setup   60   PIPE 0xaafc4e53240e4cbe    16384                     ->0x1eca6ceb32d18709
bash    30833 Setup   63   PIPE 0x904d6242c4e8c148    16384                     ->0xe8caffae10f9dd84

and then execute

$ ./client "foo" 5< /dev/fd/${SVC[0]} 6> /dev/fd/${SVC[1]}
bash    31441 Setup    5   PIPE 0x904d6242c4e8c148    16384                     ->0xe8caffae10f9dd84
bash    31441 Setup    6   PIPE 0xaafc4e53240e4cbe    16384                     ->0x1eca6ceb32d18709
Result: Foo

then things behave as expected. foo has been capitalized to Foo and we can see the capitalize output and input streams have been re-maped into client as 63 -> 5 and 60 -> 6.

However, if I change the file descriptors from 5 -> 3 and 6 -> 4, then things unexpectedly fail. They fail because descriptors 3 and 4 do not get passed to client.

If ./client is updated to

#!/usr/bin/env bash
lsof -p $$ | grep PIPE
echo $1 >&4
read line <&3
echo Result: "${line}"

then executing

$ ./client "foo" 3< /dev/fd/${SVC[0]} 4> /dev/fd/${SVC[1]}
./client: line 3: 3: Bad file descriptor
./client: line 4: 4: Bad file descriptor
Result: 

yields no results because the file descriptors do not appear!

So why can I use 5/6, but not 3/4? Are 3/4 reserved? How would I know that?


Also, if I executing using an alternate syntax for redirection then the streams are not redirected even though I thought the syntax where semantically equivalent.

So changing this

$ ./client "foo" 5< /dev/fd/${SVC[0]} 6> /dev/fd/${SVC[1]}

to

$ ./client "foo" 5<&${SVC[0]} 6>&${SVC[1]}

results in

./client: line 3: 6: Bad file descriptor
./client: line 4: 5: Bad file descriptor
Result: 

Aren't those two syntaxes for redirection, 5< /dev/fd/${SVC[0]} and 5<&${SVC[0]} supposed to be equivalent?

Thanks in advance!

2
  • 1
    Observation: In Bash 5.0.3 in Debian 10 the main problem does not occur (in Linux I need to grep for FIFO, hardly relevant; anyway there is no Bad file descriptor for 3 nor 4, these descriptors work as well as 5 and 6). The other issue is a separate issue. Commented Oct 27, 2020 at 8:29
  • Thanks! At least I know I'm not going outta my mind! Commented Oct 27, 2020 at 8:48

0

You must log in to answer this question.

Browse other questions tagged .