首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >有故障一定是运维的责任么?(上)

有故障一定是运维的责任么?(上)

作者头像
IT运维技术圈
发布2025-10-09 12:18:29
发布2025-10-09 12:18:29
1390
举报
文章被收录于专栏:IT运维技术圈IT运维技术圈

0. 写在前面:为什么你需要“神器”而非“常用命令

大家好,我是老杨,干货满满的老杨.欢迎来到互联网遥遥领先的博客. 欢迎点击原文链接或直接访问vps.top365app.com,来看老杨的全球vps信息还有各种咱们用得着的信息实时收集分析项目.

帮老杨点赞、转发、在看以及打开小星标哦

攒今世之功德,修来世之福报


背锅这个词咋来的?

老杨今天给各位补习一下这个看似没用,实则一点都用不着的知识点。

传说古代军中如果有人犯错,就会被降级去炊事班并且负责背着大锅行军。军队做大锅饭那个铸铁锅可不是一般的沉。而且这个锅到底有多重要,当年项羽要拼命了才下令破釜沉舟,也就是把锅砸了。

你背这玩意,而且要像初恋一样的保护它!

慢慢的这个岗位就被引申到了职场中。

蝙蝠侠、蜘蛛侠、闪电侠、背锅侠,这四个都是拯救苍生的英雄人物。唯一的区别大概只有背锅侠不戴面具了。

看老杨的文章涨知识吧!

进入今天的主题.

见过太多同行因为一些看似无关紧要的操作,最后成了大铁锅。

不对!是背锅侠。

有的是技术问题,有的是流程问题,但更多的是意识问题。

比如公司数据库崩了,老板直接问运维搞咋回事。结果查来查去,发现是开发改了个配置没通知,但最后还是运维背锅——"你们怎么不知道?监控呢?"

反正运维就别想跑,出了问题第一个被怀疑,背锅是常态。但有些锅其实可以避免。

禁忌一:直接在生产环境操作,不走变更流程

这是运维背锅的头号原因。很多人觉得改个配置、重启个服务很简单,直接上生产操作。结果一旦出问题,你就是那个"擅自修改生产环境"的人。

之前就有发现Nginx配置有个小错误,想着就改一行代码,直接vim修改了。结果手抖多删了一个分号,整个网站500错误。更要命的是,没有人知道他改了什么,因为没有变更记录。

这种情况下,100%背锅。

正确的做法:

代码语言:javascript
复制
# 1. 创建变更工单
# 2. 在测试环境验证
$ nginx -t -c /etc/nginx/nginx.conf.new
nginx: configuration file /etc/nginx/nginx.conf.new syntax is ok
nginx: configuration file /etc/nginx/nginx.conf.new test is successful

# 3. 备份原配置
$ cp /etc/nginx/nginx.conf /backup/nginx.conf.$(date +%Y%m%d_%H%M%S)

# 4. 执行变更并记录
$ echo"变更时间: $(date)" >> /var/log/change.log
$ echo"操作人员: 老杨" >> /var/log/change.log  
$ echo"变更内容: 修改upstream配置" >> /var/log/change.log

# 5. 应用配置
$ nginx -s reload

禁忌二:删除操作不确认,删库跑路成真实

运维最怕的就是删除操作。一个rm命令,可能毁掉整个职业生涯。

之前有个哥们,想清理 /tmp 目录下的临时文件,结果命令写成了:

