☰
Linux用户管理与MD5校验:账号配置文件完整性基线实战
2026/10/24 7:43:46 网站建设 项目流程

在日常运维和开发工作中,账号体系往往是最容易被忽视、又最不能出错的一环。团队扩容时需要批量开通账号,人员离职时需要及时回收权限,服务器被入侵后第一件事往往是确认/etc/passwd、/etc/shadow这些关键文件有没有被改动过。本文围绕“Linux 用户管理”与“MD5 校验”这条组合线索展开,属于系列笔记的第 69 篇,重点讲清楚两件事:一是 Linux 用户与用户组的核心操作该怎么写、怎么写对;二是如何用 MD5 摘要给账号相关配置文件做一份“指纹基线”,在文件被非预期修改时第一时间发现。文章面向刚接触 Linux 的同学,也适合有一定基础、想补齐账号安全治理思路的后端和运维读者。读完之后,你应该能独立完成用户的增删改查、密码策略配置,并且能亲手写出一个可落地的配置文件完整性校验脚本。

1. 背景与核心概念

1.1 Linux 用户管理到底在管什么

很多同学对“用户管理”的理解停留在“会敲useradd和passwd”,这其实只覆盖了很小一部分。从系统的角度看,Linux 的用户管理本质上是在维护一套身份标识与权限归属的映射关系:每个进程都有一个 UID 作为身份凭证,文件和目录通过属主、属组以及 rwx 权限位来决定谁能读、谁能写、谁能执行。用户管理做的事情,就是建立“用户名 → UID → 权限集合”这条链路,并保证这条链路可以被审计、被回收。

这套机制落到磁盘上,主要由几个纯文本文件承载。/etc/passwd保存用户的基本属性,/etc/shadow保存密码哈希与过期策略,/etc/group保存用户组与成员关系,/etc/gshadow保存组密码,/etc/login.defs和/etc/default/useradd保存新建用户时的默认参数。这些文件任何一个被误改或恶意篡改,都可能导致账号逃逸、权限提升或者无法登录。所以它们既是“配置”,也是需要重点盯防的“资产”。

理解这一点很关键,因为它解释了我们为什么要引入校验手段。用户管理不只是“加人减人”的日常操作,它还是一项需要留下可追溯痕迹的变更行为。当账号文件从“随便改”变成“改之前要过流程、改之后要能核对”,用户管理才算真正做到了工程化。

1.2 MD5 是什么,它能解决什么问题

MD5(Message Digest Algorithm 5)是一种摘要算法,它把任意长度的输入数据压缩成一个固定 128 位、也就是 32 个十六进制字符的输出。这个输出具备几个重要特性:同样的输入永远得到同样的输出;输入只要变动一个字节,输出就会发生剧烈变化;从输出反推输入在计算上不可行。正因为这些特性,MD5 常被用来做数据完整性校验——比对摘要值是否一致,就能判断两份数据是否完全相同。

需要特别强调的是它的适用边界。MD5 在设计上已经被证明存在碰撞攻击的可行性,也就是说攻击者有可能构造出两段内容不同、但 MD5 相同的输入。因此 MD5 不应该再被用来做安全相关的密码存储、数字签名或者需要对抗恶意构造的场景。但在“检测非预期修改”这个场景里,比如对比配置文件有没有被误改、下载的文件有没有传输出错、备份文件和源文件是否一致,MD5 依然是简单高效的选择。如果你所处的环境对安全性要求更高,可以平替为sha256sum,用法几乎完全一致。

一句话概括:MD5 是“防误改”的好工具,不是“防恶意伪造”的安全机制。把这两件事分清,后面的设计才不会走偏。

1.3 用户管理和 MD5 校验为什么放在一起讲

单独讲用户管理,落点常常在“命令怎么用”;单独讲 MD5,落点又常常停留在“怎么算一个字符串的哈希”。但把两者结合起来,就出现了一个非常实际的运维场景:账号相关配置文件的可信基线管理。

