系列:服务器篇 / 第 8 节 数据截至:2026 H1(man-pages 6.18 / sudo 1.9.17p2 / doas 6.8.2 / systemd 257 run0)
招人那天,HR 给 root 办了张卡——全公司所有门、所有机房、所有服务器、所有数据库,全开。
然后你入职了,工号 1000,HR 给你办了张"3 楼 + 7 楼"的卡——刚好够你干活。
一个星期后,隔壁部门的小李要帮你看日志,HR 给他办了张"只读 + 7 楼 + 30 天到期"的卡。
又过了一个月,实习生小张来做毕业设计,HR 给他办了张"3 楼 + 仅 9-17 点"的卡。
Linux 权限,就是给每个账号发门禁卡。 root 是卡片最多的员工 #0,但你不会真的把 #0 的卡发给别人——丢卡风险太大。
这篇文章不教你 chmod 755,教你 如何给每个运维同事、每个服务、每条脚本,发"刚好够用"的卡。
发卡之前,HR 要先认识 4 类人。Linux 权限也一样——4 类账号:
| 员工 #0 | root | ||
| 正式员工 | 普通用户 | ||
| 部门 | 组 | /opt/project 写权限 | |
| 临时工 | 服务账号 |

关键点:不是所有人都要发卡。发多了 = 安全隐患;发少了 = 啥都干不了。HR 视角叫"最小权限"——够用就行。
$ cat /etc/passwd | head -7root:x:0:0:root:/root:/bin/bash # 员工 #0daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin # 系统服务(不允许登录)www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin # nginx 用的服务账号(uid 随发行版变,Debian/Ubuntu 是 33)sshd:x:128:65534::/run/sshd:/usr/sbin/nologin # SSH 守护进程(uid 动态分配,Docker 里默认 100)zhangsan:x:1000:1000:,,,:/home/zhangsan:/bin/bash # 你(Debian/Ubuntu 第 1 个正式员工)/etc/passwd 字段含义(7 个冒号分隔):
zhangsan | ||
/etc/shadow,权限 0640 root+shadow 组) | x | |
| UID | 1000 | |
| GID | 1000 | |
,,, | ||
/home/zhangsan | ||
/bin/bash |
💡 HR 视角:UID 1-999 是"没工牌的服务账号"——不允许登录、不能 SSH、只跑自己服务。这就是为啥 nginx 不能用 root 跑——被攻破 = 全公司门都被打开。
反例:手动改 /etc/passwd 改坏了
chmod 644 /etc/passwd # ✅ 正常(所有用户都能读,UID→用户名的映射靠这个)chmod 0600 /etc/passwd # ❌ 锁死!新登录用户的工具报"无法解析用户名"/etc/passwd必须所有用户可读(系统要用它把 UID 翻译成用户名,比如 ls -l 显示的 owner 名字)。改成 0600 后:
id/whoami 用的是 nscd 或 systemd-userdb 缓存ls -l 显示 UID 数字不显示名字、su 到别人失败、getent passwd xxx 查不到chmod 644 /etc/passwd 改回正解用 usermod / useradd / userdel,不要 vim /etc/passwd。
HR 给员工发卡有 4 种模式——对应 Linux 权限的 4 种机制:
| 主门禁卡 | rwx 基础位chmod 755) | /data/project | |
| 特殊门卡 | SUID / SGID / Sticky | /usr/bin/passwd | |
| 个人专属卡 | ACLsetfacl) | /data/report 写权限 | |
| 临时通行证 | sudovisudo) | systemctl restart nginx 不给 root |

