CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Linux 服务器入门/课时/用户与 sudo
RawBlame
课时目录12 节

Linux 服务器入门

  1. 01Linux 是什么
  2. 02Shell 与 Bash
  3. 03文件系统与权限
  4. 04常用命令
  5. 05编辑器与配置
  6. 06进程与服务
  7. 07用户与 sudo
  8. 08包管理
  9. 09SSH 与密钥
  10. 10防火墙与端口
  11. 11部署 CodeRoadMap
  12. 12综合练习

用户与 sudo

用户组、sudoers、最小权限。

25 分钟

用户与 sudo

这一课你将能做到

  1. 读懂 /etc/passwd 一行,用 id、groups、whoami 说明当前用户是谁、属于哪些组、UID 是多少
  2. 创建 deploy 专用部署用户并加入 sudo 组(Ubuntu)/ wheel 组(RHEL),验证其 sudo 权限
  3. 说出「为什么服务要用专用低权限用户跑」,并把 CodeRoadMap 的部署目录属主对齐到运行用户

为什么要学

Linux 是多用户系统,权限体系(文件课)全部围绕「用户和组」展开。生产事故的两大源头——误操作(root 手滑 rm -rf 无可挽回)和权限混乱(服务全用 root 跑,一旦被入侵即整机沦陷)——根治手段都是同一件事:给每个身份最小权限。

面试里 su 与 sudo 的区别、/etc/passwd 七段含义、「为什么不用 root 跑服务」是高频三连;实战里你每天 SSH 登录用哪个用户、服务以谁的身份运行、谁能 sudo,决定这台机器的安全水位。本课把身份这件事一次讲透。

先建立图像

用户在系统里的样子

用户(UID)          组(GID)              身份三问
──────────────────────────────────────────────────────
root    UID=0      拥有至高权限            我是谁?    whoami / id
系统用户 UID=1-999  服务专用(www/mysql)   我在哪些组?groups / id -Gn
普通用户 UID=1000+  人用的(deploy)       我能干什么?sudo -l / 权限位

每个文件都挂着「属主+属组」,每个进程都带着「uid+gid」——上一课 ps aux 第一列的那个名字,就是本课的主角。

身份相关的四个关键文件

/etc/passwd   用户名册(人人可读)  deploy:x:1001:1001::/home/deploy:/bin/bash
/etc/shadow   密码哈希(仅 root)  deploy:$6$xxxx:19xxx:0:99999:7:::
/etc/group    组名册               sudo:x:27:deploy
/etc/sudoers  sudo 白名单          只用 visudo 编辑,语法错了会锁死 root

/etc/passwd 七段读法:

deploy : x : 1001 : 1001 :  : /home/deploy : /bin/bash
  │    │    │      │    │       │           └ 登录 shell(/usr/sbin/nologin=禁止登录的系统用户)
  │    │    │      │    │       └ 家目录
  │    │    │      │    └ 备注字段(GECOS,常空)
  │    │    │      └ 主组 GID
  │    │    └ UID
  │    └ 密码占位符(真哈希在 shadow)
  └ 用户名

跟着做

步骤 1:搞清「我现在是谁」

whoami                # 用户名
id                    # uid=1001(deploy) gid=1001(deploy) groups=1001(deploy),27(sudo)
groups                # 只是组名列表
who                   # 当前登录在机器上的都有谁(pts/0 终端,几点连的)
sudo -l               # 我能用 sudo 干什么(列出白名单;普通用户先输自己密码)

id 是最信息量大的一个命令:一条输出回答「我是谁+我的组」两问。

步骤 2:读 /etc/passwd,认识系统用户

cat /etc/passwd | head -5      # 前几个都是系统用户(root、daemon、bin…)
grep -E "^(root|www|mysql|deploy)" /etc/passwd    # 看关键用户的 UID 和 shell
awk -F: '$3 >= 1000 {print $1, $3}' /etc/passwd   # 只列普通用户(UID>=1000)

注意观察:mysql、www 这类系统用户的 shell 是 /usr/sbin/nologin——它们存在,但永远不该有人以它们登录,这正是「服务专用用户」的形态。

