概述

完成系统安装与初始化之后,下一项基础工作就是建立可控的账号和权限体系。Linux 服务器的权限管理不是单个命令的问题,而是一套围绕身份、认证、授权、文件访问控制、提权审计和账号生命周期的治理机制。账号创建得随意、共享 root 密码、业务目录权限过宽、sudo 规则没有边界,都会让后续的软件部署、日志审计和故障定位变得混乱。

本文是 Linux 系统管理系列第 3 篇,承接上一篇《系统安装与初始化》。前一篇已经完成主机名、网络、时间同步、防火墙、SSH 等基础配置;本文进一步说明如何把“谁能登录、能做什么、能访问哪些文件、操作如何留痕”落到日常运维流程中。

为什么用户与权限管理是安全基线的核心

权限边界

  1. 身份是审计的起点:所有登录、sudo、文件修改、服务启动记录都需要追溯到明确的账号。多人共享同一个管理员账号会让审计失效。
  2. 最小权限降低误操作半径:普通用户只拥有工作所需权限,管理员通过 sudo 临时提权,可以减少误删系统文件、误改服务配置的概率。
  3. 文件权限决定数据边界:业务配置、密钥、日志、脚本、备份文件的 owner、group、mode 直接决定可读写范围。
  4. 账号生命周期影响长期风险:离职人员、临时外包、过期项目账号如果不及时禁用,会形成长期暴露面。
  5. 标准化权限便于自动化:Ansible、CI/CD、备份、监控代理都依赖稳定的用户、组和目录权限模型。

学习目标

通过本文的学习,您将能够:

  1. 理解 Linux 用户、组、UID、GID、主组和附加组的关系。
  2. 掌握 useradd、usermod、passwd、chage、groupadd、id 等账号管理命令。
  3. 配置 sudo 最小授权,并避免直接编辑 sudoers 导致系统不可管理。
  4. 使用 chmod、chown、umask、ACL 管理文件访问权限。
  5. 建立用户创建、权限申请、定期复核、账号禁用的运维流程。

理论基础

Linux 身份模型

Linux 身份模型

身份模型

Linux 将“身份”拆分为用户和组。用户用于表示执行命令、拥有文件、登录系统的主体;组用于表达一组用户对资源的共同访问权限。每个进程都有真实用户 ID、有效用户 ID、真实组 ID、有效组 ID 和附加组列表,内核在访问文件、绑定端口、修改系统资源时会根据这些身份判断是否允许操作。

常见身份文件如下:

文件 作用 运维关注点
/etc/passwd 保存账号名、UID、GID、家目录、登录 shell 等基础信息 不再保存明文密码;所有用户通常可读
/etc/shadow 保存密码哈希、密码有效期、账号过期字段 只应由 root 或受控进程读取
/etc/group 保存组名、GID、组成员 附加组授权的主要来源
/etc/gshadow 保存组密码和组管理员信息 普通环境很少直接维护
/etc/login.defs 定义 UID/GID 范围、密码有效期、umask 等默认策略 不同发行版默认值可能不同
/etc/default/useradd useradd 默认家目录、shell、过期策略等 批量创建用户前需要检查

UID、GID 与账号类型

Linux 内核最终识别的是数字 UID/GID,而不是用户名。用户名只是便于人类理解的映射。因此,跨主机复制文件、挂载 NFS、迁移容器卷、恢复备份时,必须关注 UID/GID 是否一致。

常见账号类型如下:

类型 典型 UID 范围 典型用途 管理建议
root 0 超级管理员 禁止多人共享;SSH 通常禁用 root 直接登录
系统账号 通常低于普通用户范围 运行服务进程,如 nginx、postgres、node_exporter 不设置可登录 shell,权限绑定到服务目录
普通账号 通常从 1000 开始 运维人员、开发人员、应用部署账号 明确负责人、用途、有效期
临时账号 视策略而定 外包、审计、临时排障 必须设置过期时间并纳入复核

不同发行版的 UID/GID 默认范围可能不同,实际以 /etc/login.defs、useradd -D 和发行版策略为准。不要在生产环境中假设“1000 一定是第一个普通用户”之外的更多细节。

文件权限模型

Linux 传统权限由三组对象和三类权限组成:

text
-rw-r----- 1 app app 2048 May 19 10:00 config.yml
│││ │││
│││ │└└─ other 权限
│││ └── group 权限
│└└──── owner 权限
└────── 文件类型
权限 对文件的含义 对目录的含义
r 读取文件内容 列出目录项
w 修改文件内容 创建、删除、重命名目录内对象
x 执行文件 进入目录、访问目录下路径

目录权限尤其容易被误解。一个用户即使对某个文件有读权限,如果缺少上级目录的执行权限,也无法访问该文件路径。反过来,目录有写权限意味着可以删除目录中的文件;删除动作取决于目录权限,而不是文件本身的写权限。

特殊权限位

除普通 rwx 外,Linux 还支持 setuid、setgid 和 sticky bit:

权限位 常见表示 作用 典型场景
setuid u+s 执行文件时使用文件 owner 的有效 UID /usr/bin/passwd 需要修改 shadow
setgid g+s 执行文件时使用文件 group;目录中新文件继承目录组 团队共享目录
sticky bit +t 目录内文件只能由文件 owner、目录 owner 或 root 删除 /tmp

特殊权限位要谨慎使用,尤其是 setuid root 程序。自研脚本一般不应通过 setuid 获取 root 权限,应该使用 sudo、systemd unit 或受控自动化平台进行授权。

sudo 与 su 的区别

su 是切换到另一个用户的会话,通常需要目标用户密码。sudo 是按规则允许某个用户以 root 或其他用户身份执行指定命令,通常使用当前用户密码并记录审计日志。生产环境更推荐 sudo,因为它可以做到按用户授权、按命令授权、按主机授权,并保留提权记录。

sudo 的核心原则是:

  1. 用组授权,不对每个人复制规则。
  2. 用 visudo 修改规则,避免语法错误导致 sudo 不可用。
  3. 优先把自定义规则放到 /etc/sudoers.d/。
  4. 不要滥用 NOPASSWD,更不要给普通用户无边界的 ALL=(ALL) NOPASSWD:ALL。
  5. 需要自动化免密时,限制到明确命令和明确参数路径。

权限治理模型

用户与权限管理不应只靠命令清单。生产环境需要先定义权限治理模型,再落到 useradd、chmod、sudo、ACL 和 systemd 配置。治理模型至少包括账号分类、权限层级、授权流程、审计记录和复核周期。

账号分类决定管理方式。个人账号用于人与系统交互,必须能追溯到自然人;服务账号用于运行进程,通常不允许交互登录;自动化账号用于 CI/CD、备份、监控、配置管理等平台调用,必须限制密钥和命令范围;临时账号用于外包、审计、排障,必须有过期时间。不同类型账号如果混用,审计很快失效。

权限层级决定风险半径。普通用户只能访问自己的家目录和授权业务目录;发布用户可以写入指定应用目录,但不能修改系统服务定义;运维用户可以查看日志、重启指定服务、执行诊断命令;平台管理员才允许管理软件包、网络、防火墙和系统级服务。把所有人都加入 sudo 或 wheel,短期方便,长期会让责任边界消失。

授权流程决定权限是否可解释。每一次提权都应能回答:谁申请,为什么需要,访问哪个系统,执行什么操作,持续多久,谁批准,何时复核。小团队可以用工单或表格,大团队可以接入 IAM、堡垒机或权限管理平台。工具不同,但原则相同:授权必须有理由、有范围、有期限、有记录。

审计记录决定事后能否还原事实。Linux 本地可以通过 sudo 日志、auth.log/secure、journald、auditd、shell history、文件时间戳等收集证据。生产环境不要依赖用户本地 history 作为唯一审计,因为它容易被清理或绕过。更可靠的方式是结合堡垒机、集中日志和 sudo/auditd 记录。

复核周期决定权限是否持续有效。账号和权限不是创建后永久有效。人员转岗、项目结束、外包退场、服务下线、自动化平台替换,都会让原权限失去必要性。建议每月至少复核高权限账号和 sudo 规则,每季度复核普通账号和服务账号,每次重大组织调整后做专项复核。

账号生命周期

账号生命周期可以分为申请、创建、授权、使用、变更、禁用、删除和归档八个阶段。

申请阶段要明确用途。一个账号是给人登录、给服务运行,还是给自动化平台使用,决定了它是否需要家目录、登录 shell、密码、SSH key、sudo 权限和过期时间。不要先创建账号,再补用途说明。

创建阶段要遵守命名规范。个人账号建议与企业身份一致,例如拼音、工号或统一账号名;服务账号可以使用 svc_应用名 或应用专用名称;自动化账号可以使用 bot_用途 或平台统一命名。命名不是形式问题,它影响审计和批量管理。

授权阶段要遵守最小权限。给用户加入组、配置 sudo、授权目录、写入 SSH key,都应只覆盖当前工作需要。需要临时扩大权限时,应记录原因和到期时间。

使用阶段要保留证据。管理员登录、sudo 提权、修改关键配置、重启服务、变更权限,都应能在日志中看到。若通过跳板机或堡垒机登录,还应保留会话记录。

变更阶段要重新评估权限。人员转岗、项目范围变化、服务目录迁移、应用拆分、自动化平台替换,都可能要求调整用户、组、ACL 和 sudo 规则。

禁用阶段用于保留证据。离职或长期不用账号,通常先锁定密码、禁用 SSH key、移除 sudo 和关键组,保留家目录和文件归属一段时间。直接删除账号可能导致文件只剩数字 UID,不利于追溯。

删除阶段要谨慎处理文件。删除前先查找用户拥有的文件、计划任务、systemd user 服务、SSH key、sudoers 规则和业务目录权限。确认无依赖后再删除账号。