每个文件/目录的"主卡"是 9 位 = 3 组(owner / group / others)× 3 动作(r 读 / w 写 / x 执行)。
$ ls -l /etc/passwd-rw-r--r-- 1 root root 3050 Jun 13 04:35 /etc/passwd # 注:实际大小/时间随系统变# ↑ ↑ ↑# | | others = r-- (只读)# | group = r-- (只读)# owner = rw- (读写)💡
-rw-r--r--这一列实际是 10 个字符(最左是文件类型-=普通文件/d=目录/l=链接,后 9 位才是 rwx)。很多人误以为是 9 位。
chmod 755 拆开看 = rwxr-xr-x = owner 全权,group 和 others 读+进。
目录的 rwx 含义跟文件不一样(HR 视角:"主门能进"vs"主门能看"):
r | ls) | |
w | 能增删文件 | |
x | 能进入目录cd) |
HR 视角的坑:给目录 644 =
r--r--r--,连 owner 都不能cd进去。目录最小权限是 755,文件最小可读是 644。
有时候需要"用这张卡时,临时拿 owner 的权限"——这就要 SUID。
| SUID | s | /usr/bin/passwd | ||
| SGID | s | /usr/bin/crontab | ||
| Sticky | t | /tmp |
chmod 4755 /usr/bin/myapp # 4 = SUID,755 = rwxr-xr-xchmod 1777 /tmp # 1 = Sticky;同理 2=SGID 4=SUID,4755=SUID+rwxr-xr-xHR 视角的坑:乱加 SUID = 给有漏洞的程序发万能门禁卡。SUID 是 1971 年的老设计,80% 场景能用 sudo 替代。默认不要用。
rwx 三件套只能给"owner / group / others"三类人——但 zhangsan 跟 lisi 权限要不一样怎么办? ACL 解决。
# 526 临时需要写 /data/reportsetfacl -m u:zhangsan:rw- /data/report# lisi 只需要读setfacl -m u:lisi:r-- /data/report# 查getfacl /data/report# user:zhangsan:rw-# user:lisi:r--ACL 优先级规则(man acl(5) 权威):
mask:r-- 时所有 user/group 类 ACL 条目实际最多只有 r--chmod 改 group 位时实际改的是 mask——所以改 ACL 用 setfacl,别顺手 chmodmask 的坑——给了 rw- 但只有 r 生效:
# 给 zhangsan 写权限setfacl -m u:zhangsan:rw- /data/report# 但 mask 只有 r--(继承自原来的 group:r--)getfacl /data/report# user:zhangsan:rw- # 写了 rw-# mask::r-- # 但 mask 卡住了 → 实际只有 r--# 修:把 mask 也放开setfacl -m m::rw- /data/report# 现在 zhangsan 真正有 rw- 了适合场景:多用户共享目录、临时给脚本用户开权限、容器多进程共享数据。80% 场景用不到——只有团队协作时才上。
su - 切 root = 把 #0 的卡借给别人用(丢卡风险大)。sudo = 按需发临时通行证——HR 视角叫"用完即还"。
su - | sudo | |
|---|---|---|
visudo 救命特性(永远用 visudo,不要 vim /etc/sudoers):
最小可用 sudoers 写法:
# /etc/sudoers.d/ops-team# 让 ops 组成员能 sudo 所有命令%ops ALL=(ALL:ALL) ALL# 让 zhangsan 只能重启 nginx,不要密码zhangsan ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx# 让 lisi 能看日志但不能改lisi ALL=(root) NOPASSWD: /usr/bin/tail, /usr/bin/less, /usr/bin/journalctl⚠️ 2026 H1 注意:sudo 1.9.17p2(2025-07-26 发布)修了 CVE-2025-32462(host 提权)+ CVE-2025-32463(chroot 提权)。保持 sudo 最新。
HR 发卡的思路不是一成不变的——54 年前发一张万能卡,54 年后变成 N 张细分工卡。每一代补丁解决一个"rwx 不够"的问题。
1971:rwx 三件套——Unix 最早设计。HR 视角:"读、写、执行"3 个动作够了。
1999:sudo 1.0 —— Todd C. Miller 发布(至今仍是 sudo 上游 maintainer),告别"凡事必须 root"。HR 视角:门禁卡可审计、可撤回——今天发你、明天不给你就进不去。
2014:doas 简化版——OpenBSD 嫌 sudo 配置太复杂,搞了个 doas,配置文件就 5 行。Alpine Linux 默认用 doas(2026 H1 doas 6.8.2)。HR 视角:让"发卡"这件事变简单。
2024:run0 出现——systemd 257 引入,根本不用 SUID 攻击面。靠 transient systemd service 提权。HR 视角:把"门卡"扔了,改用"临时工牌"。
2026 现状(su / sudo / doas / run0 4 兄弟):
su | |||
sudo | /etc/sudoers | ||
doas | /etc/doas.conf | ||
run0 |
⚠️ run0 别名:systemd 团队给 Arch 用户配的
run0命令,实际上是systemd-run --pipe的 wrapper——没有 SUID 二进制、没有 setuid 调用。
run0 真正的新:跟 sudo 比,不用 SUID 不需要 root 二进制——靠 systemd 临时接管账号组 + pid 1 进程隔离。理论上更安全(没有 SUID 攻击面),但生态还在早期。
搞不清这 4 兄弟,审计服务器永远会有一个"莫名提权"。先看你的发行版默认装谁,再学那个。
HR 视角的"新员工入职"流程 = 4 步:建账号 → 配组 → 配 ACL → 配 sudo。Linux 视角就 1 个脚本搞定:
⚠️ 前提:脚本假设
ops/dev/readonly/sudo这 4 个组已经存在。首次部署前先执行:groupadd ops && groupadd dev && groupadd readonly # readonly 是只读访客组然后跑脚本。
#!/bin/bash# onboard.sh — 新员工入职自动开权限# HR 视角:建员工 → 分配部门 → 发部门门禁卡 → 发特权卡# 用法: sudo ./onboard.sh <username> <team>set -euo pipefailtrap 'echo "[ERROR] 入职失败,请人工介入"; exit 1' ERRUSERNAME="${1:?用法: $0 <username> <team>}"TEAM="${2:?用法: $0 <username> <team>}"# === 1. 建账号(HR 建员工) ===if ! id "$USERNAME" &>/dev/null; then useradd -m -s /bin/bash "$USERNAME" echo "建员工: $USERNAME"fi# === 2. 配组(HR 分配部门) ===case "$TEAM" in ops) usermod -aG ops,sudo "$USERNAME" ;; # 运维 + sudo dev) usermod -aG dev "$USERNAME" ;; # 开发者 readonly) usermod -aG readonly "$USERNAME" ;; # 只读访客 *) echo "未知团队: $TEAM"; exit 1 ;;esac# === 3. 配主门禁卡(rwx 基础位) ===chmod 700 /home/"$USERNAME"chown -R "$USERNAME":"$USERNAME" /home/"$USERNAME"# === 4. 配个人专属卡(ACL 精细控制) ===# 注:ACL 目标目录必须存在,否则 setfacl 会失败mkdir -p /opt/project[[ "$TEAM" == "dev" ]] && setfacl -m u:"$USERNAME":rwx /opt/project[[ "$TEAM" == "readonly" ]] && setfacl -m u:"$USERNAME":r-- /opt/project# === 5. 配临时通行证(sudo) ===# 注:默认 /etc/sudoers.d 不存在时也会被兜底;sudoers.d 内 fragment 必须 440if [[ "$TEAM" == "ops" ]]; then cat > /etc/sudoers.d/"$USERNAME" << EOF# 自动生成: $(date) by onboard.sh$USERNAME ALL=(root) NOPASSWD: /usr/bin/systemctl *, /usr/bin/tail, /usr/bin/journalctlEOF chmod 440 /etc/sudoers.d/"$USERNAME"fi# === 6. 初始密码(HR 给临时工牌) ===TEMP_PASS=$(openssl rand -base64 12)echo "$USERNAME:$TEMP_PASS" | chpasswdecho "✅ $USERNAME 入职完成,团队: $TEAM"echo "📋 初始密码: $TEMP_PASS(请尽快登录后修改)"30 行出头包含:建账号 / 配组 / rwx 基础位 / ACL 精细控制 / sudo 临时通行证 / 初始密码——5 个步骤对应 HR 入职流程的 5 个动作。
chmod 700 onboard.sh && chown root:root onboard.sh 后,平时用 sudo ./onboard.sh zhangsan dev。
学了上面这些,你已经能写出"最小权限"的发卡流程了。但下面这 5 个错,80% 的运维至少踩过 3 个:

