Skip to content

日常运维操作规范

运维操作的风险不在命令本身,在命令执行的范围、对象和有没有退路。同样的 rm,删一个临时文件和删整个数据目录,后果完全不一样。这篇整理日常操作流程里几个关键节点:操作分级、变更前确认、回滚准备、危险命令控制、操作留痕。这些不是流程的形式主义,是减少事故的实际手段。

一、操作分级

查一条日志和重启核心数据库,风险不一样,流程也应该不一样。按影响面和可逆程度,大致分几类:

类型例子处理方式
只读操作tail -fsystemctl statuscat 配置影响小,但要防误进入编辑模式——vim 里不小心按了 dd 这种
低风险变更改日志级别、调监控阈值、加一条非关键 cron记录改了什么、怎么退回来
中风险变更重启单个业务实例、发布非核心服务选业务低峰窗口、确认影响范围、准备回滚命令
高风险变更数据库结构变更、批量删除、防火墙策略调整、核心服务重启工单驱动、审批确认、双人复核、回滚方案事先演练
应急操作线上故障、服务中断以恢复服务为第一优先级,操作过程尽量留痕,恢复后补复盘

一个操作如果带"批量"和"删除"这两个属性,风险等级要往上提一档。单机的一条危险命令,在批量循环里可能变成一次小规模事故。

二、操作前确认

连上机器后第一件事不是动手,是确认对象。尤其在多窗口、多标签页、堡垒机同时开着几台机器的时候:

bash
hostname
hostname -I
whoami
pwd

四条命令,两秒钟,能挡住连错机器、用错账号、进错目录这种低级但常见的问题。

变更前把几件事想清楚:机器身份(主机名、IP、哪个环境、集群里的角色)、当前状态(服务是否正常、有没有未处理告警、是否正被其他变更占用)、操作账号(是不是该用的用户、会不会不小心用了 root)、影响范围(单机、单可用区、还是全集群)、上下游依赖(上面谁在调用、下面依赖哪个数据库/队列/缓存)、回滚方式(配置回退的备份在哪、版本回退的命令、数据恢复的方式和时间)、观察指标(改完后看哪几个监控、哪段日志)。

操作前看服务当前是否正常:

bash
systemctl status nginx --no-pager
journalctl -u nginx -n 50 --no-pager

--no-pager 避免输出停在 less 里——脚本里或远程批量执行时,卡在分页器等于卡死整条流程。

看当前监听和连接数:

bash
ss -lntp
ss -antp | grep ':80'

如果准备改 Nginx 配置,要先知道它现在是否正常监听、当前有多少连接。服务本来就异常了,改完配置后的行为不能简单归因于这次变更——这种"归因错误"在故障复盘里经常出现。

三、操作窗口

选操作窗口要看的不只是业务低峰:还要有人能响应(出了事不是孤军奋战)、上下游有人(网络、DB、应用、业务方能在同一段时间内响应)、监控正常(改完能观察到指标变化,不会因为监控本身挂了漏掉问题)、避开并发变更(多个变更同时进行,出了问题哪个导致的都分不清)。

数据库结构变更、网络策略收敛、批量重启这类操作,不适合卡在下班前做——做完了人都走了,没人观察。第二天再发现问题,现场信息已经少了很多。高风险变更放在"人都在、业务相对低峰"的时间,比单纯追求半夜更安全——半夜人困、反应慢、能帮忙的人也少。

四、回滚方案

只说"支持回滚"等于没说,要能真的写出回滚命令

配置变更前,备份原文件:

bash
cp -a /etc/nginx/nginx.conf /etc/nginx/nginx.conf.$(date +%F-%H%M%S).bak

cp -a 保留原文件的权限、时间戳和链接属性,配置回退时这些信息有用。

修改之后先检查语法,确认通过再加载:

bash
nginx -t
systemctl reload nginx

回滚时同样要先检查语法:

bash
cp -a /etc/nginx/nginx.conf.2026-05-21-230000.bak /etc/nginx/nginx.conf
nginx -t                    # 旧配置≠一定正确,期间环境可能已经变了
systemctl reload nginx

关键点:旧配置备份不一定还是对的——备份之后到回滚之前,环境可能已经变了(比如依赖的 upstream 加了新服务器)。所以回滚也要走"检查 → 加载"的流程,不是无脑覆盖。

应用发布如果用软链接切版本,回滚比覆盖式发布清晰得多:

text
/opt/myapp/releases/
├── 20260521-2100/
├── 20260521-2230/
└── current -> /opt/myapp/releases/20260521-2230

切回旧版本只需更新软链接:

bash
ln -sfn /opt/myapp/releases/20260521-2100 /opt/myapp/current
systemctl restart myapp

ln -sfn 中的 -n 很重要——如果 current 已经是一个指向目录的软链接,不加 -n 会在原目录内部创建链接,而不是替换 current 本身。

数据库变更的回滚最复杂。DDL、数据修复、批量删除——靠"备份恢复"四个字是不够的。需要知道恢复要多久、会不会覆盖新数据、业务能不能等这么久。操作前就评估清楚,而不是出了问题再想。

五、双人确认

另一个人站在旁边看着屏幕,和真正的双人确认是两回事。双人确认是让另一个人独立审视关键事实,不是"帮我看下这个命令写得对不对"。

需要双人确认的操作:批量删除(复核目录对不对、匹配条件对不对、有没有备份)、数据库变更(复核库名、表名、WHERE 条件、字段、有没有先备份)、防火墙调整(复核源地址、目标端口、会不会把自己挡在外面、有没有回滚入口)、生产重启(复核剩余实例数、流量是否已摘除、健康检查是否正常)、权限开通(复核用户是谁、资产范围、账号级别、有效期)。