具体做法是:在系统处于干净状态时,对/etc/passwd、/etc/shadow、/etc/group等文件计算一次 MD5,生成一份“基线清单”并妥善保存。之后可以定时、也可以在每次变更之后重新计算并比对。如果某次比对失败,说明这些文件被改动过,需要立刻确认改动来自谁、是否走了审批流程、改动内容是否合理。这套机制成本极低,却能在排查安全事件时提供非常有力的第一手线索。

对于刚入门的读者,这个案例还能顺带把 shell 脚本、循环、条件判断、退出码、定时任务这些知识点串起来练一遍,比单纯背命令要有价值得多。

2. 环境准备与版本说明

2.1 系统与权限要求

本文示例基于常见的 Linux 发行版编写,CentOS、Rocky Linux、Ubuntu、Debian 等主流系统都可以直接运行,具体命令参数以你系统中shadow-utils(RedHat 系)或passwd(Debian 系)自带版本为准,不同版本之间个别参数可能存在差异,遇到报错时优先用man查看本机手册。示例中的系统版本、内核版本不做限定,重点是掌握配置思路。

操作账号要求具备 root 权限或者等价的 sudo 权限。原因很直接:/etc/shadow和/etc/gshadow的权限通常是0000或000,普通用户连读都读不了,更不用说计算摘要。这里必须强调一句,以下所有涉及用户创建、删除、密码修改、系统文件操作的内容,都应当在你拥有合法授权的机器上进行;生产环境执行前先在测试机验证,并对关键配置文件做好备份。

2.2 涉及的工具与命令

本文会用到的核心命令包括:useradd、usermod、userdel、groupadd、passwd、chage、id、md5sum、find、crontab。其中md5sum属于 GNU Coreutils,绝大多数发行版默认自带,可以先执行md5sum --version确认一下。如果系统里没有,通过包管理器安装coreutils即可。

查看用户状态时,id 用户名可以一次性看到 UID、GID 和附加组;passwd -S 用户名能看到密码状态(是否锁定、是否设置);chage -l 用户名能看到完整的密码时效策略。这几个命令在排查“用户明明建好了却登不上”这类问题时特别有用,建议形成肌肉记忆。

2.3 实验目录结构

为了让后面的脚本不散落一地,我们先约定一个统一的目录。基线文件、校验日志、用户清单都放在/opt/user-audit下,结构如下:

/opt/user-audit/ ├── baseline/ # 基线指纹目录 │ ├── sys-account-20240101-120000.md5 │ └── current.md5 # 当前生效基线(副本) ├── logs/ # 校验日志 │ └── check-20240101-120000.log ├── users.csv # 批量建号的输入清单 └── bin/ ├── create_users.sh # 批量创建用户 ├── make_baseline.sh # 生成基线 └── check_accounts.sh # 执行校验

把脚本和数据分开放,好处是可维护性更强:脚本可以纳入版本管理,基线文件可以按时间戳归档,日志可以按需清理。如果直接全丢在/root下,过几个月你自己都分不清哪个文件是最新的。

3. Linux 用户管理核心操作拆解

3.1 三个核心配置文件的结构

先看/etc/passwd。它每行一个用户,字段用冒号分隔,依次是:用户名、密码占位符(通常是x,真正的哈希在 shadow 里)、UID、GID、描述信息、主目录、登录 shell。举个典型行:

devops:x:1001:1001:DevOps Account:/home/devops:/bin/bash

这里 UID 是重点。普通用户的 UID 一般从 1000 开始(Debian 系)或者 500 开始(早期 RedHat 系),系统账号则占用 0-999 区间。UID 为 0 的账号就是 root,哪怕是toor、admin这样的名字,只要 UID 是 0,就拥有超级用户权限。所以定期检查“有没有非预期账号的 UID 是 0”,是账号安全审计的必查项。

再看/etc/shadow,字段更多:用户名、加密密码、最后一次修改密码的时间(从 1970-01-01 起算的天数)、最小间隔天数、最大有效天数、过期前警告天数、不活动宽限天数、账号失效日期、保留字段。密码字段为!!或*表示该账号没有可用密码,通常意味着被锁定。这个文件只有 root 可读,它是我们后面 MD5 校验里最关键的目标。

