在 Bash 中使用带重定向的 sudo 时如何解决“权限被拒绝”问题?

在 Bash 中使用带重定向的 sudo 时如何解决“权限被拒绝”问题?

当使用 sudo 允许编辑文件时,我经常会收到“权限被拒绝”的提示。

例如,我的鼠标抖动且反应迟钝,所以我想禁用轮询:

sudo echo "options drm_kms_helper poll=N">/etc/modprobe.d/local.conf

系统提示我输入密码,然后得到:

bash: /etc/modprobe.d/local.conf: Permission denied

因此,我尝试通过以下方式进行临时更改以禁用轮询:

sudo echo N> /sys/module/drm_kms_helper/parameters/poll

系统再次回复:

bash: /sys/module/drm_kms_helper/parameters/poll: Permission denied

有任何想法吗?

答案1

输出重定向(通过>操作符)由 shell 完成,而不是由回声. 您必须以 root 身份登录

sudo -i

然后你可以使用重定向

echo N> /sys/module/drm_kms_helper/parameters/poll

否则你可以使用 sudo 运行 bash 字符串

sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"

答案2

输出重定向由 shell 完成调用该命令的地方。那么,把所有东西分解成几部分,下面是发生的事情*:

  • shell 调用sudo echo "options drm_kms_helper poll=N",使用命令行执行sudo命令echo "options drm_kms_helper poll=N"

  • sudo 要求输入密码,打开超级用户 shell 并调用echo "options drm_kms_helper poll=N",运行echo命令并将其传递给"options drm_kms_helper poll=N"

  • echo 以root特权运行,将字符串打印到其标准输出。

  • echo命令终止,超级用户 shell 退出,sudo终止

  • 调用命令的 shell 收集输出并尝试将其重定向到/etc/modprobe.d/local.conf,该目录仅可由 root 写入。它收到“权限被拒绝”错误。

有关解决此问题的方法,请参阅@shantanu 的回答。


(*) - 虽然上述顺序有助于理解命令失败的原因,但实际上事情发生得有些混乱:原始 shell 注意到重定向,并在调用命令之前尝试打开文件进行写入sudo ...。当打开文件失败时,shell 甚至不会调用应该写入文件的命令(感谢 @PanosRontogiannis 指出这一点)。

这是一个快速测试:

$ touch ./onlyroot.txt
$ sudo chown root:root ./onlyroot.txt
$ sudo bash -c "whoami | tee who.txt" > onlyroot.txt
bash: onlyroot.txt: Permission denied

在上面的测试中,whoami | tee who.txt将要创建一个名为who.txt包含单词“root”的文件。但是,当调用 shell 中的输出重定向失败时,“who.txt”文件也会丢失,因为没有调用该命令。

答案3

您可以使用tee命令如下:

sudo tee /sys/module/drm_kms_helper/parameters/poll <<<10

或者如果它是命令的输出:

echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/poll

如果您遇到想要附加而不是覆盖目标文件的情况 - 即使其表现tee得像>>而不是>- 您可以使用tee -a

答案4

另一个选择是使用临时文件。这在 bash 脚本中很有用。

temp=$(mktemp)
echo "Hello, world!" > $temp
sudo cp $temp /etc/wherever

相关内容