I would like to use bash process substitution for a sudo command.
For example, here's a non-sudo command that works for me:
$ cat <(echo "installed.txt")
installed.txt
And here's a sudo version of the command that does not work:
$ sudo cat <(echo "installed.txt")
cat: /dev/fd/63: Bad file descriptor
Reading the sudo man page, it seems that sudo closes all but the stdin/stdout/stderr file descriptors before running the command as root. This leads me to think that bash is creating the descriptor (and performing the process substitution) before running the sudo command.
I changed root's shell to bash (instead of sh default). I've tested that the command works fine when logged in as root. It only does not work via a sudo command.
What is the appropriate technique to achieve what I'm trying to do here? Eval, quoting, sudo flag, sudoers file mod, other?
Try doing this in your shell :
$ sudo bash -c 'cat <(echo "installed.txt for UID=$UID")'
installed.txt for UID=0
In case you're asking for process substitution for the security it brings, like hiding a password from the process list, then you might better do it this way:
cat <(echo -n "$PASSWORD") | sudo cryptsetup ... --key-file -
Sure, the password is sent to sudo
through its stdin
, so the process substitution is not done within sudo
as asked. And my answer becomes technically off topic.
I still hope it will help in this particular context, because the accepted answer comes with serious drawbacks: you need to build a properly quoted string, and then spawn a secondary shell to interpret it within the sudo
.
This makes it not only slow, but also risky due to shell injection, environment variables and so.
The behaviour described in the question is due to the design of sudo
.
$ sudo cat <(echo "installed.txt")
cat: /dev/fd/63: Bad file descriptor
The error occurs because sudo
has a default behaviour which closes file descriptors except for standard input, output and error. As described on the man page:
By default, sudo will close all open file descriptors other than standard input, standard output and standard error when executing a command.
This behaviour can be overridden with the -C
(or --close-from
) option to specify a file descriptor number below which files should not be closed. However, use of this option must be permitted by an administrator: the following needs to be added to /etc/sudoers
Defaults closefrom_override
With that in place, the command will work if -C
is used:
$ sudo -C64 cat <(echo "installed.txt")
installed.txt
(here the number 64
was given because it was greater than the 63
in the error message).
sudo bash -c 'cat <(echo "installed.txt")'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With