最后是/etc/group,格式为:组名、组密码占位符、GID、成员列表(逗号分隔)。需要注意的是,用户在/etc/passwd里的 GID 只表示“主组”,附加组信息统一维护在这里。

3.2 useradd 的常用参数与默认行为

useradd是建号的主入口。一个比较完整的用法如下:

useradd -m \ -u 1500 \ -g devops \ -G docker,ops \ -s /bin/bash \ -c "Zhang San / Backend Team" \ -d /home/zhangsan \ zhangsan

逐项解释一下:-m表示创建主目录(这个参数一定要显式带上,很多系统的默认值是不创建);-u指定 UID,团队里通常需要统一规划号段;-g指定主组,组必须已存在;-G追加附加组;-s指定登录 shell,如果这个账号只用于跑服务,可以设为/sbin/nologin;-c写备注,方便日后审计时知道这个号是给谁的;-d指定主目录路径。

如果你不加这些参数,useradd会读取/etc/default/useradd和/etc/login.defs里的默认值。这也解释了一个常见困惑:为什么同样的命令,在不同机器上创建出来的主目录位置、shell、UID 号段都不一样。想统一行为,就去改这两个默认配置,而不是每次手动敲一遍参数。

3.3 usermod 与 userdel 的坑点

修改账号时usermod用得最多,但有两个坑必须提前说清楚。

第一个坑是附加组。想把用户加进一个新组,正确写法是:

usermod -aG docker zhangsan

-a表示“追加”,它必须和-G一起使用。如果你写成usermod -G docker zhangsan,效果不是“加入 docker 组”,而是“把用户的附加组重置为只有 docker”,原来的其他附加组全部丢失。这个错误在团队里非常常见,而且往往要等到某个服务突然没权限了才会被发现。

第二个坑是删除账号。userdel zhangsan只删除/etc/passwd、/etc/shadow、/etc/group里的记录,用户主目录和邮件池会保留下来。如果你想连家目录一起清理,用userdel -r zhangsan。但在生产环境直接-r是有风险的:如果这个用户的主目录里还跑着业务、或者目录属主被改成了别的账号,删除行为可能产生意料之外的后果。更稳妥的做法是:先usermod -L -s /sbin/nologin zhangsan锁定账号,观察一段时间确认无影响,再决定是否真正删除;删除前先tar打包家目录留档。

3.4 密码策略与账号时效管理

passwd不只能改密码,还有几个实用开关:passwd -l 用户名锁定账号,passwd -u 用户名解锁,passwd -e 用户名强制用户下次登录时修改密码,passwd -S 用户名查看当前状态。锁定操作实际上是在/etc/shadow的密码哈希前面加一个!,所以它不会破坏原密码,解锁后即可恢复。

账号时效策略用chage管理:

chage -M 90 -m 1 -W 7 -I 14 zhangsan

含义是最长 90 天必须改密码、两次修改间隔至少 1 天、过期前 7 天开始提醒、密码过期后账号还能用 14 天宽限。用chage -l zhangsan可以查看当前设置。对于临时外包账号或者实习生账号,还可以用chage -E 2024-12-31 zhangsan直接设置账号失效日期,到期自动不可用,比靠人记着去删号可靠得多。

4. MD5 校验原理与命令用法

4.1 md5sum 的基本使用

md5sum的用法非常简单,直接跟文件路径:

md5sum /etc/passwd

输出形如d41d8cd98f00b204e9800998ecf8427e /etc/passwd(这里只是示意格式,实际值以你的系统为准)。注意文件名前面是两个空格,这是文本模式的标记;如果加了-b参数走二进制模式,中间会变成*。这个差异在写校验文件时需要注意,虽然-c校验时两种格式都能识别。

批量计算可以用通配符或者find:

md5sum /etc/passwd /etc/shadow /etc/group /etc/gshadow

如果只想看哈希值不要文件名,可以配合awk:

md5sum /etc/passwd | awk '{print $1}'

反过来,拿到一份校验清单后,可以用-c一次性核对:

md5sum -c sys-account.md5