步骤 3:创建 deploy 部署用户(Ubuntu 路径)

# adduser 交互式(推荐,自动建家目录/设密码/配 shell):
sudo adduser deploy
# 按提示输两次密码,其他信息一路回车

# 验证:
id deploy
ls -ld /home/deploy          # 家目录已建,属主正确

# 加入 sudo 组(Ubuntu 的 sudo 白名单组):
sudo usermod -aG sudo deploy
id deploy                    # groups 里多出 27(sudo)

# 验证 sudo 生效:切到 deploy 试一次
su - deploy                  # 输 deploy 的密码;- 表示加载完整登录环境
sudo whoami                  # 输 deploy 密码 → root,说明 sudo 通了
exit                         # 回到原用户

步骤 4:RHEL/CentOS 差异(会认即可)

# RedHat 系的对应操作(在有 sudo 的 Rocky/CentOS 上):
# useradd deploy && passwd deploy        # useradd 不交互,passwd 单独设密码
# usermod -aG wheel deploy               # RHEL 的管理员组叫 wheel,不是 sudo
# groups deploy                          # 确认 wheel 已在

一张对照表:

事项Ubuntu/DebianRHEL/Rocky/CentOS
管理员组sudowheel
建用户adduser(友好)useradd + passwd
默认用户Ubuntu 初始用户RHEL 默认只有 root

步骤 5:su 与 sudo 的对比实验

# 场景 A:su —— 变成另一个人(要「对方」的密码)
sudo -i                      # root 身份的登录 shell(输入的是【当前用户】的 sudo 密码)
whoami                       # root
exit

su deploy                    # 变成 deploy(输入的是【deploy】的密码)
whoami
exit

# 场景 B:sudo —— 以别人身份执行一条命令(要「自己」的密码,有审计记录)
sudo whoami                  # root,但你的身份没变
sudo -u www touch /tmp/t1    # 以 www 身份建文件(文件课用过)
ls -l /tmp/t1                # 属主是 www

核心区别一句话:su 是「换人」(整段会话变身),sudo 是「借权」(单条命令借力)。sudo 的每次使用都记进日志(sudo grep sudo /var/log/auth.log),这就是审计能力——生产优先 sudo。

步骤 6:给 CodeRoadMap 落地「身份模型」

生产标准:人用 deploy 登录操作,服务用 www(或同名专用用户)运行,两者通过组协作。

# 假设服务运行用户是 www(宝塔默认),部署操作用户是 deploy
sudo mkdir -p /www/wwwroot/coderoadmap/{logs,conf}
sudo useradd -r -s /usr/sbin/nologin www 2>/dev/null || true   # -r 系统用户,禁止登录

# 目录协作:www 拥有并读写,deploy 加入 www 组以便维护
sudo chown -R www:www /www/wwwroot/coderoadmap
sudo chmod -R 750 /www/wwwroot/coderoadmap
sudo usermod -aG www deploy                  # deploy 进 www 组

# 验证矩阵(文件课的 sudo -u 验证法):
sudo -u www touch /www/wwwroot/coderoadmap/logs/ok.log     # www 能写日志 → 服务可运行
sudo -u deploy touch /www/wwwroot/coderoadmap/logs/d.log   # deploy 经组权限也能写
ls -l /www/wwwroot/coderoadmap/logs/

以后 SSH 课会把 root 的密码登录关掉,所有人只走 deploy + 密钥——身份模型就闭环了。

步骤 7:sudo 白名单精细化(进阶,生产常用)

默认 sudo 组=「什么都能干」。若只想让 deploy 重启服务,不给他全部 root:

sudo visudo                       # 永远用 visudo(保存前做语法检查,防锁死)

在末尾加一行(语法:用户 主机=(以谁) 可执行命令):

deploy ALL=(root) NOPASSWD: /bin/systemctl restart coderoadmap-backend, /bin/systemctl status coderoadmap-backend

验证:

su - deploy
sudo -l                                    # 能看到这一条 NOPASSWD
sudo -n systemctl restart coderoadmap-backend   # -n 免交互,CI 里靠它自动执行
exit

