Appearance
06|日常运维操作规范
运维事故里,很少有"命令敲错了"——多数是"命令没错,但删错了对象、范围太大、没有退路"。同样一个 rm,删 /tmp/old.log 没事,删 /data/mysql 就是灾难。差别不在命令,在执行的范围、对象和有没有回滚。
本篇讲操作时怎么防这些事:危险命令怎么确认、批量操作怎么防误删、变更怎么留退路、操作怎么留痕。这些不是流程的形式主义,是减少事故的实际手段。
一、操作分级
按影响面和可逆程度分级,不同级别对应不同流程:
| 类型 | 例子 | 处理方式 |
|---|---|---|
| 只读 | tail、systemctl status、配置查阅 | 按需执行 |
| 低风险 | 改日志级别、调监控阈值、加非关键 cron | 记录变更和回滚方式 |
| 中风险 | 重启单个实例、发布非核心服务 | 低峰窗口、确认影响、备好回滚 |
| 高风险 | 数据库 DDL、批量删除、防火墙策略、核心服务重启 | 工单+审批+双人复核+回滚演练 |
| 应急 | 服务中断 | 恢复优先,尽量留痕,事后补复盘 |
一个操作带"批量"和"删除"两个属性,风险等级自动提升一档。
二、操作前确认
连上机器后第一件事不是动手,是确认对象:
bash
hostname # 正确机器?
hostname -I # IP 也对?
whoami # 账号对?
pwd # 目录对?四条命令,两秒钟,能挡住连错机器、用错账号、进错目录这类低级但常见的问题。
变更前的检查清单
| 检查项 | 确认什么 |
|---|---|
| 机器身份 | 主机名、IP、环境、集群角色 |
| 当前状态 | 服务正常?有未处理告警?正在被其他变更占用? |
| 操作账号 | 是不是该用的用户?会不会不小心用了 root? |
| 影响范围 | 单机?某个可用区?全集群? |
| 上下游依赖 | 谁在调用?依赖哪个数据库/队列/缓存? |
| 回滚方式 | 配置备份在哪?版本回退命令?数据恢复方法和时长? |
| 观察指标 | 改完后看哪个监控、哪段日志? |
看当前基线
bash
systemctl status nginx --no-pager # 服务状态
journalctl -u nginx -n 50 --no-pager # 最近日志
ss -lntp # 监听端口--no-pager 防止输出卡在 less 里。
三、操作窗口
选窗口要看的不只是业务低峰:
- 有人能响应——出了事不是孤军奋战
- 上下游有人——网络、DB、应用能在同一时间响应
- 监控正常——改完能观察到指标变化
- 避开并发变更——出了问题分不清原因
数据库结构变更、网络策略收敛、批量重启不适合卡在下班前做。 白天"人都在、业务相对低峰"的窗口比半夜更安全——半夜人困反应慢、能帮忙的人少。
四、回滚方案
"支持回滚"不等于能回滚——要能写出回滚命令。
配置类变更
bash
# 变:前备份
cp -a /etc/nginx/nginx.conf /etc/nginx/nginx.conf.$(date +%F-%H%M%S).bak
# 改:完后检查
nginx -t && systemctl reload nginx
# 回滚
cp /etc/nginx/nginx.conf.2026-05-21-230000.bak /etc/nginx/nginx.conf
nginx -t # 旧配置不一定是错的,环境可能已变
systemctl reload nginx旧配置备份不一定还对——环境可能已经变了。回滚也要走"检查→加载"流程。
版本类回滚(软链接)
text
/opt/myapp/releases/
├── 20260521-2100/
├── 20260521-2230/
└── current -> /opt/myapp/releases/20260521-2230bash
ln -sfn /opt/myapp/releases/20260521-2100 /opt/myapp/current
systemctl restart myapp-n 不可少——否则会在原目录内部创建链接,不是替换 current。
数据库变更
DDL、数据修复、批量删除——"从备份恢复"四个字不够。需要评估:恢复要多久?会不会覆盖新数据?业务能不能等?
五、双人确认
另一个人看着屏幕,与真正的双人确认是两回事。 双人确认是让另一个人独立审视关键事实。
哪些操作需要双人确认
| 操作 | 复核要点 |
|---|---|
| 批量删除 | 目录、匹配条件、备份存在 |
| 数据库变更 | 库名、表名、WHERE、字段、备份 |
| 防火墙调整 | 源地址、目标端口、回滚入口、会不会锁自己 |
| 生产重启 | 剩余实例数、流量已摘除、健康检查正常 |
| 权限开通 | 用户、资产范围、账号级别、有效期 |
确认时说明意图
准备删除 /data/app/tmp 下 7 天前的临时文件。
不涉及 /data/app/upload。
已确认备份不依赖 tmp 目录的内容。
先 find -print 看范围,确认后再执行删除。完整意图描述比裸贴命令更容易让对方发现问题。
六、危险命令防护
rm
bash
# 先看范围
find /data/app/tmp -type f -mtime +7 -print
# 确认后删除
find /data/app/tmp -type f -mtime +7 -delete变量拼接路径的 rm 必须检查:
bash
target_dir="${1:-}"
if [ -z "$target_dir" ] || [ "$target_dir" = "/" ]; then
echo "invalid target dir: $target_dir" >&2
exit 1
fi
rm -rf -- "$target_dir"/*-- 防止文件名以 - 开头被当成选项。
rsync --delete
预演不是可选步骤:
bash
rsync -avh --delete --dry-run /srv/app/dist/ web@host:/var/www/app/路径写错时,rsync 会很认真地把目标端删干净。
chmod / chown
bash
# 先看现状
find /opt/myapp -maxdepth 2 -printf '%m %u:%g %p\n' | head
# 再执行
chown -R app:app /opt/myapp
chmod -R u=rwX,go=rX /opt/myappX(大写)只给目录和已有执行位的文件加执行权限,不会给纯数据文件加执行位。 和 chmod -R 755 不同。
在系统目录做递归权限修改的破坏性极大——应定位到具体文件,而不是全局放开。
kill
bash
systemctl stop service # 标准
kill -TERM <pid> # 请求进程正常退出:关闭连接、清理文件、写日志
kill -KILL <pid> # 强制终止:不给清理机会数据库进程被 kill -9 后,可能需要 crash recovery,比正常关闭慢得多。
七、批量操作
全量批量命令把风险放大了 N 倍。安全的做法:单台验证→分批推进:
bash
# 第 1 步:单台验证
head -1 hosts.txt | while read -r host; do
ssh "$host" 'hostname; systemctl restart myapp; systemctl is-active myapp'
done
# 第 2 步:串行分批
while read -r host; do
echo "=== $host ==="
ssh "$host" 'systemctl restart myapp && systemctl is-active --quiet myapp'
sleep 10 # 给监控和均衡器时间
done < hosts.txt
# 第 3 步:控制并发(xargs -P)
cat hosts.txt | xargs -I{} -P 5 sh -c '
ssh "$1" "systemctl restart myapp && systemctl is-active --quiet myapp"
' sh {}串行分批虽慢,但每一步可控。生产批量操作不追求速度,追求影响范围最小。
-P 的并发数要按容量决定:8 个实例,每个 CPU 已 60%,一次重启 5 个会让剩下 3 个扛全部流量,错误率会上升。
八、操作记录与留痕
最低要求记录
| 项目 | 内容 |
|---|---|
| 操作人 | 堡垒机用户 |
| 时间 | 开始和结束 |
| 目标 | 主机、服务、数据库、集群 |
| 关键命令 | 执行了什么,用的哪个版本 |
| 结果 | 成功/失败,回滚是否成功 |
| 证据 | 日志片段、监控截图 |
终端记录
bash
# 用 script 记录会话
script -a /var/log/ops/$(date +%F-%H%M%S)-change.log
# 退出:exitbash
# 脚本输出到日志
./deploy.sh 2>&1 | tee deploy-$(date +%F-%H%M%S).log九、变更后观察
| 检查项 | 怎么确认 |
|---|---|
| 服务正常 | systemctl status service --no-pager |
| 无新错误 | journalctl -u service -n 100 --no-pager |
| 端口监听 | ss -lntp |
| 健康检查 | curl -fsS http://127.0.0.1:8080/healthz |
| 业务指标 | QPS、错误率、延迟对比变更前 |
| 系统指标 | CPU、内存、磁盘、网络异常波动 |
多实例变更:只看单机健康不够。 实例本机 /healthz 已 200,但负载均衡没流量——可能没重新加入。所有实例健康,整体 5xx 上涨——服务发现、入口转发、下游依赖。
十、应急操作
故障中节奏快、压力大,但几条底线要守住:
| 原则 | 做法 |
|---|---|
| 恢复优先 | 降级、摘流量、扩容、回滚——先恢复,再研究根因 |
| 少做不可逆操作 | 删数据、清日志、重建集群——可能让故障变事故 |
| 保留现场 | 关键日志、错误信息、时间点——事后复盘必需 |
| 单点指挥 | 避免多人同时改同一系统 |
| 事后补齐 | 应急时来不及写,恢复后立即补上 |
保留现场
bash
mkdir -p /tmp/incident-$(date +%F-%H%M%S)
cd /tmp/incident-*
hostname > host.txt
date > date.txt
ip addr > ip-addr.txt
ip route > ip-route.txt
ss -antp > ss-antp.txt
journalctl -n 500 --no-pager > journal-last-500.txt十一、操作记录模板
text
变更名称:
操作人:
操作时间:
目标环境:
目标主机:
变更内容:
影响范围:
回滚方案:
操作前状态:
执行命令:
操作后验证:
异常与处理:模板的作用不是把流程变复杂,而是让自己第二天打开还能看懂: 当时为什么做、做了什么、结果怎样、出问题怎么退。