接手一台CentOS服务器,别急着敲yum update。先摸清当前系统的真实负载和内核版本,这决定了后续所有操作的安全边界。很多运维事故的根源,就是在一个跑了三年的内核上直接装了最新的Docker,导致依赖库冲突,系统直接挂掉。用uname -a看内核版本,用uptime看系统连续运行了多久。如果uptime超过300天,先别重启,因为很可能有内存泄漏,一重启某些服务就起不来了,你得先排查清楚哪些服务是手动启动的,没有加入systemd自启。
系统资源监控不是装个htop就完事了htop只能看实时状态,真正要命的是历史趋势和瓶颈点。在系统突然卡死时,你根本来不及打开任何工具。所以必须部署一套轻量级的监控采集,用vmstat 1 10连续采集10次,每秒输出一次,看si和so列,如果持续非零,说明内存在疯狂换页,物理内存已经不够了。再用iostat -x 1重点看%util和await,一块普通SSD的await超过20ms就说明IO已经严重阻塞。很多MySQL突然变慢,不是SQL写错了,而是磁盘IO被打满,数据库在排队等磁盘响应。把这些命令写成脚本,每分钟追加写入日志文件,比装任何监控Agent都可靠,因为Agent本身也可能挂。
#!/bin/bash
# 每分钟采集系统核心指标并追加到日志
DATE=$(date '+%Y-%m-%d %H:%M:%S')
LOAD=$(uptime | awk -F'load average:' '{print $2}')
MEM=$(free -m | awk 'NR==2{printf "%s/%sMB (%.2f%%)", $3,$2,$3*100/$2 }')
DISK=$(df -h / | awk 'NR==2{print $5}')
echo "$DATE | LOAD:$LOAD | MEM:$MEM | DISK:$DISK" >> /var/log/sys_monitor.log
软件包管理必须锁死版本,禁止自动更新
CentOS的yum-cron服务在某些镜像里默认开启,这简直是生产环境的定时炸弹。你永远不知道凌晨三点自动更新的glibc会不会让Java虚拟机直接段错误。第一时间检查systemctl status yum-cron,如果active,立刻停掉并禁用。然后修改/etc/yum.conf,加入exclude=kernel* centos-release*,把内核和发行版基础包锁死。需要更新时,手动执行yum check-update,一条条审核变更内容,确认不影响现有业务后再更新。对于PHP、Python这类语言环境,不要用系统源里的版本,用SCL或者编译安装到独立目录,避免污染系统库。
日志轮转不配置好,再大的硬盘也会满/var/log目录是磁盘爆满的重灾区。journald日志默认是持久化存储且没有大小上限,用journalctl --disk-usage查看,超过500MB就赶紧设限。修改/etc/systemd/journald.conf,把SystemMaxUse设为500M,然后重启服务。对于传统日志,检查/etc/logrotate.d/下的配置,重点看nginx、mysql的日志轮转策略,把rotate保留份数从默认的52周改成4周,并启用compress压缩。最容易被忽略的是/var/log/btmp和/var/log/wtmp这两个登录日志文件,它们不属于任何logrotate规则,时间长了能长到几个GB,需要手动创建轮转配置,或者定期用cat /dev/null清空。
防火墙策略要基于默认拒绝原则firewalld的默认区域是public,但很多人图省事直接firewall-cmd --add-port=80/tcp --permanent,这样加到最后,规则乱成一团。正确的做法是先切换网卡到drop区域,然后只放行必要的端口和服务。对于SSH,不要用默认22端口,改成高位端口后,配合rich-rule限制来源IP,只允许公司出口IP和跳板机IP访问。用firewall-cmd --list-all检查当前生效的规则,确保没有多余的端口暴露。如果是云服务器,安全组和系统防火墙要双层配置,安全组做第一层大范围过滤,系统防火墙做第二层精细控制。
# 将默认区域设为drop,仅放行指定服务 firewall-cmd --set-default-zone=drop firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="你的办公IP" port protocol="tcp" port="2222" accept' firewall-cmd --reloadSSH安全加固远不止改端口
改了端口只是防扫描,真正危险的是弱口令和密钥泄露。编辑/etc/ssh/sshd_config,把PermitRootLogin设为no,PasswordAuthentication设为no,只允许密钥登录。同时把MaxAuthTries降到3,LoginGraceTime缩到30秒,让暴力破解无法持续尝试。更关键的是管理好~/.ssh/authorized_keys文件,定期审计里面有多少个公钥,每个公钥属于谁,有没有已经离职的同事。用ssh-keygen -lf查看公钥指纹并做好记录,发现不明公钥立刻删除。如果必须保留密码登录给某些用户,用Match User指令单独放行,不要全局开启。
内核参数调优要针对实际业务场景sysctl.conf里的参数不是网上抄一份就能用。如果是Web服务器,重点调net.core.somaxconn和net.ipv4.tcp_max_syn_backlog,提高TCP连接队列长度,应对突发流量。如果是数据库服务器,重点调vm.swappiness,设为1而不是0,让内核在物理内存耗尽前尽量不使用交换分区,但保留最后一点应急能力。vm.dirty_ratio和vm.dirty_background_ratio控制脏页比例,对于大内存机器,默认值会导致突然大量刷盘造成IO抖动,适当调低这两个值让刷盘更平滑。所有参数修改后先用sysctl -p加载,观察几天确认无异常再写入配置文件永久生效。
定时任务要加锁防堆积crontab里跑脚本,最怕上次没执行完,下次又启动了,最终进程堆满系统。每个脚本开头必须加flock文件锁,或者用进程名检测是否已有实例在跑。对于耗时超过一分钟的任务,用timeout命令包一层,防止脚本卡死无限等待。邮件发送、数据同步这类任务,一定要把标准输出和标准错误重定向到日志文件,否则cron会把输出尝试发邮件,而系统默认没配MTA,这些邮件会堆积在/var/spool/postfix/maildrop里,产生大量小文件撑爆inode。
# 带文件锁的cron脚本模板 */5 * * * * /usr/bin/flock -xn /tmp/myjob.lock -c '/opt/scripts/myjob.sh >> /var/log/myjob.log 2>&1'用户和权限审计要常态化
用lastlog查看所有用户最后登录时间,超过90天未登录的账号,如果不是系统服务账号,直接锁定。检查/etc/passwd里UID为0的用户,正常情况下只有root一个,发现其他UID为0的账号立刻排查。用find / -perm -4000查找所有SUID文件,重点看/usr/bin/passwd、/usr/bin/su这些文件是否被替换过,用rpm -Vf校验原始包完整性。对于Web目录,绝对不要设777权限,用chown把属主给应用运行用户,权限设755,需要写入的目录如uploads单独设775并配合ACL精细化控制。
备份策略要遵循3-2-1原则且必须验证数据备份不做验证等于没做。很多运维直到需要恢复时才发现备份文件是损坏的。用mysqldump导出数据库后,立刻用gzip压缩并计算MD5值存到单独文件。然后用zcat backup.sql.gz | head -n 50检查文件头是否正常,再导入到一个测试实例验证完整性。对于配置文件,用git做版本控制是最佳实践,/etc目录初始化一个git仓库,每次修改配置都commit并写好注释,这样出问题可以秒级回滚,还能追溯是谁在什么时候改了什么。备份文件至少要保留一份在离线存储或另一台服务器上,用rsync配合--bwlimit限制带宽,避免备份过程占满网络影响业务。
服务管理要善用systemd的防护机制systemd不仅能启停服务,还能限制服务的资源使用和行为。在自定义的service文件里,加入MemoryLimit限制服务最大内存,CPUQuota限制CPU使用率,防止某个服务内存泄漏拖垮整个系统。用PrivateTmp=true给服务独立的/tmp目录,用ProtectSystem=strict让服务无法修改系统目录,用NoNewPrivileges=true禁止服务提权。这些配置对于Redis、Nginx这类经常被攻击的服务尤其重要,能在漏洞被利用时大幅降低损失范围。每次修改service文件后执行systemctl daemon-reload,然后用systemctl show 服务名检查所有参数是否生效。
故障排查要建立标准化的诊断流程系统出问题时,第一反应不是重启,而是执行一套固定的诊断命令组合。先用dmesg -T | tail -50看内核日志最后50行,OOM Killer的记录就在这里,能直接看到是哪个进程因为内存不足被杀。再用ss -s看socket统计,如果timewait数量异常高,说明短连接过多需要调内核参数或优化应用。用lsof -n | grep deleted查找被删除但进程仍在占用的文件,这些文件不释放磁盘空间,是磁盘使用率莫名升高的常见原因。用strace -p 进程PID -c统计系统调用耗时,快速定位进程在哪个环节卡住。把这套流程写成检查清单,出问题时按清单逐项排查,比凭经验乱试高效得多。
内核漏洞管理要建立跟踪机制CentOS的生命周期和内核更新节奏必须持续关注。用yum list installed kernel查看已安装的内核版本,用rpm -q --changelog kernel-版本号 | head -50查看最近的变更日志,确认是否修复了已知的高危漏洞。对于不能重启的服务器,用kexec做热内核替换,虽然有一定风险,但在紧急漏洞修复时是唯一的选择。安装kernel-devel包和系统内核版本必须严格一致,否则编译内核模块会失败,很多监控Agent和自定义驱动都依赖这个。保留至少两个可用的旧内核版本,新内核启动失败时可以在GRUB菜单选择旧内核恢复。
日常运维的核心不是掌握多少工具,而是建立一套可重复、可验证的操作规范。每个操作前想清楚回滚方案,每个配置修改留下记录,每个备份验证可用性。系统稳定不是靠运气,是靠这些看似繁琐但环环相扣的细节堆出来的。