这正是 GitHub Actions 自动部署重启服务的权限基础(github-actions 轨道会用到)。

讲清楚要点

  1. UID 是内核真正认的身份,用户名只是给人看的标签。UID 0 = root(可有多个名字但权力相同);1-999 系统用户;1000+ 普通用户。进程、文件权限判断全走 UID。
  2. su 借「对方」的密码,sudo 用「自己」的密码:su 适合长时间切换身份工作;sudo 适合单条命令借权,且天然带审计(谁、何时、执行了什么)。安全默认:人手 sudo,不用裸 root。
  3. 组是权限的「批量通道」:把人加进组(usermod -aG)比逐个改文件属主优雅得多。-aG 的 -a 不能忘——漏了会把用户踢出其他所有组(经典事故:把自己踢出 sudo 组)。
  4. 服务专用用户三要素:useradd -r(系统用户)+ nologin shell(不能登录)+ 目录属主对齐(文件课)。Nginx 的 worker、Java 服务、MySQL 各用各的用户,互不越界。
  5. visudo 是唯一安全的 sudoers 编辑方式:直接 vim 改 /etc/sudoers,一个语法错就能让所有人 sudo 失败(锁在系统外)。visudo 保存前会语法检查。
  6. su - 与 su 的区别:su - user 加载对方的完整环境(PATH、家目录),su user 保留当前环境变量——后者常导致「明明装了 java 却 command not found」,因为 PATH 没换。

你可能会懵的地方

  • sudo -i、sudo -s、sudo su 有什么区别? sudo -i:模拟 root 重新登录,环境干净(推荐);sudo -s:root shell 但保留当前环境;sudo su -:效果近似 -i,绕了一层。日常记 sudo -i 即可,退出用 exit。
  • 为什么我 sudo 时提示 xxx is not in the sudoers file? 你的用户不在 sudoers(不在 sudo/wheel 组,也无白名单条目)。补救只能由 root 或另一个管理员执行:usermod -aG sudo 你的用户名。所以把自己踢出 sudo 组前,务必留着 root SSH 通道。
  • useradd 和 adduser 用哪个? Debian/Ubuntu:adduser 是友好封装(交互、自动建目录),useradd 是底层命令(需手动传参);RHEL 系没有 adduser 区别(adduser 是 useradd 的软链)。记 Ubuntu 用 adduser、RHEL 用 useradd+passwd。
  • 服务用 www 跑,那我 deploy 还要 sudo 干什么? 部署动作大多需要 root 权限:systemctl restart、写 /etc/nginx、装包。规范是 deploy 有「精确白名单」(只许 restart 本服务、reload nginx),既自动化又最小权限。
  • 密码策略/锁定用户怎么做? 锁定:sudo usermod -L user(或 passwd -l),解锁 -U;禁用登录但不删:shell 改 /usr/sbin/nologin;删除:userdel -r user(-r 连家目录)。离职当天:锁定 + 踢出会话(pkill -u)+ 收回组与 sudoers。

错法对照

错法问题正解
一切操作都 root(SSH 用 root、服务用 root)误操作无防线,入侵即沦陷人用 deploy+sudo,服务用 www/nologin
usermod -G www deploy(漏 -a)deploy 被踢出 sudo 等原有组-aG 追加;操作前 id deploy 留底
直接 vim /etc/sudoers语法错=全员锁死visudo(自带语法检查)
su deploy 后找不到 java/环境不对没加 -,环境还是上一个用户的su - deploy 完整登录环境
服务运行用户建成了可登录普通用户多一个可 SSH 的账号面useradd -r -s /usr/sbin/nologin
把 deploy 直接加进 www 组改文件属主组权限混乱,越积越难理目录属主归服务用户,人经 sudo/白名单操作