清单里每一行会输出“文件名: OK”或“文件名: FAILED”,命令的退出码也能反映结果:全部匹配返回 0,有任何不一致返回非 0。这一点非常关键,因为它让md5sum -c可以直接嵌入到脚本和定时任务里,靠退出码驱动告警逻辑,而不需要去解析文本输出。

4.2 保存哈希时要注意的细节

有两点容易被忽略。

第一,哈希值本身不是秘密,但哈希清单会泄露文件内容的“指纹”。如果你的基线文件里包含了/etc/shadow的 MD5,虽然不能反推密码,但攻击者拿到基线后可以判断某个文件是否被改过,甚至可以做离线比对。所以基线文件本身的权限要收紧,建议放到/opt/user-audit/baseline下并设置为600,属主 root。

第二,生成清单时建议使用绝对路径。md5sum -c是按清单里记录的路径去找文件的,如果生成时用的是相对路径,后续在别的目录执行校验就会失败。上面的脚本里我们统一传绝对路径,就是为了避开这个坑。

4.3 MD5 的边界:能防什么,不能防什么

再强调一次边界问题,因为这直接决定你的方案设计是否合理。

MD5 能防的:传输过程中的比特翻转、磁盘静默损坏、人为误操作导致的文件内容变化、复制粘贴时的内容丢失。这些都是“非对抗性”的完整性问题,MD5 完全够用。

MD5 不能防的:有意的碰撞构造、攻击者在改文件的同时把基线文件一起改掉、攻击者拿到 root 后重新生成一份“看起来正常”的基线。所以完整性校验必须配合其他手段才有意义,比如把基线文件同步到另一台机器或者对象存储、日志写到远端、以及对基线文件本身也设置不可变属性(chattr +i)来增加篡改成本。

如果你的场景需要更强的抗攻击能力,sha256sum是更合适的选择,命令参数与md5sum完全一致,脚本里换个命令名即可。本文继续用 MD5 演示,是因为标题和场景都聚焦在“快速核对”这个轻量需求上。

5. 完整实战:用户管理 + 配置文件完整性校验

这一节把前面的知识点串成一个可运行的小项目。整体流程是:准备用户清单 → 批量建号 → 生成基线指纹 → 编写校验脚本 → 手动验证一次改动 → 接入定时任务。

5.1 初始化目录与用户清单

先建目录并收紧权限:

mkdir -p /opt/user-audit/{baseline,logs,bin} chmod 700 /opt/user-audit chmod 700 /opt/user-audit/baseline

然后准备users.csv,格式为用户名,UID,附加组,shell,备注:

zhangsan,1500,docker, /bin/bash,Zhang San Backend lisi,1501,docker, /bin/bash,Li Si Backend wangwu,1502,, /sbin/nologin,Wang Wu Service Account

注意第三行的附加组留空,脚本里要能处理这种情况。

5.2 编写批量创建脚本

文件路径:/opt/user-audit/bin/create_users.sh

#!/bin/bash # 批量创建用户,具备幂等性:已存在的用户直接跳过 set -euo pipefail CSV_FILE="${1:-/opt/user-audit/users.csv}" if [[ ! -f "$CSV_FILE" ]]; then echo "ERROR: csv file not found: $CSV_FILE" >&2 exit 1 fi while IFS=',' read -r username uid groups shell comment; do # 跳过空行与注释行 [[ -z "${username// }" ]] && continue [[ "$username" == \#* ]] && continue # 字段去空格 username="$(echo "$username" | xargs)" uid="$(echo "$uid" | xargs)" groups="$(echo "$groups" | xargs)" shell="$(echo "$shell" | xargs)" comment="$(echo "$comment" | xargs)" if id "$username" &>/dev/null; then echo "SKIP: user $username already exists" continue fi args=(-m -u "$uid" -s "$shell" -c "$comment") if [[ -n "$groups" ]]; then args+=(-G "$groups") fi useradd "${args[@]}" "$username" echo "CREATED: $username (uid=$uid, shell=$shell)" done < "$CSV_FILE" echo "done."

几个设计点解释一下。第一,脚本用id 用户名判断用户是否已存在,这是幂等的关键——重复执行不会报错,也不会覆盖已有账号。第二,参数用数组拼接,避免空值导致useradd -G ""这种非法参数。第三,xargs用来去掉 CSV 里可能存在的首尾空格,实际项目里从 Excel 导出的文件几乎一定会有空格。第四,set -euo pipefail让脚本在出错时立即停止,而不是带着错误继续往下跑。

给脚本加执行权限并运行:

chmod +x /opt/user-audit/bin/create_users.sh /opt/user-audit/bin/create_users.sh

预期输出类似:

CREATED: zhangsan (uid=1500, shell=/bin/bash) CREATED: lisi (uid=1501, shell=/bin/bash) CREATED: wangwu (uid=1502, shell=/sbin/nologin) done.

如果你把脚本再执行一遍,应该看到三行SKIP,这说明幂等生效了。

5.3 生成账号文件基线

文件路径:/opt/user-audit/bin/make_baseline.sh

#!/bin/bash # 对账号相关配置文件生成 MD5 基线 set -euo pipefail BASE_DIR="/opt/user-audit/baseline" TARGETS=( /etc/passwd /etc/shadow /etc/group /etc/gshadow /etc/login.defs /etc/default/useradd ) mkdir -p "$BASE_DIR" STAMP="$(date +%Y%m%d-%H%M%S)" OUT_FILE="$BASE_DIR/sys-account-$STAMP.md5" : > "$OUT_FILE" for f in "${TARGETS[@]}"; do if [[ -f "$f" ]]; then md5sum "$f" >> "$OUT_FILE" else echo "WARN: target not found, skipped: $f" >&2 fi done chmod 600 "$OUT_FILE" cp -f "$OUT_FILE" "$BASE_DIR/current.md5" chmod 600 "$BASE_DIR/current.md5" echo "baseline created: $OUT_FILE" echo "lines: $(wc -l < "$OUT_FILE")"

这里用时间戳命名归档,同时复制一份为current.md5作为“当前生效基线”,校验脚本只认current.md5。这样后续想要更新基线,只需要重新跑一次脚本,历史版本会自动保留,出问题时可以回溯对比。

执行:

chmod +x /opt/user-audit/bin/make_baseline.sh /opt/user-audit/bin/make_baseline.sh

输出大约是:

baseline created: /opt/user-audit/baseline/sys-account-20240101-120000.md5 lines: 6

可以用cat看一眼内容,确认每行都是绝对路径:

cat /opt/user-audit/baseline/current.md5

5.4 编写校验脚本

文件路径:/opt/user-audit/bin/check_accounts.sh

#!/bin/bash # 校验账号配置文件是否与基线一致 set -uo pipefail BASE_DIR="/opt/user-audit/baseline" LOG_DIR="/opt/user-audit/logs" BASELINE="$BASE_DIR/current.md5" STAMP="$(date +%Y%m%d-%H%M%S)" LOG_FILE="$LOG_DIR/check-$STAMP.log" mkdir -p "$LOG_DIR" if [[ ! -f "$BASELINE" ]]; then echo "[$STAMP] FATAL: baseline missing: $BASELINE" | tee -a "$LOG_FILE" exit 2 fi TMP_OUT="$(mktemp)" if md5sum -c --quiet "$BASELINE" > "$TMP_OUT" 2>&1; then echo "[$STAMP] OK: account files match baseline" | tee -a "$LOG_FILE" rm -f "$TMP_OUT" exit 0 else echo "[$STAMP] ALERT: account files changed" | tee -a "$LOG_FILE" cat "$TMP_OUT" >> "$LOG_FILE" rm -f "$TMP_OUT" exit 1 fi

脚本里刻意没有用set -e,而是用set -uo pipefail,因为md5sum -c在发现不一致时本身就会返回非 0,如果用set -e,脚本会直接退出,我们精心准备的日志和分类信息就写不进去了。这里的思路是“手动接管错误处理”:用if判断退出码,分别走成功和告警两条路径。

退出码的设计也有讲究:0表示正常,1表示有文件被改动,2表示基线缺失这类环境问题。有了明确的退出码,上层监控系统就能区分“真的出事了”和“配置没准备好”,避免告警风暴。

