我编辑了 EC2 实例上的 sudoers 文件,可尝试运行 sudo 命令时,出现了语法错误。如何修复此问题?
上次更新时间:2021 年 9 月 17 日
我手动编辑了 Amazon Elastic Compute Cloud(Amazon EC2)实例上的 sudoers 文件。现在,在尝试运行 sudo su 命令或需要特权用户访问权限的命令时,我收到类似于下面这样的语法错误:
- “/etc/sudoers: syntax error near line xx”
- “sudo: parse error in /etc/sudoers near line xx”
- “sudo: no valid sudoers sources found, quitting”
- “sudo: unable to initialize policy plugin”
简短描述
手动编辑 /etc/sudoers 文件以更改 sudo 用户时,如果不慎在文件中添加了不符合要求的字符,就会发生此语法错误。结果可能是无法在受影响的实例上运行 sudo su,或者命令需要具有特权用户访问权限。要修复此语法错误,请停止实例,分离其根卷,将其挂载到恢复实例,将根卷挂载为辅助卷,然后还原对 sudoers 文件所做的更改。
警告:开始此流程之前,请注意以下几点:
- 停止和重新启动实例会擦除实例存储卷上的所有数据。确保备份实例存储卷上您想保存的所有数据。有关更多信息,请参阅确定实例的根设备类型。
- 停止和重新启动实例会更改实例的公有 IP 地址。在将外部流量路由到您的实例时,最佳做法是使用弹性 IP 地址而不是公有 IP 地址。
解决方法
注意:请勿使用文本编辑器(如 vi、nano 或 vim 等)在您可能会连接的并且正在运行的实例上手动编辑 sudoers 文件。请始终在您可能会连接的实例上运行 visudo 来编辑 /etc/sudoers 文件。Visudo 会在您编辑的过程中检查解析错误,一旦您因编辑在文件中引入问题,它会在您保存更改之前提醒您注意。
1. 打开 Amazon EC2 控制台。
2. 从导航窗格中选择实例,然后选择受损实例。
3. 依次选择操作、实例状态和停止。
4. 在描述选项卡中,选择根设备,然后选择 EBS ID。
5. 选择 操作,然后选择分离卷(/dev/sda1 或 /dev/xvda),再选择是,请分离。
6. 验证以确认状态为可用。
7. 在原始实例所在的可用区中启动新的 EC2 实例。这个新实例将成为您的“救援”实例。
8. 启动救援实例后,从导航窗格中选择卷,然后选择原始实例已分离的根卷。
9. 选择操作,然后选择连接卷。
10. 选择救援实例 ID (1-xxxx),然后输入设备名称(例如 /dev/sdf)。
11. 使用您的密钥对,通过 SSH 连接到救援实例。
12. 运行 lsblk 命令以验证所挂载卷的设备名称。
lsblk
示例输出如下。
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda 202:0 0 8G 0 disk
└─xvda1 202:1 0 8G 0 part /
xvdf 202:80 0 500G 0 disk
└─xvdf1 202:81 0 500G 0 part
13. 创建挂载目录,然后使用根权限进行挂载:
Amazon Linux、Ubuntu 和 Debian:
sudo mount /dev/xvdf1 /mnt
Amazon Linux 2、CentOS 7 或 8、SUSE Linux 12 和 RHEL 7.x 或 8.x:
sudo mount -o nouuid /dev/xvdf1 /mnt
在控制台中检查新连接的卷的挂载点。通常该挂载点是 /dev/xvdf1。
14. 执行 Chroot 以进入安装目录。
for dir in {/dev,/dev/pts,/sys,/proc}; do sudo mount -o bind $dir /mnt$dir; done
chroot /mnt
15. 使用 visudo 命令编辑 sudoers 文件。
visudo
有两个选项可用于编辑该文件:
选项 1:还原造成语法错误的相应更改。
选项 2:复制恢复实例中已知正确的 /mnt/etc/sudoers 文件,替换出问题的文件。
创建原始文件的备份。
sudo mv /mnt/etc/sudoers /mnt/etc/sudoers.backup
将文件复制到您的实例。
sudo cp /etc/sudoers /mnt/etc/sudoers
16. 编辑或替换 sudoers 文件后,卸载该卷。
for dir in {/dev,/dev/pts,/sys,/proc}; do umount /mnt$dir; done
sudo umount /mnt
17. 将卷附加到原始实例。将挂载点指定为 /dev/xvda 或 /dev/sda1,因为这是原始实例的根卷。
18. 启动原始实例。
19. 使用 SSH 连接到实例,并尝试运行 sudo 命令。