确认时要说明意图,不只是把命令贴过去让人看:

text
准备删除 /data/app/tmp 下 7 天前的临时文件。
不涉及 /data/app/upload。
已确认备份不依赖 tmp 目录的内容。
先执行 find -print 看范围,确认后再执行删除。

完整的意图描述比裸贴一条命令更容易让人发现问题——对方可能会想到你没想到的东西,比如"tmp 里是不是有一周的部署回滚包"。

六、危险命令防护

rm

删除前先用 find -print 看将要操作的范围:

bash
find /data/app/tmp -type f -mtime +7 -print

确认文件列表符合预期,再删除:

bash
find /data/app/tmp -type f -mtime +7 -delete

rm -rf 配合变量使用时风险很高:

bash
rm -rf $dir/*

如果 $dir 变成空字符串,这条命令实际执行的可能是 rm -rf /*。脚本里至少要有变量检查:

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"/*

-- 告诉命令"后面的参数都是路径,不是选项"——防止文件名以 - 开头(比如有人创建了 -rf 文件)被当成选项处理。

rsync --delete

预演是必须的步骤,不是可选的:

bash
rsync -avh --delete --dry-run /srv/app/dist/ web@192.168.10.30:/var/www/app/

--delete 本身没问题,问题出在源路径和目标路径写错。路径写错时,rsync 会很认真地把写错的那个目录删干净

chmod 和 chown

递归改权限前,先确认范围和当前状态:

bash
find /opt/myapp -maxdepth 2 -printf '%m %u:%g %p\n' | head

再执行:

bash
chown -R app:app /opt/myapp
chmod -R u=rwX,go=rX /opt/myapp

X(大写)表示只给目录和原本就有执行位的文件加执行权限。chmod -R 755 的区别是:X 不会给普通数据文件(.conf.html.log)加上执行权限。应用目录里适合用 X,而不是无差别给所有文件加执行位。

在系统目录做递归权限修改的破坏性极大:

bash
chmod -R 777 /var   # 把权限体系打穿

遇到权限问题时,应该定位具体的文件和进程用户做针对性调整,而不是用全局放开来解决一个局部问题。

kill

先从正常停止开始:

bash
systemctl stop nginx

再考虑发信号:

bash
kill -TERM <pid>    # 请求进程正常退出:关闭连接、清理临时文件、写日志
kill -KILL <pid>    # 强制终止:不给进程任何清理机会

kill -9(等于 kill -KILL)只是把进程的存在抹掉,不代表服务状态恢复,也不给进程清理连接和文件状态的机会。数据库进程被 kill -9 后,恢复时可能要做 crash recovery,比正常关闭后再启动慢很多。

七、批量操作

全量批量操作把"一条命令的影响"放大了 N 倍:

bash
for host in $(cat hosts.txt); do
    ssh "$host" 'systemctl restart myapp'
done

安全的做法是先单台验证,再分批推进:

bash
# 第一步:只挑一台验证
head -n 1 hosts.txt | while read -r host; do
    ssh "$host" 'hostname; systemctl restart myapp; systemctl is-active myapp'
done

# 第二步:确认单台没问题后,串行分批
while read -r host; do
    echo "restart $host"

    ssh "$host" '
        set -e
        systemctl restart myapp
        systemctl is-active --quiet myapp
    '

    sleep 10   # 给监控和负载均衡观察和摘除的时间
done < hosts.txt

串行分批虽然慢,但每一步都可控。生产环境的批量操作不追求速度,追求失败时影响范围最小

需要并发时,用 xargs -P 限制并发数:

bash
cat hosts.txt | xargs -I{} -P 5 sh -c '
    host="$1"
    echo "restart $host"
    ssh "$host" "systemctl restart myapp && systemctl is-active --quiet myapp"
' sh {}

-P 5 限制最多同时跑 5 个。并发数要按服务容量和负载均衡摘除策略来定。比如总共 8 个实例,单个实例平时 CPU 已经 60%,一次重启 5 个会让剩下 3 个扛全部流量,错误率很容易上去;如果负载均衡健康检查需要 30 秒才摘除异常实例,重启间隔还要把这段时间算进去。

八、操作留痕

操作过程需要能被追溯,至少记录:操作人(堡垒机用户、目标系统用户)、时间(开始和结束)、目标(主机、服务、数据库、集群)、关键命令(执行了什么、用的哪个版本的脚本)、结果(成功还是失败,失败有没有回滚、回滚是否成功)、证据(日志片段、监控截图、工单链接)。

script 记录整个终端会话:

bash
script -a /var/log/ops/$(date +%F-%H%M%S)-change.log

退出记录时输入 exit

单条脚本用 tee 留日志:

bash
./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、内存、磁盘、网络有没有异常波动

curl -fsS 的判断逻辑:-f 在 HTTP 4xx/5xx 时返回非 0,脚本里可以直接用退出码判断健康检查是否通过。如果用浏览器打开页面,状态码 500 和 200 在视觉上可能看不出差别

多实例的变更,只看单机健康不够。比如刚重启的实例本机 /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

这只是最基础的现场快照,不是完整的故障诊断流程。内容可能包含敏感信息(IP 地址、连接信息),保存和使用时注意。对于某些严格环境,这些采集命令本身也需要纳入操作审批

十一、操作记录模板

text
变更名称:
操作人:
操作时间:
目标环境:
目标主机:

变更内容:
影响范围:
回滚方案:

操作前状态:
执行命令:
操作后验证:
异常与处理:

模板的作用不是把流程变复杂,而是让自己第二天打开还能看懂:当时为什么做这件事、做了什么、结果怎样、出了问题怎么退。