归档阶段要保留审计记录。账号申请、授权、变更、禁用和删除记录应保留到组织规定期限,便于安全审计和事故复盘。

服务账号设计

服务账号是生产 Linux 管理里最容易被低估的一类账号。很多服务为了省事直接用 root 启动,或者多个应用共用同一个 app 用户。这样做会扩大故障和攻击半径:一个应用被攻破,就能访问同一用户下的其他应用文件;一个脚本误删目录,也可能影响多个服务。

服务账号设计应遵循三个原则。第一,一服务一账号或一应用域一账号。简单环境可以按应用域合并,但不要让无关业务共用同一个高权限账号。第二,服务账号默认不可交互登录,shell 可以设置为 /usr/sbin/nologin 或 /bin/false。第三,服务账号只拥有必要目录权限,例如配置只读、数据目录可写、日志目录可写,不能拥有系统目录写权限。

systemd 可以进一步收紧服务权限。除了 User=、Group=、UMask=,还可以使用 NoNewPrivileges=、PrivateTmp=、ProtectSystem=、ProtectHome=、ReadWritePaths= 等选项。但这些选项必须逐项验证,因为服务可能需要读证书、写缓存、访问设备或调用外部命令。安全选项不能机械复制。

服务账号还要和部署流程配合。发布用户不一定等于运行用户。发布用户可以把包部署到暂存目录,再由受控脚本或 systemd 重启服务;运行用户只负责进程运行和必要读写。这样能减少发布脚本误改运行权限的风险。

集中身份与本地账号

单台服务器可以只靠本地账号管理,多主机环境则应考虑集中身份。常见方式包括 LDAP、FreeIPA、Active Directory、SSSD、堡垒机账号映射和云平台 IAM。集中身份的好处是统一账号生命周期、减少本地重复创建、便于禁用离职人员和集中审计。

集中身份并不意味着本地账号消失。系统仍需要 root、服务账号、应急账号和部分本地自动化账号。关键是明确本地账号和域账号的职责边界。域账号适合人登录和集中授权;本地服务账号适合运行进程;应急账号适合身份系统不可用时进入服务器,但必须严格保管和审计。

引入集中身份时要关注 NSS 和 PAM。NSS 决定系统如何解析用户和组,PAM 决定认证和会话策略。配置错误可能导致无法登录,甚至把管理员锁在系统外。变更前应保留本地应急账号和控制台访问,并在测试服务器验证。

UID/GID 规划也更重要。集中身份会给用户分配数字 ID,如果与本地账号或历史 NFS 文件冲突,可能造成文件归属混乱。跨主机共享目录、NFS、容器卷和备份恢复都要考虑 UID/GID 一致性。

权限复核清单

权限复核要从“账号、组、sudo、文件、特殊位、密钥、服务”七个角度进行。

账号复核看是否有过期、离职、长期未登录、无负责人账号。组复核看高权限组成员是否合理,是否存在临时成员没有移除。sudo 复核看是否有 ALL=(ALL) ALL、NOPASSWD、通配符过宽、脚本路径可被普通用户修改等问题。文件复核看业务目录 owner/group/mode 是否符合预期,是否存在 world-writable 文件。特殊位复核看 setuid/setgid 文件是否异常。密钥复核看 authorized_keys 是否有未知 key。服务复核看 systemd unit 是否使用 root 或过宽目录权限。

可以把复核结果分成三类:立即整改、限期整改、接受风险。立即整改包括离职账号仍可登录、普通用户拥有 root 级 sudo、业务目录 777、私钥可被多人读取。限期整改包括服务账号缺少负责人、sudo 规则过宽但有业务依赖、UID/GID 不规范。接受风险则必须记录原因和复核日期。

权限复核的目标不是追求零例外,而是让每个例外可见、可解释、可跟踪。

sudo 规则设计

sudo 规则设计要从操作场景出发,而不是从用户职级出发。常见错误是把“运维人员”等同于“所有命令都能执行”。更稳妥的方式是把操作拆成若干命令集合,例如查看状态、重启指定服务、查看日志、发布应用、执行备份、管理网络、安装软件包,再按组授权。

例如,应用运维可能只需要查看和重启某个服务:

sudoers
Cmnd_Alias DEMO_STATUS = /bin/systemctl status demo.service, /bin/journalctl -u demo.service *
Cmnd_Alias DEMO_RESTART = /bin/systemctl restart demo.service

%demo-ops ALL=(root) DEMO_STATUS, DEMO_RESTART

这个规则比 ALL=(ALL) ALL 安全得多,但仍要注意路径和参数。若允许执行一个可被普通用户修改的脚本,即使 sudoers 看起来限制了命令,也可能被绕过。因此,被 sudo 调用的脚本必须由 root 或受控组拥有,普通用户不能写。

自动化账号的 sudo 规则要更严格。备份账号可能只需要读取指定目录和执行备份命令;发布账号可能只需要同步文件、切换软链接、reload 服务;监控账号通常只需要只读命令。不要因为自动化需要免密,就给它 NOPASSWD:ALL。免密不是问题,问题是免密范围失控。

