← 回目录
09 Week 02 · 权限和用户

sudo:为什么不直接用 root

「反正我有 root 密码,直接登 root 多省事」——这个想法在面试里会直接扣分。今天讲清楚为什么。

今天要敲的
$ sudo -l                          # 我有哪些 sudo 权限
$ sudo visudo                      # 改配置(别用 vi)
$ sudo tail -20 /var/log/secure    # sudo 操作都记在这
$ sudo -u nginx whoami             # 以别的用户身份执行

两个理由

这就是面试答案
为什么不直接用 root
① 可追溯
所有人都用 root,出了事查不出是谁干的——日志里只有一个 root。用各自的账号 sudo,/var/log/secure 里清清楚楚记着谁、什么时候、执行了什么
② 最小权限
给了 root 密码就是给了全部。用 sudo 可以精确到只允许某条命令——比如开发只能重启自己那个服务,别的一概不行。
③ 顺带的好处
sudo 这四个字母的过程,本身就是一次提醒:你正在做有风险的操作。长期泡在 root 里,手一滑就是事故。

sudo -l

先看自己有什么权限
列出当前用户的 sudo 权限
$ sudo -l
User devops may run the following commands on rocky:
    (ALL) ALL
    ↑ 意思是:可以以任何身份执行任何命令 —— 全权

接手一台陌生服务器时,sudo -l 是第一个该敲的命令之一——先搞清楚自己能干什么。

wheel

红帽系的 sudo 门票

昨天讲了 usermod -aG wheel。为什么加进这个组就能 sudo?因为 /etc/sudoers 里预置了一行:

默认配置
$ sudo grep -v "^#" /etc/sudoers | grep -v "^$" | grep wheel
%wheel  ALL=(ALL)       ALL
                     
% 表示组  在哪些主机  可以变成谁   能执行什么命令
发行版差异

红帽系(Rocky/RHEL/CentOS)用 wheel 组,Debian/Ubuntu 用 sudo 组。说对 wheel,又是一个「在红帽系干过」的信号。

visudo

今天最该记住的一条

永远不要用 vi 直接编辑 /etc/sudoers要用 visudo

visudo 多做了两件事
保存前做语法检查
写错了它会拦住你,问你要不要重新编辑。这是关键。
加锁
防止两个人同时改这个文件把彼此的改动覆盖掉。
改错了会怎样

/etc/sudoers 语法错误的后果是:系统里所有人都失去 sudo 权限,包括你自己。

这时候你没法 sudo 去修它——只能重启进单用户模式,或者用救援盘。生产服务器上这就是一次事故。

visudo 就是为了防止这件事存在的。

精确授权

sudo 真正的价值

最常见的需求:让开发能重启自己的服务,但不给他别的权限。

在 visudo 里加一行
# 允许 devops 用户免密重启 nginx,仅此一条
devops ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart nginx

# 允许 dev 组的人管理 nginx 的几个动作
%dev ALL=(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl status nginx
那一行怎么读
devops
对谁生效。前面加 % 就表示组。
ALL=
在哪些主机上生效。单机环境写 ALL 就行。
(ALL)
可以切换成哪个用户执行。ALL 表示任意。
NOPASSWD:
执行时不用输密码。给脚本或自动化用的时候必须加,否则会卡在密码提示上。
/usr/bin/systemctl restart nginx
允许执行的命令,必须写绝对路径。写相对路径会被绕过。

审计日志

谁在什么时候干了什么
sudo 的每一次使用都有记录
$ sudo tail -5 /var/log/secure
Sep  7 14:22:01 rocky sudo[3021]: devops : TTY=pts/0 ; PWD=/home/devops ;
    USER=root ; COMMAND=/bin/systemctl restart nginx
  ↑ 谁                                        ↑ 干了什么

这就是「可追溯」的实际样子。Day 03 说过 secure 记登录,今天你知道它也记 sudo。

顺带几个

常用变体
$ sudo -u nginx whoami        # 以 nginx 身份执行(不是变 root)
$ sudo -i                     # 切换成 root 的完整登录环境
$ sudo su -                   # 效果类似,老写法
$ sudo !!                     # 上一条命令加 sudo 重跑一遍(很好用)
sudo !! 值得单独记

敲了个命令被拒绝,不用重打,直接 sudo !!——两个感叹号代表"上一条命令"。这个小技巧一天能省你好几次重复输入。

今天的面试点

「为什么不直接用 root?」

一是可追溯/var/log/secure 里能查到谁在什么时候执行了什么;都用 root 的话查不出是谁。」

二是最小权限,可以在 sudoers 里精确授权,比如只允许开发重启某个服务,而不是把 root 密码给出去。」

「改 sudoers 用什么?」

visudo不能用 vi 直接改。因为它保存前会做语法检查——那个文件写错了会导致所有人都失去 sudo 权限,只能进单用户模式救。」

能说出后果的人,明显比只知道命令的人更可信。

今天的练习

敲完再走 · 约 12 分钟
  • sudo -l 看自己有哪些权限
  • sudo grep -v "^#" /etc/sudoers | grep -v "^$"(Day 05 学的过滤法),看真正生效的配置就那么几行
  • sudo tail -20 /var/log/secure,找找你今天敲过的 sudo 命令,看它是怎么记录的
  • sudo visudo 打开看看(不要改,直接 :q 退出),确认它用的就是 vim 那套操作
  • 试试 sudo -u nginx whoami,理解 sudo 不只是"变 root"
  • 故意敲个需要权限的命令比如 cat /etc/shadow,被拒后用 sudo !! 重跑
明天预告

Day 10 是第二周的复习日。不学新东西,自己制造一个权限故障再修好——把这一周的 ls -lidchmodchown 串成一条排查链。