5.5 运行验证与结果说明

先跑一次正常校验:

chmod +x /opt/user-audit/bin/check_accounts.sh /opt/user-audit/bin/check_accounts.sh echo "exit code: $?"

预期输出:

[20240101-121000] OK: account files match baseline exit code: 0

现在制造一次改动,验证告警是否生效。这一步一定要在测试机上做,生产环境请勿随意改动账号文件:

useradd -m -u 1600 -s /bin/bash testuser /opt/user-audit/bin/check_accounts.sh echo "exit code: $?"

预期输出类似:

[20240101-121500] ALERT: account files changed /etc/passwd: FAILED /etc/shadow: FAILED /etc/group: FAILED exit code: 1

可以看到md5sum -c会把具体哪个文件不一致列出来,这正是我们排查时最需要的信息。确认这次改动是预期行为后,重新生成基线:

/opt/user-audit/bin/make_baseline.sh /opt/user-audit/bin/check_accounts.sh

此时应该恢复为OK。这个“变更 → 告警 → 审批 → 重建基线”的闭环,就是整套方案的核心工作流。

5.6 接入定时任务

最后用 crontab 让它每天自动跑一次:

crontab -e

写入:

# 每天 02:30 校验账号配置文件完整性 30 2 * * * /opt/user-audit/bin/check_accounts.sh >> /opt/user-audit/logs/cron.log 2>&1

crontab执行环境和你交互式 shell 的 PATH 可能不同,所以脚本里涉及的命令全部用了绝对路径或者系统自带路径,能极大降低“手动跑没问题、定时任务就是跑不起来”的概率。日志追加到cron.log,方便集中查看。

如果你需要把告警推送到监控系统,可以在脚本的ALERT分支里追加一行curl调用 webhook,或者把日志接入日志采集组件。具体对接方式取决于你所在团队的技术栈,这里不做硬编码。

6. 常见问题与排查思路

问题现象常见原因解决思路
useradd执行后没有生成主目录系统默认CREATE_HOME为 no,或命令未加-m显式使用useradd -m,或修改/etc/login.defs中的CREATE_HOME yes
用户加入新组后原有附加组丢失使用了usermod -G而不是usermod -aG重新补齐全部附加组,或改用gpasswd -a 用户 组追加
md5sum -c报No such file or directory基线文件里记录的是相对路径生成基线时使用绝对路径;或在校验前cd到生成时的目录
校验脚本手动跑正常,定时任务报错cron 环境变量精简,PATH 不含自定义命令脚本内统一使用绝对路径,或在脚本开头显式设置 PATH
校验结果频繁告警系统有其他工具会写这些文件(如自动化运维平台、认证组件)先定位写入来源,再决定是纳入白名单还是调整基线更新频率
md5sum -c输出Permission denied非 root 执行,无法读取/etc/shadow用 root 或带 sudo 的执行身份运行脚本与定时任务
基线文件被同步工具覆盖基线目录位于某些自动同步或备份路径下把基线目录排除在自动同步之外,或对基线文件设置chattr +i
修改密码后校验立刻失败passwd会改写/etc/shadow,属于正常变更走正常变更流程,确认后在维护窗口重建基线
userdel -r后残留文件或报错用户进程仍在运行,或主目录存在非属主文件先pkill -u 用户名或用lsof检查占用,再执行删除
UID 冲突导致建号失败规划号段重叠,或与已有系统账号 UID 相同建号前用getent passwd 1500检查占用,统一维护 UID 号段表

排查这类问题时,一个通用的顺序是:先看退出码,再看日志,最后看具体文件状态。比如校验失败时,先执行echo $?确认是 1 还是 2,1 就往“文件被改”方向查,2 就往“基线缺失、权限不足”方向查。这个习惯能省下大量无谓的猜测。

7. 最佳实践与工程建议

7.1 账号命名与 UID 规划

账号命名建议统一规则,比如“姓名拼音 + 用途后缀”,服务账号加svc_前缀。这样在/etc/passwd里一眼就能区分人和服务。UID 号段一定要提前规划,不要让系统自动分配,否则不同机器的 UID 会乱掉,跨机共享目录的权限就会出问题。常见做法是:1000-1999 给普通员工,2000-2999 给服务账号,3000 以上留给临时账号。

