Bash – Parameretrize file descriptor number to open a tcp socket in shell script

bashfile-descriptorsio-redirectionshellshell-script

I'm tried to parameretrize in a variable the file descriptor number to open a tcp socket using exec command but it failed. Only work correctly when file descriptor number is a constant. In the next example code only success the first retry (RC=0).

Code:

echo -e "\nRetry 1: "
socket="/dev/tcp/$ip/$port"
exec 3<>$socket
echo "RC: $?"


echo -e "\nRetry 2: "
descriptor=3
socket="/dev/tcp/$ip/$port"
exec $descriptor<>$socket
echo "RC: $?"


echo -e "\nRetry 3: "
descriptor="3"
socket="/dev/tcp/$ip/$port"
exec $descriptor<>$socket
echo "RC: $?"

echo -e "\nRetry 4: "
descriptor=3
socket="/dev/tcp/$ip/$port"
exec "$descriptor"<>$socket
echo "RC: $?"

echo -e "\nRetry 5: "
descriptor=3
socket="/dev/tcp/$ip/$port"
`exec $descriptor<>$socket`
echo "RC: $?"

The output is:

Retry 1:
RC: 0

Retry 5:
socket.sh: line 46: exec: 3: not found
RC: 127

or, in other cases:

Retry 1:
RC: 0

Retry X:
socket.sh: line 27: exec: 3: not found

Best Answer

It's easy to understand why it fails when you think of:

echo $text>some-file

You wouldn't want it to behave differently if $text happens to contain a number.

You'd need to use eval here:

eval 'exec '"$fd"'> "$file"'

(you want $fd to be expanded in the arguments to eval, but not $file).

Note that ksh93, zsh and bash have introduced (in April 2005, zsh 4.3.0, bash 4.1-alpha, ksh93r) the possibility to have dynamic fds, like:

exec {fd}> "$file"

Here, the file descriptor (a free one above 10) is chosen by the shell and stored into the $fd variable.

Which you can use with ... >&$fd.

It matches more closely what you do in other languages: fd = open(...), write(fd, ...).

Related Question