sudo 日志也要纳入集中采集。至少要能看到谁在什么时间、从哪台主机、执行了什么 sudo 命令、返回结果如何。对高风险命令,例如修改 sudoers、删除目录、改防火墙、改网络、安装软件包,应进入安全审计或运维值班视图。

业务目录权限样例

以 /srv/apps/demo 为例,一个常见权限设计如下:

text
/srv/apps/demo/
  releases/      发布包目录,deploy 组可写
  current -> releases/20260612
  shared/
    config/      配置目录,root 管理,应用只读
    logs/        日志目录,应用可写,运维可读
    data/        业务数据目录,应用可写,备份可读

对应的权限可以这样规划:

路径 owner group mode 说明
/srv/apps/demo root deploy 2750 setgid 让新文件继承组
releases deploy deploy 2770 发布组写入
shared/config root demoapp 2750 应用读配置,不能改配置
shared/logs demoapp ops 2750 应用写日志,运维读日志
shared/data demoapp backup 2750 应用写数据,备份读数据

这种设计把发布、运行、运维、备份拆开,避免一个用户拥有所有能力。实际环境中还可以通过 ACL 给某个排障账号临时读日志权限,排障结束后撤销 ACL,而不是把他永久加入高权限组。

设置权限时要先创建组和服务账号:

bash
sudo groupadd deploy
sudo groupadd ops
sudo groupadd backup
sudo useradd --system --no-create-home --shell /usr/sbin/nologin demoapp

sudo mkdir -p /srv/apps/demo/{releases,shared/config,shared/logs,shared/data}
sudo chown root:deploy /srv/apps/demo
sudo chmod 2750 /srv/apps/demo
sudo chown deploy:deploy /srv/apps/demo/releases
sudo chmod 2770 /srv/apps/demo/releases
sudo chown root:demoapp /srv/apps/demo/shared/config
sudo chmod 2750 /srv/apps/demo/shared/config
sudo chown demoapp:ops /srv/apps/demo/shared/logs
sudo chmod 2750 /srv/apps/demo/shared/logs
sudo chown demoapp:backup /srv/apps/demo/shared/data
sudo chmod 2750 /srv/apps/demo/shared/data

执行后要用不同身份验证,而不是只看 ls -l:

bash
sudo -u demoapp test -r /srv/apps/demo/shared/config/app.yml
sudo -u demoapp test -w /srv/apps/demo/shared/logs
sudo -u demoapp test -w /srv/apps/demo/shared/data
sudo -u demoapp test ! -w /srv/apps/demo/shared/config

权限设计的核心是“按职责拆分写权限”。读权限可以相对宽一些,但写权限必须清楚地落到责任主体上。

密钥和凭据管理

Linux 用户权限不只体现在密码和 sudo。SSH key、API token、数据库密码、私钥文件、云凭据、备份密钥都属于权限边界。很多服务器事故不是账号本身泄露,而是某个用户家目录中的私钥或配置文件被其他用户读取。

SSH authorized_keys 应定期复核。个人账号的 key 应来自可信设备或统一堡垒机,不应长期保留临时 key。服务账号如果必须使用 SSH key,应限制来源、命令和用途,例如使用 from=、command= 等 OpenSSH authorized_keys 选项,或者通过部署平台统一管理。

敏感文件权限建议遵守保守原则:私钥 600,包含密码的配置文件不超过 640,目录不超过 750,owner 和 group 必须明确。不要为了让服务能读配置就把配置目录改成 777。如果服务无法读取,应该分析运行用户、组、ACL 和 systemd 限制,而不是直接放宽所有权限。

离职、转岗和应急账号

离职和转岗是权限管理中最容易被拖延的环节。人员离开团队后,账号应立即锁定或禁用,SSH key 应删除,sudo 和高权限组应移除,堡垒机、VPN、云平台和代码仓库权限也要同步处理。不要只删除 Linux 本地账号,而忽略集中身份和自动化平台中的授权。

离职账号不一定马上删除。对生产服务器,可以先锁定账号并保留家目录一段时间,用于审计和文件归属确认。处理步骤可以是:锁定密码、禁用 SSH key、移除 sudo、移出业务组、检查计划任务、检查 systemd user 服务、查找该用户拥有的文件、归档必要资料,最后按保留策略删除。

转岗账号要重新评估权限。一个人从运维转到项目管理,或者从数据库团队转到应用团队,原有 sudo、数据库备份、生产日志和发布权限可能不再需要。转岗不能只改组织架构系统,必须同步权限复核。

应急账号用于集中身份不可用、堡垒机故障或关键系统排障。应急账号必须少量、强密码、离线保管、定期演练、使用后立即轮换密码,并在日志中标记使用原因。不要把应急账号变成日常共享管理员账号。

