Bash: Redirection with <> wronlgy recognized as positonal parameter

Hello dear community and team of Travis CI,

I try to run a command which is including the creation of a file descriptor in bash with 3<>/dev/tap4.
So attaching a VM to a TAP device via the creation of a R/W redirection to a file descriptor.
This is failing during runtime because the parser of Travis CI seems to not recognized this kind of redirection but it interprets it as positional parameter and add some quoting which spoils the redirection.

Is there something I can do to make this thing work?

The command to run:

sudo qemu-system-x86_64 -m 2048 -smp 2 -display none -daemonize -boot n -net nic,model=e1000 -net tap,fd=3 3<>/dev/tap4

How Travis CI interprets it:

sudo qemu-system-x86_64 -m 2048 -smp 2 -display none -daemonize -boot n -net nic,model=e1000 -net tap,fd=3 '3<>/dev/tap4'

Leads to failing with:

qemu-system-x86_64: -net tap,fd=3: Could not open '3<>/dev/tap4': No such file or directory
The command "./server/run_coinboot" exited with 1.

Here the link to the build log: https://travis-ci.com/frzb/coinboot/jobs/240224598

This reasoning doesn’t make sense to me. We compile the bash script, it is true. However, since the string in question is contained inside your Bash script, there is no chance for our build script to mess with the argument handling.

The string is passed to bash, which hands it to sudo, which hands it to qemu-system-x86_64 for interpretation. I can’t tell you which of these part(s) is not working with <>, but I am pretty doubtful that it is Travis CI.

Does this set up work on your machine?

I believe stuff inserted by substitution is not subject to further interpretation by Bash. It first interprets shell syntax, then processes its semantics including any substitutions.

You need to use eval to force Bash to re-interpret the result of substitutions as a new command line.

Thank you for having a look into this.

Yes the command is working properly outside Travis CI.

For my understanding the issue is created by the quoting added obviously by Travis CI: transforming 3<>/dev/tap4 to '3<>/dev/tap4' transforms also everything to one string avoiding the redirection <> to be handled properly by the shell.

The string is inside your script.

There is no way that our build script is changing the content of this file. Something is interpreting that part of the string as an argument, and it is at least one of bash, sudo, and qemu-system-x86_64.

To wit:

travis@e5bb08546f87:~$ cat build.sh
#!/usr/bin/env bash

ARGS="abc 3<>/tmp/foo"
sudo echo $ARGS
travis@e5bb08546f87:~$ bash -x build.sh
+ ARGS='abc 3<>/tmp/foo'
+ sudo echo abc '3<>/tmp/foo'
abc 3<>/tmp/foo

You notice that, despite having ARGS="abc 3<>/tmp/foo", bash’s xtrace option shows that it interprets the last component as one argument to sudo, not file descriptors redirection.

You can try taking @native-api’s advice and play with eval and what not.

1 Like

Thanks @native-api and @BanzaiMan for these insights.

Makes completely sense - I gave eval a try and it looks good so far.