卡点急救

  1. 误把自己踢出 sudo 组(漏 -a):只要还能用 root SSH/控制台 VNC 登录,usermod -aG sudo deploy 加回来;彻底锁死时用云厂商的「VNC/救援模式」以 root 进入修复——所以任何 usermod 前先 id 用户 截图留底。
  2. sudo 提示不在 sudoers 且没有 root 通道:云服务器走控制台 VNC 以 root 登录修复;本地 VM 用单用户模式(GRUB 编辑启动参数加 init=/bin/bash)。这是不重视「留 root 后门」的代价。
  3. 新建用户登录后只有 $、补全失效、乱码:家目录配置缺失(建用户时用了 useradd 没建骨架)。sudo cp /etc/skel/.bashrc /etc/skel/.profile /home/deploy/ && sudo chown deploy:deploy /home/deploy/.* 修复。
  4. NOPASSWD 不生效:/etc/sudoers.d/ 里可能有后面的文件覆盖了规则(sudoers 后写的生效);用 sudo visudo -f /etc/sudoers.d/xxx 检查;确认路径是绝对路径(/bin/systemctl 还是 /usr/bin/systemctl,which systemctl 确认)。
  5. deploy 用户重启服务报权限错:白名单命令路径与实际执行不一致(如带了参数)。sudo -l 看自己被允许的精确形式,命令照抄白名单;需要通配时用 ALL=(root) NOPASSWD: /bin/systemctl restart coderoadmap* 谨慎放开。

面试常问

  • su 和 sudo 的区别?生产环境推荐哪个? su 切换为另一个用户(需对方密码),整个会话都是对方身份;sudo 以指定身份执行单条命令(输自己的密码),权限可白名单细化、操作全审计(auth.log)。生产推荐 sudo:最小权限 + 审计 + 不必共享 root 密码。root 密码甚至可以不设(Ubuntu 默认)。

  • /etc/passwd 每个字段是什么?为什么密码在 /etc/shadow? 七段:用户名:x:UID:GID:备注:家目录:shell。密码哈希放 shadow 是安全分层:passwd 需人人可读(很多程序查用户名→UID),哈希不能公开,所以拆到仅 root 可读的 shadow,用 x 占位。影子文件还带过期策略字段。

  • 为什么生产服务(Nginx/Java/MySQL)不用 root 跑? 最小权限原则:服务进程若被漏洞攻破(如反序列化 RCE),攻击者继承的是运行用户的能力——www 用户写不了 /etc、读不了其他用户数据,爆炸半径可控;root 进程被攻破等于整机沦陷。配套做法:专用系统用户 + nologin + 目录属主对齐。

  • 如何让一个用户只能重启某个服务而不能做别的? sudoers 白名单:deploy ALL=(root) NOPASSWD: /bin/systemctl restart app.service(visudo 编辑,或放 /etc/sudoers.d/)。验证 sudo -l。CI 自动部署的重启权限就是这么开的。

  • usermod -aG 和 -G 的区别? -G 是「设置」附加组列表,会把用户之前所有附加组覆盖掉;-aG 是「追加」。实践一律用 -aG,除非刻意重置。误用 -G 踢掉自己所在 sudo 组是经典运维事故。

  • Linux 用户 UID 有什么约定? 0=root(特权);1-999 为系统用户(服务专用,通常 nologin、不设密码);1000+ 为可登录普通用户。判断进程/文件身份看 UID 而非名字;多机同步时 UID 冲突会导致权限错乱(NFS 场景尤其注意)。

自测三问

  1. id 与 whoami 输出的信息差在哪?groups deploy 能回答什么问题?
  2. 写出「创建禁止登录的系统用户 www、让其拥有 /www/wwwroot/coderoadmap 全部权限」的命令序列。
  3. deploy 用户被要求「只能重启 coderoadmap-backend、不能干别的」,写出 sudoers 条目并说明验证方法。

小结一句话

身份是权限的起点:人用普通用户 + sudo 白名单操作,服务用 nologin 系统用户运行,组做批量授权——「最小权限 + 可审计」六个字就是生产身份模型的全部。

延伸

  • Ubuntu 官方文档 — User Management
  • sudo 官方手册(sudoers 语法)
  • 下一课预告:包管理——apt update 和 upgrade 有什么区别?JDK 17、Node 20、MySQL 8 在 Ubuntu 上怎么装才不踩坑?RedHat 系的 dnf 又怎么对应?
加载本节练习…
← 上一课进程与服务下一课 →包管理