在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
有任何想法吗?
输出重定向(通过>
运算符)由shell完成,而不是由echo完成 。 您必须以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"
输出重定向由调用该命令的shell完成。 所以,把所有东西都打成碎片,这里发生了什么*:
-
shell调用
sudo echo "options drm_kms_helper poll=N"
,它使用echo "options drm_kms_helper poll=N"
命令行执行sudo
命令 -
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
whoami | tee who.txt
将创建一个名为who.txt
的文件, who.txt
包含“root”一词。 但是,当调用shell中的输出重定向失败时,“who.txt”文件也会丢失,因为未调用该命令。
添加到Shantanu的答案:
…或者您可以使用这样的tee
命令:
sudo tee /sys/module/drm_kms_helper/parameters/poll <<<10
或者如果它是一个命令的输出:
echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/poll
我在这里没有提到的方法是简单地在自己的shell中执行整个命令行。 sudo
页本身就是这种方法的一个例子:
在/ home分区中创建目录的用法列表。 请注意,这会在子shell中运行命令以使cd和文件重定向工作。
$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
另一种选择是使用临时文件。 这在bash脚本中很有用。
temp=$(mktemp) echo "Hello, world!" > $temp sudo cp $temp /etc/wherever
sudo dd of=
要根据需要追加:
echo inbytes | sudo dd of=outfile oflag=append conv=notrunc
或者从头开始重新创建文件:
echo inbytes | sudo dd of=outfile
好处:
- 因为没有
/dev/null
重定向,所以比tee
更好 - 比
sh
更好,因为没有明确的子shell(但是重定向的隐式子shell) -
dd
有许多强大的选项,例如status=progress
来查看转移进度
因为sudo将stdin转发给命令而工作。