权限管理的成熟度体现在异常场景。平时创建账号很容易,真正考验流程的是人员离开、系统故障、身份源不可用、业务紧急发布和安全事件响应时,权限是否仍然可控。

这些场景都应进入演练清单,避免真正故障时临时放权,留下新的安全缺口和审计盲区,影响追溯和整改闭环效率提升。


环境规划

本文示例以常见服务器环境为基准:

项目 示例规划
发行版 Ubuntu Server 22.04/24.04、Debian 12、Rocky Linux 9、RHEL 9 同类环境均可参考
管理方式 SSH 登录 + sudo 提权
账号策略 个人账号登录,禁止共享 root;服务账号不可交互登录
普通用户组 ops 运维组、deploy 发布组、audit 审计组
业务目录 /srv/apps/demo
参考命令 shadow-utils、coreutils、sudo、acl 工具集

执行前先确认当前环境:

bash
cat /etc/os-release
id
getent passwd root
getent group sudo || getent group wheel
useradd -D
grep -E '^(UID_MIN|UID_MAX|SYS_UID_MIN|SYS_UID_MAX|UMASK|PASS_)' /etc/login.defs

不同发行版存在命令差异:

场景 Debian/Ubuntu RHEL/Rocky/Alma
管理员组 sudo wheel
添加交互用户常用工具 adduser 或 useradd useradd
sudo 包 sudo sudo
ACL 工具包 acl acl
日志查看 /var/log/auth.log、journald /var/log/secure、journald

本文使用更通用的 useradd、groupadd、usermod 命令演示。Debian/Ubuntu 的 adduser 是更友好的前端工具,在人工创建用户时也可以使用。


实战操作

账号与用户组落地路径

账号路径

1. 查看当前用户与组

bash
# 查看当前登录身份
id
whoami
groups

# 查看指定用户
id root
getent passwd root
getent shadow root

# 查看组
getent group sudo
getent group wheel

getent 比直接 cat /etc/passwd 更适合生产环境,因为它会通过 Name Service Switch 查询系统配置的身份来源,包括本地文件、LDAP、SSSD 等。

2. 创建运维组和发布组

bash
# 创建基础组
sudo groupadd ops
sudo groupadd deploy
sudo groupadd audit

# 验证组是否存在
getent group ops
getent group deploy
getent group audit

如果命令提示组已存在,不要直接删除重建。应先确认该组是否已经被目录、服务或 sudo 规则引用:

bash
getent group ops
find / -xdev -group ops -ls 2>/dev/null | head
sudo grep -R "ops" /etc/sudoers /etc/sudoers.d 2>/dev/null

3. 创建普通运维用户

以下示例创建个人账号 zhangsan,指定注释、家目录、shell,并加入 ops 附加组:

bash
sudo useradd \
  --create-home \
  --comment "Ops engineer Zhang San" \
  --shell /bin/bash \
  --groups ops \
  zhangsan

sudo passwd zhangsan
id zhangsan
getent passwd zhangsan

关键参数说明:

参数 含义 注意事项
--create-home / -m 创建家目录并复制 /etc/skel 系统账号通常不需要家目录
--comment / -c 设置 GECOS 备注 建议写清负责人和用途
--shell / -s 设置登录 shell 服务账号可用 /usr/sbin/nologin
--groups / -G 设置附加组 修改已有用户附加组时注意 -aG

给已有用户追加组时必须使用 -aG,否则会覆盖原有附加组:

bash
# 正确:追加 deploy 组
sudo usermod -aG deploy zhangsan

# 危险:不带 -a 会把附加组替换为 deploy
sudo usermod -G deploy zhangsan

用户组变更通常需要用户重新登录后才会在新会话中生效。排障时要确认当前会话的 id 输出,而不是只看 /etc/group。

4. 创建不可交互登录的服务账号

业务服务不应使用个人账号运行,也不应使用 root 直接运行。可以创建专用系统账号:

bash
sudo useradd \
  --system \
  --no-create-home \
  --shell /usr/sbin/nologin \
  --comment "Demo application service account" \
  demoapp

id demoapp
getent passwd demoapp

如果某些发行版没有 /usr/sbin/nologin,可用以下命令确认可用路径:

bash
command -v nologin
grep nologin /etc/shells 2>/dev/null || true

服务账号目录建议放在 /srv、/var/lib、/opt 等明确位置,并把 owner 设为服务账号或部署组:

bash
sudo mkdir -p /srv/apps/demo/{current,shared,logs}
sudo chown -R demoapp:deploy /srv/apps/demo
sudo chmod 2750 /srv/apps/demo
sudo chmod 2770 /srv/apps/demo/{shared,logs}

这里的 2 是 setgid 位,表示目录中新建文件默认继承目录所属组,适合团队共享部署目录。

5. 设置密码有效期和账号过期时间

查看密码策略:

bash
sudo chage -l zhangsan
grep -E '^(PASS_MAX_DAYS|PASS_MIN_DAYS|PASS_WARN_AGE)' /etc/login.defs

