如何修复运行 sudo 命令时 Amazon EC2 或 Lightsail 实例上的 sudo 错误?
我在 Amazon Elastic Compute Cloud (Amazon EC2) 或 Amazon Lightsail 实例上更改了 /etc/sudoers 文件的所有权或删除了该文件。现在,我在运行 sudo 命令时收到错误。
简短描述
如果删除或错误配置了 /etc/sudoers 文件,您可能会收到以下语法错误或 sudo 错误:
- "sudo: /etc/sudoers is owned by uid 1000, should be 0"
- "sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set"
- "sudo: unable to open /etc/sudoers: No such file or directory"
- "sudo: no valid sudoers sources found, quitting"
- "sudo: error initializing audit plugin sudoers_audit"
如果您收到上述错误之一,则无法向用户或用户组授予系统资源的访问权限。要修复 Amazon EC2 或 Lightsail 上的 /etc/sudoers 和 /usr/bin/sudo 文件,请使用用户数据或启动脚本修改文件权限。或者,将根磁盘连接到救援实例以手动进行更改。
**注意:**如果您删除了 /etc/sudoers 文件,则必须使用用户数据脚本来重新创建该文件。
解决方法
**注意:**如果您在运行 AWS 命令行界面 (AWS CLI) 命令时收到错误,请参阅 AWS CLI 错误故障排除。此外,请确保您使用的是最新版本的 AWS CLI。
使用用户数据或启动脚本修改文件权限
要解决 "owned by uid 1000" 或 "must be owned by uid 0" 错误消息,必须修改 /etc/sudoers 和 /usr/bin/sudo 文件权限。
对于 Amazon EC2 实例,请完成以下步骤以使用用户数据脚本修改文件权限:
-
打开 Amazon EC2 控制台。
-
在导航窗格中,选择 Instances(实例),然后选择 EC2 实例。
-
选择 Instance state(实例状态),然后选择 Stop Instance(停止实例)。
-
选择 Actions(操作),然后选择 Instance settings(实例设置)。
-
选择 Edit user data(编辑用户数据)。
-
输入以下脚本:
Content-Type: multipart/mixed; boundary="//" MIME-Version: 1.0 --// Content-Type: text/cloud-config; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="cloud-config.txt" #cloud-config cloud_final_modules: - [scripts-user, always] --// Content-Type: text/x-shellscript; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="userdata.txt" #!/bin/bash # To fix error sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set. use below commands chown -R root:root /usr/bin/sudo chmod 4755 /usr/bin/sudo # to fix below sudo errors: #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 chown -R root:root /etc/sudoers chown -R root:root /etc/sudoers.d/ sudo service sshd restart --//-- -
启动实例,然后等待其通过状态检查。
-
连接到实例,然后运行以下命令来验证 /etc/sudoers 和 /usr/bin/sudo 文件的权限是否正确:
sudo ls -la /etc/sudoers sudo ls -la /usr/bin/sudo以下输出示例显示了正确的权限:
$sudo ls -la /etc/sudoers /usr/bin/sudo -r--r----- 1 root root 1714 Jun 25 13:38 /etc/sudoers -rwsr-xr-x 1 root root 281624 Jun 27 2023 /usr/bin/sudo
对于 Lightsail 实例,请完成以下步骤以使用启动脚本修改文件权限:
-
打开 Lightsail 控制台。
-
选择 Snapshots(快照),然后选择您的实例快照。
-
选择 Actions(操作),然后选择 Create new instance(创建新实例)。
-
在 Optional(可选)下,选择 + Add launch script(+ 添加启动脚本)。
-
输入以下启动脚本:
#!/bin/bash # To fix error sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set. use below commands chown -R root:root /usr/bin/sudo chmod 4755 /usr/bin/sudo # to fix below sudo errors: #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 chown -R root:root /etc/sudoers chown -R root:root /etc/sudoers.d/ sudo service sshd restart --//-- -
选择 Create instance(创建实例)。
-
连接到实例,然后运行以下命令来检查 /etc/sudoers 和 /usr/bin/sudo 文件的权限:
sudo ls -la /etc/sudoers sudo ls -la /usr/bin/sudo以下输出示例显示了正确的权限:
$sudo ls -la /etc/sudoers /usr/bin/sudo -r--r----- 1 root root 1714 Jun 25 13:38 /etc/sudoers -rwsr-xr-x 1 root root 281624 Jun 27 2023 /usr/bin/sudo
将根磁盘连接到救援实例
配置实例以进行停止和启动
**注意:**当停止或启动某个实例时,该实例的公有 IP 地址将发生变化。最佳做法是使用弹性 IP 地址(而不是公有 IP 地址)将外部流量路由到您的实例。如果您使用的是 Amazon Route 53,则在公有 IP 地址发生变化时可能需要更新 Route 53 DNS 记录。
在停止和启动实例之前,请执行以下操作:
- 如果您的实例使用实例存储,则将实例存储上的卷数据保存到永久存储。例如,您可以将数据保存到 Amazon Elastic Block Store (Amazon EBS) 卷或 Amazon Simple Storage Service (Amazon S3) 存储桶。
**重要事项:**当您停止实例时,Amazon EC2 会删除实例存储数据。 - 创建 Amazon EBS 卷的快照。如果您遇到问题,则可以使用该快照来还原您的实例。
- 暂时将实例从其 Amazon EC2 Auto Scaling 组中移除,以免在停止实例时意外终止该实例。
**注意:**EC2 Auto Scaling 可能会根据您的缩减保护设置终止自动扩缩组中已停止的实例。使用 Amazon EMR、AWS CloudFormation 或 AWS Elastic Beanstalk 启动的实例可能位于自动扩缩组中。 - 将实例关闭行为设置为 Stop(停止),确保实例在您停止时不会终止。
将根磁盘连接到救援实例
完成以下步骤:
-
从同一可用区内具有相同 Linux 操作系统 (OS) 版本的亚马逊机器映像 (AMI) 中启动恢复实例。
-
使用新的 SSH 密钥对连接到恢复实例。
-
运行以下命令以更改为根用户:
sudo su -
要确定块设备名称和分区,请从恢复实例运行以下命令:
lsblk输出示例
[root ~]$ 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 101G 0 disk └─xvdf1 202:81 0 101G 0 part xvdg 202:96 0 30G 0 disk在上述示例中,设备名称为 xvda 和 xvdf 的卷是分区卷,而 xvdg 不是分区卷。
如果卷已分区,请运行以下命令来挂载分区 /dev/xvdf1,而不是原始设备 /dev/xvdf:mount -o nouuid /dev/xvdf1 /mnt如果您使用基于 AWS Nitro System 构建的实例,则卷设备名称使用 /dev/nvme[0-26]n1 格式。运行以下命令将分区挂载到 /mnt 目录:
mount -o nouuid /dev/nvme1n1p1 /mnt**注意:**请将 /dev/nvme1n1p1 替换为通过 lsblk 命令确定的设备名称。有关详细信息,请参阅 Amazon EC2 实例上卷的设备名称。
-
要从工作实例中复制 /etc/sudoers 文件作为备份,请运行以下命令:
cp /etc/sudoers /mnt/etc/sudoers.bak -
要在 /mnt 目录中创建 chroot 环境,请运行以下命令:
for i in dev proc sys run; do mount -o bind /$i /mnt/$i; done; chroot /mnt
上述示例从原始根文件系统中绑定挂载 /dev、/proc、/sys 和 /run 目录。此配置允许在 chroot 环境中运行的进程访问这些系统目录。 要编辑 /etc/sudoers 文件,请在 chroot 环境中运行以下命令:
visudo
确保该文件具有以下默认设置:
# This file MUST be edited with the 'visudo' command as root. # Please consider adding local content in /etc/sudoers.d/ instead of # directly modifying this file. # See the man page for details on how to write a sudoers file. Defaults env_reset Defaults mail_badpass Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin" # Host alias specification # User alias specification # Cmnd alias specification # User privilege specification root ALL=(ALL:ALL) ALL # Members of the admin group may gain root privileges %admin ALL=(ALL) ALL # Allow members of group sudo to execute any command %sudo ALL=(ALL:ALL) ALL # See sudoers(5) for more information on "#include" directives: #includedir /etc/sudoers.d
**注意:**visudo 命令会锁定 sudoers 文件。
如果您在运行上述命令时收到错误,请运行以下 diff 命令将 /etc/sudoers 文件与新文件 /etc/sudoers.bak 进行比较:
diff /etc/sudoers /etc/sudoers.bak
**注意:**如果您在编辑文件之前没有进行自定义更改,请将 /etc/sudoers.bak 文件恢复为 /etc/sudoers。 要退出 chroot 环境,请运行以下命令:
exit
- 要卸载根卷,请运行以下命令:
umount -fl /mnt
- 将作为辅助卷连接的根卷与恢复实例分离。然后,使用步骤 2 中的设备名称将其重新连接到原始实例。
- 启动原始实例,然后运行以下命令确认 sudo 命令是否正常运行:
sudo su
使用用户数据修改文件内容或重新创建文件
**注意:**要使用以下故障排除方法,必须为根用户设置密码。
重新创建文件
要以根用户身份访问实例以便重新创建文件,请完成以下步骤:
-
打开 Amazon EC2 控制台。
-
在导航窗格中,选择 Instances(实例),然后选择实例。
-
选择 Instance state(实例状态),然后选择 Stop Instance(停止实例)。
-
在 Stop instance?(停止实例?)下,选择 Stop(停止)。
-
选择 Actions(操作),然后选择 Instance settings(实例设置)。
-
选择 Edit user data(编辑用户数据)。
-
输入以下脚本为根用户设置临时密码:
Content-Type: multipart/mixed; boundary="//" MIME-Version: 1.0 --// Content-Type: text/cloud-config; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="cloud-config.txt" #cloud-config cloud_final_modules: - [scripts-user, always] --// Content-Type: text/x-shellscript; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="userdata.txt" #!/bin/bash chpasswd <<<"root:root" --//**重要事项:**此密码使用纯文本传递密钥,并不安全。完成故障排除步骤后,请务必移除根用户的临时密码。
-
启动实例,然后以 ec2-user 身份登录。
-
要重新创建 /etc/sudoers 文件,请运行以下 pkexec 命令:
pkexec /usr/sbin/visudo -
输入根用户密码,然后使用以下值修改 /etc/sudoers 文件:
# This file MUST be edited with the 'visudo' command as root. # # Please consider adding local content in /etc/sudoers.d/ instead of # directly modifying this file. # # See the man page for details on how to write a sudoers file. # Defaults env_reset Defaults mail_badpass Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" # Host alias specification # User alias specification # Cmnd alias specification # User privilege specification root ALL=(ALL:ALL) ALL # Members of the admin group may gain root privileges %admin ALL=(ALL) ALL # Allow members of group sudo to execute any command %sudo ALL=(ALL:ALL) ALL # See sudoers(5) for more information on "#include" directives: #includedir /etc/sudoers.d
- 运行 sudo 命令以验证 sudo 是否正常运行。
- 停止实例。
删除用户数据脚本
要使用 Amazon EC2 控制台删除用户数据值(包括根用户密码),请完成以下步骤:
- 打开 Amazon EC2 控制台。
- 在导航窗格中,选择 Instances(实例),然后选择实例。
- 选择 Actions(操作),然后选择 Instance settings(实例设置)。
- 选择 Edit user data(编辑用户数据),然后删除所有用户数据。
要使用 AWS CLI 删除用户数据值(包括根用户密码),请运行以下 modify-instance-attribute 命令:
aws ec2 modify-instance-attribute --instance-id example-instance-id --user-data Value=""
**注意:**请将 example-instance-id 替换为您的实例 ID。
要验证是否已移除用户数据,请运行以下 describe-instance-attribute 命令:
aws ec2 describe-instance-attribute --instance-id example-instance-id --attribute userData
**注意:**请将 example-instance-id 替换为您的实例 ID。
删除用户数据后,启动实例。
