本页面提供了有关使用 sudo
命令行实用程序、管理 sudoers
插件以及预防或修复出现的问题的技巧。
出现问题的原因
在每次执行 sudo
命令时,系统都会执行以下过程来验证 sudoers
文件:
- 系统会检查语法是否正确。
- 会对内容进行分析,以排除一些逻辑错误。
- 检查所有权和权限。
sudoers
文件的验证可能会因为以下任何错误而失败:
语法错误
更改 sudoers
文件时,您必须遵循特定的语法规则。如果与此语法存在任何偏差,包括但不限于字符缺失、多余字符或不当逗号,都可能导致文件无效。若文件无效,则无法使用 sudo
实用程序。
解决方案
解决方案是使用 visudo
实用程序修改 sudoers
文件。它会在保存文件内容之前进行验证,并在出现问题时发出通知。创建 visudo
实用程序就是为了以安全的方式修改该文件。
以下示例展示了正确的和错误的语法示例:
正确语法
user ALL=(ALL) ALL
错误语法
user ALL=(ALL), ALL
语法错误示例
$ sudo useradd username
/etc/sudoers:20:17: syntax error
user ALL=(ALL), ALL
^
逻辑错误
此类错误可能由以下任一原因引起:
- 对
sudoers
插件原则的误解。 - 与正确语法存在偏差。
不过,逻辑错误在验证期间不会被识别,因为它们不会违反语法规则,因此很难检测到。
解决方案
在修改文件时,您必须仔细阅读官方文档并遵循其原则。
Google 还建议使用 visudo
实用程序来修改 sudoers
文件,因为它可以检测某些类型的逻辑错误,例如:
- 未定义或未使用的别名
- 循环引用
- 重复条目
如果检测到任何问题,您会看到一条警告消息。
以下示例展示了逻辑正确和错误的样本:
逻辑正确
barbara ALL=(ALL:ALL) /usr/bin/ls
逻辑错误
barbara ALL=(4LL:ALL) /usr/bin/ls
^
barbara ALL=(ALL;ALL) /usr/bin/ls
^
bar6ara ALL=(ALL:ALL) /usr/bin/1s
^ ^
权限不正确
除了 sudoers
文件的内容导致的错误外,文件权限过多或所有权错误也可能会导致 sudo
实用程序运行失败。
解决方案
您会在执行失败的 sudo
命令的输出中看到这些错误的说明。仔细阅读错误消息说明,并进行必要的更正。
以下是正确文件权限和所有权的示例
$ ls -l /etc/sudoers
-r--r----- 1 root root 700 Jan 1 12:00 /etc/sudoers
$ sudo useradd username
以下示例显示了所有用户权限组具有冗余权限时显示的错误:
$ ls -l /etc/sudoers
-r--r---w- 1 root root 700 Jan 1 12:00 /etc/sudoers
$ sudo useradd username
sudo: /etc/sudoers is world writable
sudo: no valid sudoers sources found, quitting
sudo: error initializing audit plugin sudoers_audit
以下示例展示了所有权有误时显示的错误。在此示例中,该文件的所有者为 ID 不是 0
的用户(或者不是 root
的用户):
$ ls -l /etc/sudoers
-r--r----- 1 user user 700 Jan 1 12:00 /etc/sudoers
$ sudo useradd username
sudo: /etc/sudoers is owned by uid 1000, should be 0
sudo: no valid sudoers sources found, quitting
sudo: error initializing audit plugin sudoers_audit
如需详细了解 sudoers
文件的配置,请参阅
Sudoers 手册。
如需了解如何管理和使用 visudo
编辑器,请参阅 Visudo 手册。
问题的后果
sudoers
文件中的问题会造成负面影响,并可能影响整个系统的功能。
sudo
命令不再有效。这是
sudoers
文件中存在问题时的最常见后果。这样的后果是无法使用用户的提升权限,从而阻止用户在服务器上的活动。但是,更具破坏性且不可预测的后果是依赖于
sudo
命令的应用执行失败。在某些情况下,这可能会导致应用完全失败,进而导致意外行为、崩溃或数据丢失。另一个示例是,应用在操作系统启动序列期间调用sudo
命令并失败时。它可能会导致操作系统故障或者导致启动序列卡住。可能导致对系统的未经授权访问。
另一个风险在于,
sudoers
文件中的问题可能会导致对系统的未经授权访问。当sudoers
文件中的规则向某些用户或群组授予过多权限时,便可能会因逻辑错误而发生该问题。另外,也可能会因为系统所有者暂时停用或削弱系统防御机制来登录并解决问题而发生该问题。
出现问题时的恢复方法
如果由于 sudoers
文件问题而失去提升的用户权限或无法使用 sudo
命令,请使用超级用户账号进行恢复。
在类 Unix 操作系统中,超级用户是一个 ID 等于 0 的特殊用户账号,通常称为 root
。超级用户拥有对系统资源的完全访问权限,并且可以不受限制地执行任何管理任务。虽然通常认为以超级用户的身份与操作系统进行交互是不安全的,但这可能是执行某些任务(例如恢复 sudoers
文件)的唯一选项。
以超级用户身份直接登录会使操作系统面临风险。为了避免这种风险,Google 建议使用启动脚本功能,因为此脚本会以超级用户的身份执行。
详细了解 Compute Engine 启动脚本。
如需使用启动脚本恢复 sudoers
文件,请执行以下操作:
创建当前启动脚本(如果已在使用)的备份副本。备份方法取决于启动脚本的配置方式。
startup-script
如果脚本内容直接在元数据值中设置,您可以将脚本内容复制到 Cloud Storage 存储桶、本地文件或任何其他临时私有存储空间。
startup-script-url
如果脚本的内容已在远程存储中,并且使用了其网址,则只需临时移除
startup-script-url
元数据键即可停用当前启动脚本。使用以下命令序列更新启动脚本:
mv /etc/sudoers /etc/sudoers.backup.$(date +"%s") && echo "%google-sudoers ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers && chown 0:0 /etc/sudoers && chmod 0440 /etc/sudoers
详细了解上述命令的作用
-
mv /etc/sudoers /etc/sudoers.backup.$(date +"%s")
-
此命令会使用不同的名称为
/etc/sudoers
文件创建一个副本,并删除原始文件。新文件的名称末尾有一个时间戳,用于确保唯一性(例如sudoers.backup.1672527600
)。 -
echo "%google-sudoers ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers
-
此命令会创建之前删除的
/etc/sudoers
文件,其中仅包含一条规则,该规则允许有权访问虚拟机的获授权 Google Cloud 用户以任何系统用户的身份执行任何命令。默认情况下,此规则始终存在于其他文件/etc/sudoers.d/google_sudoers
中。 -
chown 0:0 /etc/sudoers
-
此命令会将
/etc/sudoers
文件的所有者设置为 ID 为0
的用户,并将一组所有者设置为 ID 为0
的群组。 -
chmod 0440 /etc/sudoers
-
此命令会将
/etc/sudoers
文件的权限设置为只读,并仅允许其所有者和所有者群组读取该文件。
-
停止虚拟机(如果正在运行)。重启虚拟机以触发启动脚本的执行。
连接到虚拟机,并修改损坏的
sudoers
文件以将其恢复。sudo visudo /etc/sudoers.backup.TIMESTAMP
保存更改,并将当前的
/etc/sudoers
文件替换为您刚刚修改的文件。sudo mv /etc/sudoers.backup.TIMESTAMP /etc/sudoers
确保使用
sudo
命令和提升权限的原始问题已修复。移除临时启动脚本,并恢复原始脚本(如果使用过)。
后续步骤
- 了解如何恢复无法访问或已损坏的虚拟机。
- 了解如何将现有磁盘添加到其他虚拟机。