简体   繁体   中英

Using bash process substitution for a sudo command

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM