简体   繁体   English

使用 bash 进程替换 sudo 命令

[英]Using bash process substitution for a sudo command

I would like to use bash process substitution for a sudo command.我想对 sudo 命令使用 bash 进程替换。

For example, here's a non-sudo command that works for me:例如,这是一个对我有用的非 sudo 命令:

$ cat <(echo "installed.txt")
installed.txt

And here's a sudo version of the command that does not work:这是一个不起作用的命令的 sudo 版本:

$ 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.阅读 sudo 手册页,似乎 sudo 在以 root 身份运行命令之前关闭了除 stdin/stdout/stderr 文件描述符之外的所有文件描述符。 This leads me to think that bash is creating the descriptor (and performing the process substitution) before running the sudo command.这让我认为 bash 在运行 sudo 命令之前正在创建描述符(并执行进程替换)。

I changed root's shell to bash (instead of sh default).我将 root 的 shell 更改为 bash(而不是 sh 默认值)。 I've tested that the command works fine when logged in as root.我已经测试过该命令在以 root 身份登录时可以正常工作。 It only does not work via a sudo command.它只是不能通过 sudo 命令工作。

What is the appropriate technique to achieve what I'm trying to do here?实现我在这里要做的事情的适当技术是什么? Eval, quoting, sudo flag, sudoers file mod, other? Eval,引用,sudo 标志,sudoers 文件模块,其他?

The behaviour described in the question is due to the design of sudo .问题中描述的行为是由于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.发生错误是因为sudo有一个默认行为,即关闭除标准输入、输出和错误之外的文件描述符。 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.默认情况下,sudo 会在执行命令时关闭除标准输入、标准输出和标准错误之外的所有打开的文件描述符。

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.此行为可以用-C (或--close-from )选项覆盖以指定文件描述符编号,低于该编号不应关闭文件。 However, use of this option must be permitted by an administrator: the following needs to be added to /etc/sudoers但是,使用此选项必须得到管理员的允许:以下需要添加到/etc/sudoers

 Defaults closefrom_override

With that in place, the command will work if -C is used:有了它,如果使用-C ,该命令将起作用:

$ 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). (这里给出了数字64 ,因为它大于错误消息中的63 )。

Try doing this in your shell :尝试在您的 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.当然,密码是通过它的stdin发送到sudo ,所以进程替换不是按照要求sudo完成的。 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 .我仍然希望它在这个特定的上下文中有所帮助,因为接受的答案有严重的缺点:您需要构建一个正确引用的字符串,然后生成一个辅助 shell 以在sudo解释它。

This makes it not only slow, but also risky due to shell injection, environment variables and so.这使得它不仅速度慢,而且由于 shell 注入、环境变量等原因而存在风险。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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