设置单个用户的密码周期:

bash
# 最长 90 天、最短 1 天、提前 14 天提醒
sudo chage -M 90 -m 1 -W 14 zhangsan

# 强制下次登录修改密码
sudo passwd --expire zhangsan

设置临时账号过期:

bash
sudo useradd -m -s /bin/bash -e 2026-06-30 temp_vendor
sudo passwd temp_vendor
sudo chage -l temp_vendor

临时账号必须记录申请人、用途和到期时间。到期后建议先锁定观察,再按流程删除:

bash
sudo usermod --lock temp_vendor
sudo usermod --expiredate 1 temp_vendor

6. 配置 sudo 最小授权

Ubuntu/Debian 通常使用 sudo 组,RHEL/Rocky 通常使用 wheel 组。添加管理员组:

bash
# Ubuntu/Debian
sudo usermod -aG sudo zhangsan

# RHEL/Rocky
sudo usermod -aG wheel zhangsan

更推荐为业务操作创建专门规则。例如允许 deploy 组重启 demo 服务、查看服务状态,但不允许任意 root shell:

bash
sudo visudo -f /etc/sudoers.d/demo-deploy

写入以下内容:

sudoers
%deploy ALL=(root) /bin/systemctl status demo.service, /bin/systemctl restart demo.service, /bin/journalctl -u demo.service

保存后检查语法:

bash
sudo visudo -cf /etc/sudoers
sudo visudo -cf /etc/sudoers.d/demo-deploy
sudo -l -U zhangsan

如果 systemctl 路径不同,先用 command -v systemctl 确认。sudoers 中的命令路径应使用绝对路径,不要写相对路径。

7. 管理文件 owner、group 和 mode

创建业务配置目录:

bash
sudo mkdir -p /etc/demoapp
sudo touch /etc/demoapp/config.yml
sudo chown root:deploy /etc/demoapp/config.yml
sudo chmod 640 /etc/demoapp/config.yml
ls -l /etc/demoapp/config.yml

含义是:

对象 权限 说明
owner root rw- 只有 root 可以修改
group deploy r-- 发布组可以读取
other --- 其他用户无权限

递归修改权限时要谨慎,尤其不要在根目录、系统目录或挂载点误执行:

bash
# 推荐先预览
find /srv/apps/demo -maxdepth 2 -ls

# 分别设置目录和文件权限
sudo find /srv/apps/demo -type d -exec chmod 2750 {} \;
sudo find /srv/apps/demo -type f -exec chmod 640 {} \;

不要使用 chmod -R 777 解决权限问题。它会把读写执行权限开放给所有本地用户,并且可能暴露密钥、配置和日志。

8. 使用 umask 控制新文件默认权限

umask 决定新建文件和目录会屏蔽哪些权限。常见值:

umask 新文件常见权限 新目录常见权限 适用场景
022 644 755 系统默认、普通只读共享
027 640 750 企业服务器常见收紧策略
077 600 700 密钥、个人敏感文件

查看当前 umask:

bash
umask

对服务进程,优先在 systemd unit 中设置:

ini
[Service]
User=demoapp
Group=deploy
UMask=0027

修改后重载并重启服务:

bash
sudo systemctl daemon-reload
sudo systemctl restart demo.service

9. 使用 ACL 处理例外权限

传统 owner/group/other 权限无法表达“多给某个用户读权限,但不改变文件所属组”的需求。此时可以使用 ACL:

bash
# 安装 ACL 工具
sudo apt install -y acl
# 或
sudo dnf install -y acl

# 给 audit 用户读取权限
sudo setfacl -m u:audituser:r /etc/demoapp/config.yml
getfacl /etc/demoapp/config.yml

# 设置目录默认 ACL,让新文件继承
sudo setfacl -m d:g:audit:rx /srv/apps/demo/logs
sudo setfacl -m g:audit:rx /srv/apps/demo/logs
getfacl /srv/apps/demo/logs

ACL 适合处理少量例外,不适合替代整体权限设计。若某个目录存在大量 ACL 规则,应重新评估组模型是否设计不合理。

10. 禁用、锁定和删除账号

账号退出使用时,建议按“锁定 -> 观察 -> 归档 -> 删除”的顺序处理:

bash
# 锁定密码登录
sudo passwd --lock zhangsan

# 禁用账号登录
sudo usermod --expiredate 1 zhangsan

# 确认仍有哪些文件属于该用户
sudo find / -xdev -user zhangsan -ls 2>/dev/null

# 删除账号但保留家目录
sudo userdel zhangsan

# 删除账号并删除家目录,执行前必须确认备份
sudo userdel --remove zhangsan

如果账号拥有定时任务、systemd user service、SSH key、sudo 规则或业务目录权限,删除前要一并清理:

bash
sudo crontab -u zhangsan -l
sudo grep -R "zhangsan" /etc/sudoers /etc/sudoers.d /etc/ssh 2>/dev/null
sudo find /srv /opt /var -xdev -user zhangsan -ls 2>/dev/null

