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?
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).
Try doing this in your shell :
$ sudo bash -c 'cat <(echo "installed.txt for UID=$UID")'
installed.txt for UID=0
sudo bash -c 'cat <(echo "installed.txt")'
最好的方法可能是将所有内容都放在一个脚本中,然后使用sudo
运行该脚本。
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 technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.