我正在为 Linux 制作一个桌面应用程序,该应用程序与一些 Ubuntu 系统文件交互。因此,在最终用户安装我的软件时,我需要生成一个文件,让/etc/sudoers.d/
一些脚本无需知道密码即可访问系统文件。用户将在安装过程中输入密码,但之后他们不必输入密码。在安装过程中,他们将运行give-sudo.sh
包含以下几行 Bash 代码的脚本:
echo '$USER ALL=(ALL) NOPASSWD: power_off.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: reboot.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: timeout_moss.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: timeout_default.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: set_next_os.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: boot_os_1.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: boot_os_2.sh' >> /etc/sudoers.d/moss-priv
echo '$USER ALL=(ALL) NOPASSWD: give_sudo.sh' >> /etc/sudoers.d/moss-priv
它应该创建一个名为的文件moss-priv
,并附加使我的脚本无需密码即可运行所需的行。我有 8 个脚本,所以我附加了 8 行代码。命令echo
运行正常,moss-priv
生成并显示其内容:
$USER ALL=(ALL) NOPASSWD: power_off.sh
$USER ALL=(ALL) NOPASSWD: reboot.sh
$USER ALL=(ALL) NOPASSWD: timeout_moss.sh
$USER ALL=(ALL) NOPASSWD: timeout_default.sh
$USER ALL=(ALL) NOPASSWD: set_next_os.sh
$USER ALL=(ALL) NOPASSWD: boot_os_1.sh
$USER ALL=(ALL) NOPASSWD: boot_os_2.sh
$USER ALL=(ALL) NOPASSWD: give_sudo.sh
问题就出在此时。脚本无需输入密码sudo
,而是打印堆栈跟踪,指出每行(1-8)都发生了错误。不仅如此,如果我sudo
出于任何原因尝试调用,它会显示“授权失败”和堆栈跟踪。因此,我完全失去了sudo
访问权限,甚至无法回去删除导致此问题的文件。我最终不得不重新安装整个操作系统才能使其恢复正常。
现在我已经sudo
回来了,我准备在弄清楚文件出了什么问题后再试一次moss-priv
。虽然我搞不清楚,但我觉得它看起来不错。帮忙?
我很高兴能找到这个问题的解决方案或好的替代方法。
错误:
\>>> /etc/sudoers.d/moss-priv: syntax error near line 1 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 2 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 3 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 4 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 5 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 6 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 7 <<<
\>>> /etc/sudoers.d/moss-priv: syntax error near line 8 <<<
\sudo: parse error in /etc/sudoers.d/moss-priv near line 1
\sudo: no valid sudoers sources found, quitting
\sudo: unable to initialize policy plugin1\\
更新:根据建议的修复,我有一个文件give_sudo.sh
:
echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/power_off.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/reboot.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/timeout_moss.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/timeout_default.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/set_next_os.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/boot_os_1.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/boot_os_2.sh" >> /etc/sudoers.d/moss-priv echo "$SUDO_USER ALL=(ALL) NOPASSWD: /home/jeremiahdgage/Desktop/MOSS/give_sudo" >> /etc/sudoers.d/moss-priv
其中一个脚本是这样的timeout_moss.sh
:
sudo sed -i 's/GRUB_HIDDEN_TIMEOUT=10/GRUB_HIDDEN_TIMEOUT=0.01/g' /etc/default/grub
当我运行它时,bash timeout_moss.sh
(当我在当前目录中时)它仍然要求我输入密码...为什么?
答案1
echo '$USER ALL=(ALL) NOPASSWD: power_off.sh' >> /etc/sudoers.d/moss-priv
此后,文件看起来不太好。您需要提供完全限定文件名(下面我假设/sbin/power_off.sh
)。此外,$USER
单引号中的 不会展开,它会以文字形式进入文件$USER
;我猜测这不是你想要的。使用双引号并指定满的小路:
echo "$USER ALL=(ALL) NOPASSWD: /sbin/power_off.sh" >> /etc/sudoers.d/moss-priv
文件中的行将如下所示:
kamil ALL=(ALL) NOPASSWD: /sbin/power_off.sh
提示:
- 如果不可执行,则此操作将不起作用
/sbin/power_off.sh
。使用 使其可执行chmod
。 - 确保
$USER
按预期展开。如果您的安装脚本运行sudo
后,您可能需要$SUDO_USER
(请参阅man 8 sudo
)。无论如何,建议在写入文件之前检查扩展值是否合理。 使用这里的文件(不带引号单词因为您想要
$SUDO_USER
扩展)以更优雅的方式写入文件。此示例将重新创建文件:cat >/etc/sudoers.d/moss-priv <<EOF $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/power_off.sh $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/reboot.sh $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/timeout_moss.sh $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/timeout_default.sh $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/set_next_os.sh $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/boot_os_1.sh $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/boot_os_2.sh $SUDO_USER ALL=(ALL) NOPASSWD: /sbin/give_sudo.sh EOF
- 注意
sudoers
允许您指定整个目录(通过其完整路径,它应该以 开头/
并以 结尾/
)。将脚本移动到专用目录,您只需在 中添加一行即可/etc/sudoers.d/moss-priv
。但是,如果您需要通过 访问您的工具PATH
,请记住sudo
可以使用单独的PATH
。 - 在您的测试中,首先打开一个提升的shell(例如
sudo su -
)并一直保持打开状态。在常规 shell 中测试sudo
更改后是否有效。如果您失去sudo
访问权限,请使用提升的 shell 来解决问题(在您的情况下,删除/etc/sudoers.d/moss-priv
应该可以)。 - 如果远程工作,请在测试中使用
tmux
或screen
作为普通用户,并从那里打开提升的 shell。这样,即使您在要修复访问sudo
权限的最关键时刻暂时失去连接,shell 仍会存活。您将能够跳转到提升的 shell,而无需sudo
重新连接到tmux
/screen
。
答案2
尝试使用双引号:
echo "$USER ALL=(ALL) NOPASSWD: power_off.sh" >> /etc/sudoers.d/moss-priv
因此该$USER
变量将被其内容替换。单引号可防止变量被解释。