chmod 777 | owner + group + ACL,不无脑 777 | ||
vim /etc/sudoers | 永远用 visudo | ||
/tmp | /tmp | ||
USER 1000 | |||
错 4(容器 root)—— 2024-2026 真实 CVE 升级版:
USER 1000,或用 rootless Podman。错 5(SUID)—— 1971 年的老设计,2024-2026 还在被滥用:
host 选项误用可让普通用户提权。保持 sudo 最新(2026 H1 推荐 1.9.17p2)。WSL 用户的 chmod 坑(HR 视角:"跨公司发卡"):
# WSL2 里 chmod 改 /mnt/c 下的 Windows 文件$ chmod 777 /mnt/c/Users/xxx/test.txt# 看起来成功了,但实际没用!Microsoft 官方解释:WSL 加 4 个 NTFS 扩展属性($LXUID/$LXGID/$LXMOD/$LXDEV),你没法给自己超出 Windows NTFS 的权限。来源:learn.microsoft.com/en-us/windows/wsl/file-permissions。正解:改 Windows NTFS ACL(icacls 命令),不要在 WSL 里 chmod。
先说结论:不但要学,而且比以往任何时候都值得学。
不是因为"基本功不能丢"这种正确废话。而是因为 AI 时代出现了两个变化:
变化一:发卡变快了,但审卡变重要了
现在用 ChatGPT 或 Claude 生成一个 sudoers 配置也就是一句话的事。但 AI 生成的 sudoers 常常有小问题——把 NOPASSWD 给得太宽、命令路径写错、引号没闭合。如果你不懂 Linux 权限,你根本看不出这些问题。AI 降低了写的门槛,但提高了审的门槛。
变化二:AI 成了发卡审计的好帮手
# 传统:手动找所有 SUID 文件,逐个审计find / -perm -4000 -type f 2>/dev/null# AI 时代:直接问 AI# "帮我审计这台服务器上所有异常的 SUID 文件,标出可疑的"# AI 可以:# 1. 自动跑 find 命令# 2. 对比"标准 SUID 清单"(passwd/sudo/ping/mount/su/umount 等)# 3. 标出不在标准清单里的 SUID 文件# 4. 给每个异常 SUID 文件解释风险这是 AI 真正擅长的事:机械检查 + 标准对比 + 风险评估。而"知道 SUID 干啥用"+"知道为啥危险"+"知道啥时候该用 sudo 替代"——这些是 AI 帮不了你的,只能靠你自己学。
所以我的建议是:
chmod/chown/setfacl/visudo 这 4 个核心命令够用关于 Linux 权限,最打动我的一句话来自最小权限原则:
「给一把刚好能开这扇门的钥匙,不要给一串能开整栋楼的钥匙。」
你公司发门禁卡,不会给保洁全公司所有门的卡,也不会给装修工只给 1 张客人临时卡。Linux 发卡也该是这样——root 是员工 #0 的万能卡,运维的本事是给每个人发"刚好够用"的卡。
今天就试试:
chmod 777 改成 chown + chmod 750useradd 专用账号 + visudo 授权find / -perm -4000,看看有几个 SUID 你不认识那一刻你会明白我在说什么。
| sudo | 1.9.17p2 | ||
| doas(OpenDoas) | 6.8.2 | ||
主流 Linux 发行版默认提权工具:
| Alpine 3.20+ | doas | |