代码语言:javascript
复制
$ rm -rf /tmp /*

注意那个空格,本来想删 /tmp/* ,结果变成了删除 /tmp 和 /* 。服务器直接GG了。

更可怕的是这种情况:

代码语言:javascript
复制
# 本意是删除旧的备份文件
$ rm -rf $BACKUP_DIR/old_backup/*

# 但如果$BACKUP_DIR变量为空...
$ rm -rf /old_backup/*
# 这就变成了删除根目录下的old_backup目录

正确的删除姿势:

代码语言:javascript
复制
# 1. 先用ls确认要删除的内容
$ ls -la /tmp/old_logs/
total 1024
drwxr-xr-x 2 root root    4096 Dec  1 10:00 .
drwxr-xr-x 8 root root    4096 Dec  1 09:00 ..
-rw-r--r-- 1 root root 1048576 Nov 30 23:59 app.log.old

# 2. 使用find命令精确匹配
$ find /tmp/old_logs/ -name "*.log.old" -type f -mtime +7 -print
/tmp/old_logs/app.log.old
/tmp/old_logs/error.log.old

# 3. 确认无误后执行删除
$ find /tmp/old_logs/ -name "*.log.old" -type f -mtime +7 -delete

# 4. 或者更安全的做法,先移动到回收站
$ mkdir -p /tmp/trash/$(date +%Y%m%d)
$ mv /tmp/old_logs/*.log.old /tmp/trash/$(date +%Y%m%d)/

而且删除数据库数据时,一定要先备份:

代码语言:javascript
复制
# 绝对不要直接删除
# DELETE FROM users WHERE created_at < '2023-01-01';

# 正确做法:
# 1. 先查询要删除的数据量
SELECT COUNT(*) FROM users WHERE created_at < '2023-01-01';
-- 返回: 50000

# 2. 创建备份表
CREATE TABLE users_backup_20241201 AS 
SELECT * FROM users WHERE created_at < '2023-01-01';

# 3. 确认备份成功
SELECT COUNT(*) FROM users_backup_20241201;
-- 返回: 50000

# 4. 小批量删除,避免锁表
DELETE FROM users WHERE created_at < '2023-01-01' LIMIT 1000;

禁忌三:监控告警不处理,出事了说"不知道"

监控系统天天发告警,很多运维觉得都是"狼来了",直接忽略。等真出问题了,老板问为什么没有预警,你说监控有告警但没处理,这就是典型的失职。

比如磁盘使用率超过90%的告警连续一周都在发,觉得还有10%空间,应该没事。结果某天日志爆增,磁盘满了,数据库写入失败,订单系统瘫痪2小时。

正确的监控处理流程:

代码语言:javascript
复制
# 1. 收到磁盘告警后立即检查
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        50G   45G  2.6G  95%   /
/dev/sda2       100G   92G  4.2G  96%   /var

# 2. 分析磁盘使用情况
$ du -h --max-depth=1 /var | sort -hr
85G     /var/log
3.2G    /var/lib
1.8G    /var/cache
...

# 3. 找到占用空间最大的日志文件
$ find /var/log -type f -size +1G -execls -lh {} \;
-rw-r--r-- 1 root root  15G Dec  1 10:30 /var/log/mysql/mysql.log
-rw-r--r-- 1 root root  8.5G Dec  1 10:25 /var/log/nginx/access.log

# 4. 清理日志并配置轮转
$ echo > /var/log/mysql/mysql.log
$ echo > /var/log/nginx/access.log

# 5. 配置logrotate防止再次发生
$ vim /etc/logrotate.d/mysql
/var/log/mysql/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    postrotate
        /bin/kill -HUP $(cat /var/run/mysqld/mysqld.pid 2>/dev/null) 2>/dev/null || true
    endscript
}

而且要建立告警处理机制:

代码语言:javascript
复制
# 告警处理脚本 alert_handler.py
import json
import time
import subprocess
from datetime import datetime

defhandle_disk_alert(server, mount_point, usage_percent):
    """处理磁盘告警"""
    print(f"处理磁盘告警: {server}:{mount_point} 使用率{usage_percent}%")
    
    if usage_percent > 95:
        # 紧急处理:清理临时文件
        subprocess.run([
            "ssh", server, 
            "find /tmp -type f -mtime +1 -delete"
        ])
        
        # 清理日志文件
        subprocess.run([
            "ssh", server,
            "find /var/log -name '*.log' -size +1G -exec truncate -s 0 {} \\;"
        ])
        
        # 记录处理动作
        withopen('/var/log/alert_actions.log', 'a') as f:
            f.write(f"{datetime.now()}: 自动清理{server}磁盘空间\n")
    
    elif usage_percent > 85:
        # 预警处理:发送通知给运维
        send_wework_notification(
            f"磁盘预警: {server}:{mount_point} 使用率{usage_percent}%,请及时处理"
        )

defsend_wework_notification(message):
    """发送企业微信通知"""
    # 实现企业微信通知逻辑
    pass

if __name__ == "__main__":
    # 模拟处理告警
    handle_disk_alert("web-01", "/var", 96)

禁忌四:密码明文存储,权限管理混乱

很多运维图方便,把各种密码写在脚本里,或者所有人共用一个root账号。出了安全问题,你就是第一责任人。

我见过这样的脚本:

代码语言:javascript
复制
#!/bin/bash
# 备份脚本 - 错误示例
mysql -h localhost -u root -p123456 mydb > backup.sql
scp backup.sql admin@192.168.1.100:/backup/

密码直接写在脚本里,任何能看到这个脚本的人都知道数据库密码。更可怕的是,这个脚本还被提交到Git仓库里,整个公司的人都能看到。

正确的密码管理:

代码语言:javascript
复制
# 1. 使用环境变量
export MYSQL_PASSWORD="your_secure_password"
mysql -h localhost -u root -p$MYSQL_PASSWORD mydb > backup.sql

# 2. 使用配置文件(权限600)
$ vim ~/.my.cnf
[client]
user=backup_user
password=your_secure_password
host=localhost

$ chmod 600 ~/.my.cnf

# 3. 在脚本中使用
mysql --defaults-file=~/.my.cnf mydb > backup.sql

# 4. 或者使用密钥管理系统
$ vault kv get -field=password secret/mysql/prod
your_secure_password

$ MYSQL_PASSWORD=$(vault kv get -field=password secret/mysql/prod)
$ mysql -h localhost -u root -p$MYSQL_PASSWORD mydb > backup.sql

权限管理也要规范:

代码语言:javascript
复制
# 1. 每个人独立账号,禁止共享root
$ useradd -m -s /bin/bash zhangsan
$ usermod -aG sudo zhangsan

# 2. 配置sudo权限,只给必要的命令权限
$ vim /etc/sudoers.d/zhangsan
zhangsan ALL=(ALL) NOPASSWD: /bin/systemctl restart nginx
zhangsan ALL=(ALL) NOPASSWD: /bin/systemctl restart mysql
zhangsan ALL=(ALL) NOPASSWD: /usr/bin/docker restart *

# 3. 使用密钥登录,禁止密码登录
$ ssh-keygen -t rsa -b 4096 -C "zhangsan@company.com"
$ ssh-copy-id zhangsan@server

# 4. 配置SSH只允许密钥登录
$ vim /etc/ssh/sshd_config
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no

禁忌五:备份不验证,恢复时才发现备份是坏的

很多运维做了备份,但从来不验证备份的完整性。等真需要恢复的时候,发现备份文件损坏或者根本恢复不了,这时候就只能背锅了。

比如某公司数据库崩了,运维信心满满地说:"没事,我们有备份。" 结果恢复的时候发现,备份脚本有bug,备份出来的数据都是空的,持续了3个月。

正确的备份验证流程:

代码语言:javascript
复制
#!/bin/bash
# 数据库备份与验证脚本

DB_NAME="production"
BACKUP_DIR="/backup/mysql"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_${TIMESTAMP}.sql"

echo"开始备份数据库 $DB_NAME..."

# 1. 执行备份
mysqldump --single-transaction \
          --routines \
          --triggers \
          --hex-blob \
          --lock-tables=false \
          $DB_NAME > $BACKUP_FILE

# 2. 检查备份文件大小
BACKUP_SIZE=$(stat -c%s $BACKUP_FILE)
echo"备份文件大小: $(($BACKUP_SIZE / 1024 / 1024))MB"

if [ $BACKUP_SIZE -lt 1048576 ]; then# 小于1MB可能有问题
    echo"警告:备份文件过小,可能备份失败"
    exit 1
fi

# 3. 验证SQL文件语法
if ! mysql --force --batch --skip-column-names -e "source $BACKUP_FILE" test_restore_db 2>/dev/null; then
    echo"警告:备份文件SQL语法错误"
    exit 1
fi

# 4. 创建测试数据库并恢复验证
TEST_DB="test_restore_$(date +%s)"
echo"创建测试数据库 $TEST_DB 进行恢复验证..."

mysql -e "CREATE DATABASE $TEST_DB"
mysql $TEST_DB < $BACKUP_FILE

# 5. 验证数据完整性
ORIGINAL_COUNT=$(mysql -N -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$DB_NAME'")
RESTORED_COUNT=$(mysql -N -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$TEST_DB'")

echo"原数据库表数量: $ORIGINAL_COUNT"
echo"恢复数据库表数量: $RESTORED_COUNT"

if [ "$ORIGINAL_COUNT" != "$RESTORED_COUNT" ]; then
    echo"错误:恢复后表数量不一致"
    mysql -e "DROP DATABASE $TEST_DB"
    exit 1
fi

# 6. 清理测试数据库
mysql -e "DROP DATABASE $TEST_DB"

# 7. 压缩备份文件
gzip $BACKUP_FILE

echo"备份完成并验证通过: ${BACKUP_FILE}.gz"

# 8. 记录备份日志
echo"$(date): $DB_NAME 备份成功,文件: ${BACKUP_FILE}.gz" >> $BACKUP_DIR/backup.log

而且要定期做恢复演练:

代码语言:javascript
复制
#!/bin/bash
# 每月备份恢复演练脚本

echo"开始每月备份恢复演练..."

# 1. 随机选择一个备份文件进行恢复测试
BACKUP_FILES=$(find /backup/mysql -name "*.sql.gz" -mtime -30 | shuf -n 1)
echo"选择备份文件: $BACKUP_FILES"

# 2. 创建独立的恢复测试环境
DRILL_DB="drill_test_$(date +%s)"
zcat $BACKUP_FILES | mysql $DRILL_DB

# 3. 执行数据一致性检查
# 这里可以加入具体的业务数据检查逻辑

# 4. 记录演练结果
echo"$(date): 恢复演练完成,备份文件: $BACKUP_FILES" >> /var/log/backup_drill.log

# 5. 清理测试数据
mysql -e "DROP DATABASE $DRILL_DB"

老杨时间

这里老杨先声明一下,日常生活中大家都叫老杨波哥,跟辈分没关系,主要是岁数大了.就一个代称而已. 老杨的00后小同事老杨喊都是带哥的.张哥,李哥的. 但是这个称呼呀,在线下参加一些活动时.金主爸爸也这么叫就显的不太合适. 比如上次某集团策划总监,公司开大会来一句:“今个咱高兴!有请IT运维技术圈的波哥讲两句“ 这个氛围配这个称呼在互联网这行来讲就有点对不齐! 每次遇到这个情况老杨就想这么接话: “遇到各位是缘分,承蒙厚爱,啥也别说了,都在酒里了.老杨干了,你们随意!” 所以以后咱们改叫老杨,即市井又低调.还挺亲切,老杨觉得挺好.

运维X档案系列文章:

从告警到CTO:一个P0故障的11小时生死时速

企业级 Kubernetes 集群安全加固全攻略( 附带一键检查脚本)

看完别走.修行在于点赞、转发、在看.攒今世之功德,修来世之福报

点击阅读原文或打开地址实时收集分析全球vps的项目 vps.top365app.com

老杨AI的号: 98dev

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-09-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT运维技术圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 禁忌一:直接在生产环境操作,不走变更流程
  • 禁忌二:删除操作不确认,删库跑路成真实
  • 禁忌三:监控告警不处理,出事了说"不知道"
  • 禁忌四:密码明文存储,权限管理混乱
  • 禁忌五:备份不验证,恢复时才发现备份是坏的
  • 老杨时间
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档