
sudo 命令允许你以另一个用户的身份运行程序,默认是 root 用户。每当任务需要管理员权限时,你都会用到它,例如管理软件包、服务、用户或系统配置文件。
本指南讲解如何在 Linux 上使用 sudo 命令,涵盖常用选项、sudoers 配置以及实际示例。
什么是 sudo
这个名字是 "su do" 的缩写,sudo 项目将其描述为一种授权委派机制:允许特定用户或用户组以 root 或其他用户的身份运行部分或全部命令。默认情况下,sudo 会记录成功与失败的执行尝试。
正是这种委派机制将 sudo 与共享 root 访问区分开来,后者产生的操作并不与个人普通账户绑定。使用 sudo 时,每个人通常用自己的密码进行身份验证,/etc/sudoers 中的规则决定他们可以运行哪些命令,日志会记录调用 sudo 的账户。这些规则可以授予完整的管理员权限,也可以只授予单条命令、别无其他。
sudo 记录的是它启动的命令,而不是在 sudo -i 或其他特权 shell 中输入的所有命令。该 shell 内部的命令只有在管理员启用了 I/O 日志时才会被记录。
安装 sudo
sudo 软件包在大多数 Linux 发行版中已预装。
要检查系统是否安装了 sudo,请运行:
sudo --version
如果未安装 sudo,你会看到 sudo: command not found 错误。要安装它,请以 root 用户身份运行以下命令。在启用了 root 账户的系统上,先用 su - 切换到 root;否则使用其他管理员账户或 root 恢复 shell。
在 Ubuntu、Debian 及其衍生版上安装 sudo
apt install sudo
在 Fedora、RHEL 及其衍生版上安装 sudo
dnf install sudo
将用户添加到 sudoers
默认情况下,在大多数 Linux 发行版上,授予 sudo 访问权限只需将用户添加到 sudoers 文件中定义的 sudo 组即可。该组成员可以 root 身份运行任何命令。该组的名称在不同发行版之间有所不同。
在 Fedora、RHEL 及其衍生版上,sudo 组名为 wheel。要将用户添加到该组,请运行:
usermod -aG wheel username
在 Ubuntu、Debian 及其衍生版上,sudo 组的成员被授予 sudo 访问权限:
usermod -aG sudo username
Ubuntu 中的 root 用户账户出于安全原因默认被禁用,官方建议用户使用 sudo 来执行系统管理任务。Ubuntu 安装程序创建的初始用户已是 sudo 组的成员。关于 Ubuntu 的具体细节(包括 adduser、drop-in 规则文件以及你可能遇到的错误),请参阅我们关于在 Ubuntu 中添加用户到 sudoers 的指南。
要允许特定用户仅以 sudo 身份运行某些程序,请将该用户直接添加到 sudoers 文件,而不是添加到组。使用 visudo 打开该文件:
sudo visudo
然后追加以下行,允许 linuxize 用户仅运行 mkdir 命令:
linuxize ALL = (root) /usr/bin/mkdir
visudo 打开哪个编辑器取决于 sudo 软件包的构建方式。当前 Debian、Ubuntu 和 Fedora 的构建都优先使用 nano。在 Debian 和 Ubuntu 上,软件包调用 /usr/bin/editor,因此你可以通过 alternatives 系统更改默认值:
sudo update-alternatives --config editor
当 sudoers 策略允许时,visudo 还会检查 SUDO_EDITOR、VISUAL 和 EDITOR 变量。匹配 ALL 的命令规则隐含 SETENV,而只授予 /usr/sbin/visudo 的规则必须显式添加 SETENV 或保留编辑器变量。为避免依赖该策略,可以打开 root 登录 shell 并在其中设置编辑器:
sudo -i
EDITOR
=
/usr/bin/vim visudo
如果你不小心进入了 vim,请参阅我们关于如何保存文件并退出 vim 编辑器的文章。
你也可以允许用户运行 sudo 命令而无需输入密码:
linuxize ALL = (ALL) NOPASSWD: ALL
如何使用 sudo
sudo 命令的一般语法为:
sudo
[
OPTION
]
... COMMAND
sudo 命令有许多控制其行为的选项,但最常见的是不带任何选项的基本形式。
要以 root 身份运行命令,请在命令前加 sudo:
sudo command
其中 command 是你想以提升的权限运行的命令。
在会话中首次使用 sudo 时,系统会提示你输入用户密码。身份验证通过后,sudo 会读取 /etc/sudoers 以验证用户是否拥有权限,然后以 root 身份执行命令。
与其在每个命令前都加 sudo,不如打开一个交互式 root shell 进行较长的会话。
sudo ls /root
[sudo] password for linuxize: . .. .bashrc .cache .config .local .profile
打开 root Shell
-i 选项启动一个 root 登录 shell,加载 root 的环境、主目录和 shell 配置:
-s 选项启动一个 root 交互式 shell,但不运行登录 shell,因此会保留更多当前环境:
sudo -i
你也可以通过运行 sudo su - 借助 su 命令进入 root shell,不过 sudo -i 一步就能给你相同的登录 shell。
sudo -s
使用 exit 或按 Ctrl+D 返回普通用户会话。
要查看当前用户被允许以 sudo 身份运行哪些命令,请使用 -l 选项:
列出 sudo 权限
要列出特定用户的权限,请传递 -U 标志并后跟用户名:
sudo -l
Matching Defaults entries for linuxize on server:
env_reset, mail_badpass, secure_path=...
User linuxize may run the following commands on server:
(ALL : ALL) ALL
身份验证成功后,sudo 会缓存你的凭据,这样下一条命令就不会再次提示。上游 sudoers 政策默认为五分钟,但发行版在构建软件包时可以选择不同的值。当前的 Debian 和 Ubuntu 软件包使用 15 分钟,而 Fedora 使用上游的五分钟默认值。管理员可以在 sudoers 配置中覆盖任一值。
sudo -l -U username
密码超时
缓存也是按终端的。sudo 为每个终端保留独立的时间戳记录,因此在某个 shell 中输入的密码不会延续到并排打开的第二个 shell。这种行为来自 timestamp_type 设置,其默认值为 tty。
要更改默认超时时间,请使用 visudo 打开 sudoers 文件:
添加以下行,将 10 替换为你想要的超时分钟数:
sudo visudo
要仅为特定用户设置超时,请使用:
Defaults timestamp_timeout = 10
-v 选项在不运行命令的情况下续期缓存的凭据,如果缓存已过期则先对你进行身份验证:
Defaults:user_name timestamp_timeout = 10
刷新 sudo 时间戳
在长脚本或构建开始时调用它,会开启一个新的超时周期,从而降低下一个特权步骤中出现密码提示的可能性。如果该周期已过期,后续的 sudo 命令仍会提示。
sudo -v
-N 选项是在 sudo 1.9.12 中新增的。在 sudo 1.9.12 及更新版本中,你可以通过将 -v 与 -N 和 -n 组合来测试是否已有有效凭据,而无需提示或延长缓存:
在缓存仍然有效时,该命令以状态 0 退出。一旦过期,sudo 会打印错误并以非零状态退出,而不是询问密码,这正是该检查可以安全在无值守环境下运行的原因。
sudo -N -n -v
要手动清除缓存的凭据,并强制 sudo 在下一次使用时提示输入密码,请运行:
使 sudo 时间戳失效
这在你完成特权会话并希望立即要求重新身份验证时很有用。
sudo -k
由于凭据是按终端缓存的,-k 只会清除你运行它的那个终端的记录。大写形式则会删除你账户的所有缓存凭据,无论是由哪个终端创建的:
存在一个常见的误解,认为 sudo 仅用于提供 root 权限。通过传递 -u 选项,你可以使用 sudo 以任意用户的身份运行命令。
sudo -K
以其他用户身份运行命令
在以下示例中,我们使用 sudo 以 richard 用户的身份运行 whoami 命令:
除了已经介绍的选项外,还有几个选项在脚本和日常管理中经常出现,值得了解:
sudo -u richard whoami
如果你尝试将输出重定向到一个当前用户没有写入权限的文件,你会收到 "Permission denied" 错误:
richard
常用 sudo 选项
这是因为 shell 在调用 sudo 之前先处理 > 重定向,因此重定向是以你的普通用户身份运行的,而不是 root。
如何使用 sudo 进行重定向
一种解决方案是使用 sudo sh -c 以 root 身份启动子 shell:
sudo
echo
"test"
> /root/file.txt
bash: /root/file.txt: Permission denied
另一种选择是将输出通过管道传给带 sudo 的 tee 命令:
同样的规则适用于所有 shell 运算符,而不仅仅是 >。在 sudo cat /etc/shadow | wc -l 中,只有 cat 以 root 身份运行,而管道和 wc 以你自己的用户身份运行。在 sudo cd /root 中,cd 是 shell 内建命令而非磁盘上的程序,因此 sudo 没有可执行的对象:
sudo sh -c
'echo "test" > /root/file.txt'
将整行包裹在 sh -c 中,会让所有内容都在 root 下运行:
echo
"test"
|
sudo tee /root/file.txt
运行管道与多条命令
在字符串周围使用单引号,这样你自己的 shell 不会动那些运算符,而是原样交给 root shell。
sudo: cd: command not found sudo: "cd" is a shell built-in command, it cannot be run directly. sudo: the -s option may be used to run a privileged shell. sudo: the -D option may be used to run a command in a specific directory.
运行 sudo vim /etc/hosts 会打开文件,但同时也会以 root 身份启动一个完整的编辑器,而该编辑器内部的任何插件、宏或 shell 转义也都会以 root 身份运行。-e 选项可以避免这一点,它也可通过 sudoedit 名称使用:
sudo sh -c
'cd /root && ls -l | wc -l'
sudo 会创建一个属于你的文件临时副本,以你的普通用户身份运行编辑器,并在你退出时将结果复制回原始位置。编辑器本身从不持有 root 权限。如果文件尚不存在,它会被创建。
使用 sudoedit 以 root 身份编辑文件
编辑器按 SUDO_EDITOR、VISUAL、EDITOR 的顺序选取,当三者都未设置时回退到 sudoers 政策中配置的列表:
sudo -e /etc/hosts
默认情况下,sudoedit 拒绝符号链接以及你自己可写入目录中的文件。sudoers 政策可以显式允许这些情况,但设备文件始终被拒绝。
如需可打印的快速参考,请参阅 sudo 速查表。
SUDO_EDITOR
=
nano sudo -e /etc/hosts
用户名不在 sudoers 文件中:该用户尚未被添加到 sudoers 组。以 root 身份登录并运行 usermod -aG sudo username(Ubuntu/Debian)或 usermod -aG wheel username(RHEL/Fedora),然后注销并重新登录以使组变更生效。
快速参考
sudo: unable to resolve host hostname:系统主机名与 /etc/hosts 中的条目不匹配。在 /etc/hosts 中为你的主机名添加一条记录(例如,在 Ubuntu 和 Debian 上为 127.0.1.1 hostname),然后重试。
| 选项 | 说明 |
|---|---|
sudo command | 以 root 身份运行命令 |
sudo -u user command | 以特定用户身份运行命令 |
sudo -i | 打开 root 登录 shell |
sudo -s | 打开 root shell(非登录) |
sudo -l | 列出当前用户的 sudo 权限 |
sudo -l -U user | 列出其他用户的 sudo 权限 |
sudo -v | 不运行命令即刷新缓存凭据 |
sudo -k | 使当前终端的缓存凭据失效 |
sudo -K | 删除所有终端的缓存凭据 |
sudo -n command | 以错误失败,而非提示输入密码 |
sudo -E command | 保留当前环境变量 |
sudo -b command | 在后台运行命令 |
sudo -H command | 将 HOME 设为目标用户的主目录 |
sudo -D dir command | 当 sudoers 允许 -D 时在指定目录运行 |
sudo sh -c '...' | 以 root 身份运行整条命令行(含管道与重定向) |
sudo -e file | 使用默认编辑器以 root 身份编辑文件 |
sudo visudo | 安全编辑 sudoers 文件 |
故障排查
sudo: command not found(使用 sudo -i 或 sudo -s 之后):root shell 可能使用了受限的 PATH,其中不包含你命令所在的目录。使用命令的完整路径(例如 /usr/local/bin/command),或运行 sudo env PATH="$PATH" command 以保留当前路径。当缺失的命令是 sudo 本身而非你所调用的程序时,请参阅我们关于修复 "sudo: command not found" 的指南。
sudo 和 su 有什么区别?sudo 以另一个用户(通常是 root)的身份运行单条命令,并且需要你自己的密码。su 完全切换到另一个用户账户,并需要该用户的密码。sudo 适用于一次性特权命令;su 用于完全切换用户会话。
如何使用 sudo 重新运行上一条命令?使用 sudo !!,!! 会展开为你 shell 历史中的上一条命令,sudo 会以提升的权限运行它。
常见问题
如何在不输入密码的情况下运行 sudo?在 sudoers 文件中添加一条 NOPASSWD 规则:linuxize ALL=(ALL) NOPASSWD: ALL。请参阅我们关于无密码运行 sudo 的指南。
sudo 会记住我的密码多久?当前的 Debian 和 Ubuntu 软件包默认 15 分钟,而 Fedora 使用上游的五分钟默认值。管理员可以通过 Defaults timestamp_timeout=N 更改超时,sudo -v 则在不运行命令的情况下续期缓存。
sudo 命令是 Linux 系统管理不可或缺的工具。它让你以提升的权限运行命令,同时通过避免直接 root 登录来保持系统安全。使用 sudo -l 检查你的权限,sudo -i 打开 root shell,完成后用 sudo -k 清除凭据缓存。
结论
Next · Part 12
How to Run Sudo Command Without Password