服务账号的 shell 建议设为/sbin/nologin或/bin/false,并加上-r参数创建为系统账号。这类账号只需要能运行进程,不需要交互登录,限制 shell 是最简单的收敛手段。

7.2 配置文件变更管理

/etc/passwd、/etc/shadow这类文件必须纳入变更管理。原则是:任何手工修改都要留记录,任何自动化工具写入都要走审批。本文的基线校验只是“事后发现”,真正的治理要靠“事前约束”——比如限制谁能执行useradd、谁能读 shadow、把高危命令纳入命令审计。

另外,基线更新不能太随意。如果每次告警就无脑重建基线,那这套机制等于失效。正确做法是:告警后先定位变更来源,确认是预期变更再更新基线,并把这次变更记录下来。基线文件本身建议保留最近 N 个版本,方便回溯。

7.3 密码与凭据安全

不要在脚本里硬编码明文密码,也不要用echo "密码" | passwd --stdin这种在命令行暴露密码的方式。如果必须批量设置初始密码,可以用openssl rand生成随机密码写入临时文件,权限设为 600,用户首次登录强制修改(chage -d 0 用户名),用完立即删除临时文件。

再次提醒,MD5 不适合做密码存储。如果你在自研系统里需要存密码,请使用 bcrypt、scrypt 或者 Argon2 这类专门为密码设计的算法,它们自带盐值和可调计算成本,能有效抵抗彩虹表和暴力破解。

7.4 校验系统的可靠性设计

一个能长期跑下去的校验系统,需要注意几个工程细节。日志要有轮转,否则一年后logs目录能撑爆磁盘,可以用logrotate配置按天切分、保留 30 天。告警要能区分严重程度,配置文件变化是高优先级,基线缺失是中优先级,不能混在一起发。校验频率要合理,一天一次对大多数场景够用,如果对实时性要求高,可以改成每 10 分钟一次,但要评估 IO 开销。

最后,校验范围不要无限扩大。如果对整个/etc做 MD5,会包含大量经常变化的文件(如网络配置、日志轮转配置),导致告警噪音过大,最后没人看。聚焦在真正关键、变更频率低的文件上,才是可持续的做法。账号相关的四五个文件,正好符合这个特征。

8. 学习路线与延伸方向

如果把这篇内容当成一个起点,接下来可以按三个方向继续深入。

第一个方向是账号体系本身。继续研究 PAM 认证框架,理解pam_unix、pam_tally2、pam_faillock这些模块如何控制登录失败锁定;研究 sudo 的精细化授权,用visudo配置“某个用户只能以某个身份执行某几条命令”;研究 LDAP 或统一身份认证方案,理解大规模环境下为什么不再依赖本地/etc/passwd。这些内容会让你从“会建号”走到“会治理账号”。

第二个方向是文件完整性监控。本文用的是最朴素的基线比对,工业级方案可以参考 AIDE、Tripwire 这类工具的设计思路:它们支持规则配置、排除列表、数据库存储、多级告警,并且会对文件属性而不只是内容做校验。理解它们的原理之后,你会发现核心思想和我们这个几十行的脚本是一致的,只是工程化程度不同。

第三个方向是脚本工程化。把本文的三个脚本改造成带参数解析、带--dry-run试运行、带日志级别、带退出码规范的版本,再配上一套简单的测试用例,就是一个很好的 shell 工程练习。能在 shell 里把错误处理、幂等性、日志、配置分离这几件事做扎实,后面写 Ansible Playbook 或者运维平台代码会轻松很多。

实操建议是:不要只看不练。找一台虚拟机,把 5.1 到 5.6 的流程完整走一遍,故意制造几次失败场景——比如把/etc/shadow权限改错、把基线文件删掉、用普通用户执行脚本,看看各自的报错长什么样。排错经验是敲出来的,不是看出来的。等你把这些异常都见过一遍,再遇到线上问题时,判断会快很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询