配置详解

/etc/passwd 字段

示例:

text
zhangsan:x:1001:1001:Ops engineer Zhang San:/home/zhangsan:/bin/bash

字段含义:

字段 示例 含义
用户名 zhangsan 登录名
密码占位 x 表示密码哈希在 /etc/shadow
UID 1001 用户数字 ID
GID 1001 主组数字 ID
GECOS Ops engineer Zhang San 备注信息
家目录 /home/zhangsan 登录后的默认目录
shell /bin/bash 登录 shell

/etc/shadow 的关键字段

/etc/shadow 包含密码哈希和有效期信息。不要手工编辑密码哈希,优先使用 passwd、chage、usermod 等工具。

常见状态:

状态 表现 含义
有哈希 $y$...、$6$... 等 可使用密码认证
! 或 * 密码字段被锁定 不能用密码登录
过期日期已到 chage -l 显示过期 账号不可正常登录

sudoers 规则结构

sudoers
%deploy ALL=(root) /bin/systemctl restart demo.service

字段解释:

片段 含义
%deploy deploy 组成员
ALL 在所有主机上生效
(root) 以 root 身份执行
/bin/systemctl restart demo.service 允许执行的命令

如果需要限制参数,必须把参数写完整。允许 /bin/systemctl * demo.service 这类宽泛匹配时,要评估是否会绕过边界。

权限数字表示法

chmod 640 file 中每一位是权限求和:

数字 权限
4 read
2 write
1 execute

因此:

模式 含义
600 owner 读写,其他无权限
640 owner 读写,group 只读
750 owner 全权限,group 读和执行
2750 在 750 基础上增加 setgid
1777 所有人可写目录,但启用 sticky bit

验证与测试

权限验证与审计路径

审计路径

1. 验证账号创建

bash
getent passwd zhangsan
id zhangsan
sudo chage -l zhangsan

成功标准:

  • getent passwd 能查到用户。
  • id 显示正确 UID、主组和附加组。
  • chage -l 显示符合预期的密码有效期和账号过期策略。

2. 验证 sudo 授权

bash
sudo -l -U zhangsan

再使用目标用户新建 SSH 会话验证:

bash
sudo systemctl status demo.service
sudo systemctl restart demo.service
sudo -i

成功标准:

  • 被授权命令可以执行或进入正常权限检查。
  • 未授权命令被拒绝。
  • sudo 日志能记录执行用户、目标命令和时间。

3. 验证目录权限

bash
namei -l /srv/apps/demo/shared
ls -ld /srv/apps/demo /srv/apps/demo/shared
sudo -u demoapp test -w /srv/apps/demo/logs && echo writable
sudo -u nobody test -r /etc/demoapp/config.yml || echo denied

namei -l 可以逐级显示路径权限,适合排查“文件权限看起来正确但仍无法访问”的问题。

4. 验证 ACL

bash
getfacl /etc/demoapp/config.yml
sudo -u audituser test -r /etc/demoapp/config.yml && echo readable

如果 ACL 未生效,检查文件系统挂载选项、上级目录执行权限和 ACL mask。

5. 审计高风险权限

bash
# 查找 world-writable 目录
sudo find / -xdev -type d -perm -0002 -ls 2>/dev/null

# 查找 setuid 文件
sudo find / -xdev -perm -4000 -type f -ls 2>/dev/null

# 查找无属主文件
sudo find / -xdev \( -nouser -o -nogroup \) -ls 2>/dev/null

# 查找 SSH 私钥权限过宽的情况
sudo find /home -xdev -name "id_*" -type f -not -perm 600 -ls 2>/dev/null

这些命令可能输出较多,生产环境建议限定目录、纳入定期巡检,并人工确认误报。


故障排查

1. 用户已经加入组,但仍然没有权限

常见原因:

  • 当前 shell 会话还没有重新加载组成员关系。
  • 使用 usermod -G 覆盖了原有附加组。
  • 目标路径上级目录缺少执行权限。
  • ACL mask 限制了实际权限。

排查命令:

bash
id
id zhangsan
namei -l /path/to/resource
getfacl /path/to/resource

处理方式:

bash
# 重新登录最可靠;临时测试可使用
newgrp deploy

2. sudo 提示用户不在 sudoers 文件中

检查用户所属组和发行版管理员组:

bash
id zhangsan
getent group sudo
getent group wheel
sudo -l -U zhangsan

修复方式:

bash
# Ubuntu/Debian
sudo usermod -aG sudo zhangsan

# RHEL/Rocky
sudo usermod -aG wheel zhangsan

如果 sudoers 文件语法错误,应从 root 控制台、云厂商救援模式或单用户模式修复,并使用 visudo -c 验证。

3. SSH 密钥登录失败

重点检查:

bash
ls -ld /home/zhangsan /home/zhangsan/.ssh
ls -l /home/zhangsan/.ssh/authorized_keys
sudo tail -n 100 /var/log/auth.log 2>/dev/null || sudo tail -n 100 /var/log/secure 2>/dev/null
sudo journalctl -u ssh -u sshd --since "30 min ago"

