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

Jac*_*ack 168 command-line bash sudo

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

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

sudo echo "options drm_kms_helper poll=N">/etc/modprobe.d/local.conf
Run Code Online (Sandbox Code Playgroud)

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

bash: /etc/modprobe.d/local.conf: Permission denied
Run Code Online (Sandbox Code Playgroud)

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

sudo echo N> /sys/module/drm_kms_helper/parameters/poll
Run Code Online (Sandbox Code Playgroud)

系统再次回应:

bash: /sys/module/drm_kms_helper/parameters/poll: Permission denied
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

sha*_*anu 206

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

sudo -i
Run Code Online (Sandbox Code Playgroud)

然后你可以使用重定向

echo N> /sys/module/drm_kms_helper/parameters/poll
Run Code Online (Sandbox Code Playgroud)

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

sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"
Run Code Online (Sandbox Code Playgroud)

  • 好的,如果是这种情况,那么请更新您的答案以反映运行 echo 仅在这种情况下是一个问题。 (4认同)

Ser*_*gey 82

输出重定向由调用命令的 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
Run Code Online (Sandbox Code Playgroud)

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


Unt*_*led 66

您可以使用这样的tee命令:

sudo tee /sys/module/drm_kms_helper/parameters/poll <<<10
Run Code Online (Sandbox Code Playgroud)

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

echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/poll
Run Code Online (Sandbox Code Playgroud)

如果您想追加而不是覆盖目标文件的情况——也就是说,要使tee行为类似于>>而不是>——您可以使用tee -a.

  • +1 以 root 身份登录对于手动工作来说是个坏主意,对于脚本任务来说*真的* 坏主意。 (4认同)
  • 另外,如果你不希望它也打印到​​ `stdout`,`sudo tee /sys/module/drm_kms_helper/parameters/poll &gt; /dev/null`。 (2认同)

koj*_*iro 17

我在这里没有看到的一种方法是在它自己的 shell 中简单地执行整个命令行。该sudo联机帮助页给出了这种方法的一个例子:

制作 /home 分区中目录的使用列表。请注意,这会在子 shell 中运行命令以使 cd 和文件重定向工作。

$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
Run Code Online (Sandbox Code Playgroud)


小智 5

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

temp=$(mktemp)
echo "Hello, world!" > $temp
sudo cp $temp /etc/wherever
Run Code Online (Sandbox Code Playgroud)


Cir*_*郝海东 5

sudo dd of=

根据需要附加:

echo inbytes | sudo dd of=outfile oflag=append conv=notrunc
Run Code Online (Sandbox Code Playgroud)

或从头开始重新创建文件:

echo inbytes | sudo dd of=outfile
Run Code Online (Sandbox Code Playgroud)

优点:

有效是因为 sudo 将 stdin 转发到命令。