概述

完成系统安装与初始化之后,下一项基础工作就是建立可控的账号和权限体系。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.defsuseradd -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. 需要自动化免密时,限制到明确命令和明确参数路径。

权限治理模型

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

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

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

授权流程决定权限是否可解释。每一次提权都应能回答:谁申请,为什么需要,访问哪个系统,执行什么操作,持续多久,谁批准,何时复核。小团队可以用工单或表格,大团队可以接入 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) ALLNOPASSWD、通配符过宽、脚本路径可被普通用户修改等问题。文件复核看业务目录 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
添加交互用户常用工具 adduseruseradd useradd
sudo 包 sudo sudo
ACL 工具包 acl acl
日志查看 /var/log/auth.log、journald /var/log/secure、journald

本文使用更通用的 useraddgroupaddusermod 命令演示。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 包含密码哈希和有效期信息。不要手工编辑密码哈希,优先使用 passwdchageusermod 等工具。

常见状态:

状态 表现 含义
有哈希 $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、家目录和有效期,创建后用 idgetentchage 验证。
  3. sudo 应采用最小授权,优先通过 /etc/sudoers.d/visudo 管理。
  4. 文件权限要同时检查 owner、group、mode、ACL、umask 和上级目录执行权限。
  5. 账号禁用、删除、权限复核应成为固定运维流程,而不是故障后补救动作,责任边界也要同步记录。

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


参考资料



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