常见权限要求:

bash
sudo chown -R zhangsan:zhangsan /home/zhangsan/.ssh
sudo chmod 700 /home/zhangsan/.ssh
sudo chmod 600 /home/zhangsan/.ssh/authorized_keys

还要检查账号是否被锁定、shell 是否为 nologin、家目录是否存在。

4. 服务账号无法写日志

排查顺序:

bash
id demoapp
namei -l /srv/apps/demo/logs/app.log
ls -ld /srv/apps/demo/logs
getfacl /srv/apps/demo/logs
sudo -u demoapp test -w /srv/apps/demo/logs && echo ok

如果服务由 systemd 管理,还要检查 unit 中的 User=、Group=、ReadWritePaths=、ProtectSystem=、DynamicUser= 等安全限制。

5. 删除用户后文件显示数字 UID

原因是文件系统保存的是 UID/GID,用户名删除后映射消失。先确认文件归属和业务影响:

bash
sudo find / -xdev -nouser -ls 2>/dev/null
sudo find / -xdev -nogroup -ls 2>/dev/null

处理方式:

bash
sudo chown -R newowner:newgroup /path/to/data

不要为了“让名字回来”而随意创建同 UID 用户,除非这是经过确认的恢复方案。

6. chmod 后权限仍然不符合预期

可能原因:

  • 有 ACL,实际权限受 ACL mask 影响。
  • 目录 setgid 导致新文件继承组。
  • 服务进程 umask 覆盖了默认权限。
  • 容器、NFS、CIFS 等挂载层有额外权限映射。

排查命令:

bash
getfacl /path/to/file
stat /path/to/file
findmnt /path/to/file
systemctl show demo.service -p UMask -p User -p Group

运维建议

1. 建立账号申请模板

账号申请至少记录:

字段 示例
申请人 张三
账号名 zhangsan
用途 日常运维
所属组 ops
sudo 权限 仅查看服务状态、重启指定服务
有效期 长期或明确到期日
审批人 运维负责人

2. 禁止共享高权限账号

建议策略:

  • root 不直接用于 SSH 登录。
  • 管理员使用个人账号登录,再通过 sudo 提权。
  • 自动化任务使用专用服务账号,并限制命令、目录和密钥用途。
  • 临时排障账号设置过期时间。

3. 定期复核用户和 sudo 权限

每月至少检查:

bash
getent passwd | awk -F: '$3 >= 1000 {print $1, $3, $6, $7}'
getent group sudo
getent group wheel
sudo grep -R "ALL" /etc/sudoers /etc/sudoers.d 2>/dev/null
sudo find / -xdev -perm -4000 -type f -ls 2>/dev/null

复核重点:

  • 是否存在离职、转岗、过期账号。
  • 是否存在无负责人服务账号。
  • 是否存在过宽 sudo 规则。
  • 是否存在异常 setuid 文件。
  • 是否存在 world-writable 业务目录。

4. 统一 UID/GID 规划

多主机环境建议提前规划:

  • 本地普通用户使用默认范围即可。
  • 跨主机共享目录、NFS、备份恢复涉及的服务账号,应固定 UID/GID。
  • LDAP/FreeIPA/AD/SSSD 环境中,本地账号和域账号范围不要冲突。
  • 容器宿主机要关注 /etc/subuid、/etc/subgid 对 rootless 容器的影响。

5. 服务权限与 systemd 安全选项结合

服务账号只是第一层隔离。systemd unit 中还可以叠加:

ini
[Service]
User=demoapp
Group=deploy
UMask=0027
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/srv/apps/demo /var/log/demoapp

这些选项需要结合服务实际读写路径逐项验证,不能直接照搬到生产服务,否则可能导致服务无法启动或无法写入必要文件。


总结

用户与权限管理是 Linux 服务器安全和可维护性的底座。本文从身份模型、账号文件、UID/GID、sudo、文件权限、umask、ACL 和账号生命周期几个角度,构建了一套可落地的管理方法。

关键要点回顾:

  1. 用户和组是权限控制的基础,生产环境应使用个人账号和专用服务账号,避免共享 root。
  2. 创建用户前先规划用途、组、shell、家目录和有效期,创建后用 id、getent、chage 验证。
  3. sudo 应采用最小授权,优先通过 /etc/sudoers.d/ 和 visudo 管理。
  4. 文件权限要同时检查 owner、group、mode、ACL、umask 和上级目录执行权限。
  5. 账号禁用、删除、权限复核应成为固定运维流程,而不是故障后补救动作,责任边界也要同步记录。

下一步学习: 在掌握用户与权限管理之后,建议继续学习《文件系统管理》,系统理解 Linux 文件系统层级、挂载、磁盘空间、inode、LVM 与常见文件系统维护方法。


参考资料



本文最后更新于 2026-05-22