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

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

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 /* 或者 rm -rf /some/default/*。脚本里至少要有变量检查:

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 个。并发数要结合服务容量和负载均衡摘除策略来定——比如 5 个实例同时重启,剩下的是否能扛住全部流量。

八、操作留痕

操作过程需要能被追溯。至少记录这些:

内容具体是什么
操作人堡垒机用户、目标系统用户
时间开始时间和结束时间
目标主机、服务、数据库、集群
关键命令执行了什么命令,用的哪个版本的脚本
结果成功还是失败;如果失败,有没有回滚,回滚是否成功
证据日志片段、监控截图、工单链接

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 在视觉上可能看不出差别。

多实例的变更,只看单机健康不够——还要看负载均衡有没有把流量正确分发、服务发现有没有摘掉异常实例、整体错误率有没有上升。单实例健康不等于业务健康。

十、应急操作:故障中的底线

故障中节奏会变快,压力会变大,但有几条底线要守住:

底线为什么
以恢复服务为第一优先级降级、摘流量、扩容、回滚——先让业务恢复,再研究根因
少做不可逆操作删数据、清日志、重建集群——这些动作可能让故障升级成事故
保留现场关键日志、错误信息、时间点——事后复盘需要这些
单点指挥避免多人同时改同一系统,状态越改越乱,最后连哪个动作产生了效果都不知道
事后补齐记录应急时来不及写,恢复后立即补上操作步骤和时间线

故障时的基本现场保存:

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
变更名称:
操作人:
操作时间:
目标环境:
目标主机:

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

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

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