Search code examples
bashfile-descriptor

Error while closing file descriptors in bash with exec


I'm trying to make a script to test a program but I need to use some black magic with file descriptor and redirections.
But the problem is that I'm trying to use exec file_descriptor > &- to close it but the script is throwing an error here is the code and the errors:

for fd in "${fds[@]}"; do
    echo "Closing fd $fd and remove pipes"
    exec $fd<&-
    rm -f pipe$fd
done

and the fd's are created/stored like that:

pfd=25 #I start the file descriptors to 25 because my program open some file descriptors
fds=()
mkfifo pipe$pfd
exec $pfd>pipe$pfd
fds+=$pfd
pfd=$((( $pfd + 1 )))

And the error is

exec: 25: not found

I don't know why but exec don't want to be executed with the variable, when i remove the variable and put the number, it works. But I need to put the variable so I don't know how to fix this.


Solution

  • The correct syntax is:

    exec {fd}<&-
    

    Note that this requires bash 4.1 or later; earlier versions could not substitute file descriptor numbers without using eval.


    That said, consider letting bash auto-allocate all the descriptor numbers, and splitting them off from your pipe numbers.

    pipe_names=( )
    pipe_fds=( )
    pipe_num=0
    
    newpipe() {
      local pfd_new pipe_name="pipe${pipe_num}"
      mkfifo "$pipe_name" || return
      exec {pfd_new}>"$pipe_name" || return
      pipe_fds[$pipe_num]=$pfd_new
      pipe_names[$pipe_num]=$pipe_name
      (( ++pipe_num ))
    }