接手一台Ubuntu服务器,最怕遇到的情况不是配置复杂,而是运行了半年后突然SSH连不上,或者凌晨三点CPU负载飙到100%。Ubuntu 22.04/24.04 LTS作为主力生产环境,其稳定性依赖于日常的精细化运维,而不是等故障发生后再去搜索引擎里翻答案。以下内容基于实际生产环境中的血泪经验,直接切入核心操作。
系统资源瓶颈的快速定位登录服务器第一件事,习惯性敲下htop而非top。htop的彩色柱状图能让你在一秒内判断出是CPU单核被打满还是内存泄漏。如果发现load average数值持续超过CPU核心数的1.5倍,需要立即查看进程状态。使用ps aux --sort=-%cpu | head -10揪出占用CPU最高的进程。如果是MySQL或PostgreSQL导致的高负载,不要急着杀进程,先用SHOW FULL PROCESSLIST查看是否存在锁表或慢查询堆积。内存方面,free -h显示的available列才是真实可用内存,不要被used列吓到,因为Linux会积极使用空闲内存做文件缓存。当available低于总内存的10%时,执行echo 3 > /proc/sys/vm/drop_caches手动释放页缓存、目录项和inode,但这只是临时手段,根本解决之道在于调整应用的内存限制或增加物理资源。
磁盘IO与空间清理的硬核操作服务器突然响应变慢,90%的可能是磁盘IO被耗尽。用iotop -o直接查看当前正在读写磁盘的进程。如果发现logrotate没生效导致syslog或nginx日志撑爆了根分区,第一时间用du -sh /* 2>/dev/null | sort -hr快速定位大目录。遇到已删除但进程未释放句柄导致磁盘空间不释放的经典问题,使用lsof | grep deleted找到这些“幽灵文件”,重启对应服务即可回收空间。对于Docker环境,每周执行docker system prune -a --volumes --force清理悬空镜像和停止的容器卷,能有效防止/var/lib/docker把磁盘吃满。另外,将/tmp目录挂载为tmpfs,并设置noexec,nosuid挂载选项,既能提升临时文件读写性能,又能防止恶意脚本在临时目录执行。
内核参数调优与安全加固默认的内核参数在并发场景下表现糟糕。编辑/etc/sysctl.d/99-custom.conf,针对Web服务器和数据库服务器做差异化调整。对于高并发反向代理,必须增大net.core.somaxconn和net.ipv4.tcp_max_syn_backlog的值,避免SYN队列溢出。开启net.ipv4.tcp_tw_reuse = 1允许将处于TIME_WAIT状态的套接字用于新连接,缓解端口耗尽问题。安全层面,开启net.ipv4.conf.all.rp_filter = 1防止IP欺骗,设置net.ipv4.icmp_echo_ignore_all = 1禁止响应ping请求以减少被扫描的风险。所有修改通过sysctl -p生效后,用ss -s观察网络连接状态分布,确保TIME_WAIT占比不会过高。
自动化任务与定时作业的隐患排除Crontab里的定时任务是最容易被忽视的故障源头。检查/var/spool/cron/crontabs目录下所有用户的定时任务,确保每个脚本的输出都重定向到文件或/dev/null,否则系统邮件队列会被塞满。对于凌晨执行的重负载任务,比如数据库备份或日志分析,务必在脚本开头使用flock互斥锁,防止上一次任务未结束新任务又启动导致资源耗尽。示例代码如下:
#!/bin/bash exec 200>/var/lock/myscript.lock flock -n 200 || exit 1 # 实际任务逻辑
使用systemd-timer替代部分cron任务是个更现代的选择,它支持随机延迟启动和CPU配额限制,能有效避免定时任务集中触发造成的资源尖峰。
SSH连接故障的深度排查SSH连不上时,别急着重启服务器。先通过带外管理或VNC登录控制台,检查sshd是否存活:systemctl status sshd。如果服务正常但连接卡在debug1: Connecting to...阶段,大概率是防火墙或云服务商安全组拦截了端口。在服务器本地用tcpdump -i any port 22监听,再尝试从客户端连接,观察是否有SYN包到达。如果收到SYN包但无回应,检查/etc/hosts.allow和/etc/hosts.deny是否误封了IP。连接成功但密码验证后立即断开,需要检查/etc/ssh/sshd_config中是否设置了AllowUsers或AllowGroups限制。对于使用密钥登录失败的情况,确认~/.ssh目录权限为700,authorized_keys文件权限为600,家目录所有者必须是用户本人而非root,否则sshd会拒绝读取密钥。
软件包管理与依赖地狱的解脱执行apt upgrade时遇到held broken packages错误,说明系统中存在版本冲突。先用apt-mark showhold查看被锁定的包,再用apt-cache policy 包名检查各版本优先级。如果是从第三方PPA安装的软件导致依赖混乱,使用ppa-purge工具彻底移除PPA并降级相关包。生产环境严禁直接运行apt autoremove -y,这条命令曾无数次删除了仍在使用的内核或驱动。正确的做法是先列出将被删除的包:apt autoremove --dry-run,确认无关键组件后再执行。对于需要编译安装的软件,统一使用checkinstall替代make install,这样会生成deb包便于日后卸载和版本管理。
Systemd服务异常的分析路径服务启动失败时,journalctl -u 服务名 -n 50 --no-pager是获取错误信息的最快方式。重点关注ExecStartPre和ExecStart中定义的命令路径是否存在,权限是否正确。遇到服务启动后立即退出的情况,检查Type=forking的服务的PIDFile路径是否与实际匹配。对于需要网络就绪后才启动的服务,必须添加After=network-online.target和Wants=network-online.target,否则会在网络未完全配置好时启动失败。使用systemd-analyze blame查看系统启动耗时分布,禁用那些拖慢启动速度且非必需的服务。如果某个服务频繁被OOM Killer杀死,在服务单元文件中设置OOMScoreAdjust=-500降低被选中的概率,同时用MemoryHigh和MemoryMax限制其内存使用上限。
日志系统的高效管理journald默认的日志保留策略会迅速占满/var/log/journal。修改/etc/systemd/journald.conf,设置SystemMaxUse=500M和MaxFileSec=1week,限制日志总体积和单文件留存时间。对于文本日志,使用logrotate的copytruncate模式处理那些不支持重开文件句柄的服务日志。遇到应用日志疯狂写入的情况,用truncate -s 0 /var/log/大文件.log直接清空而不影响正在写入的进程。搭建ELK或Loki日志中心时,务必在filebeat或promtail配置中设置ignore_older: 24h,避免采集端将历史归档日志重新灌入存储造成索引爆炸。
内核崩溃与硬件故障的预判服务器无故重启,第一时间检查/var/crash目录下是否有内核转储文件。使用rasdaemon监控内存的CE(可纠正错误)和UE(不可纠正错误),CE错误频繁出现是内存条即将物理损坏的前兆。通过mcelog或edac-utils读取硬件错误日志,能提前发现ECC内存错误和CPU缓存错误。对于使用NVMe固态的服务器,定期执行nvme smart-log /dev/nvme0查看Media_Errors和Percentage_Used,当可用备用空间低于10%时必须规划更换硬盘。设置内核参数panic_on_oops=1和panic=30,让系统在内核遇到严重错误时30秒后自动重启,比无限期挂死更可控。
备份策略与快速恢复验证备份不做验证等于没做。使用restic或borgbackup这类支持去重和加密的现代备份工具,每次备份后立即执行check命令验证仓库完整性。对于MySQL数据库,使用xtrabackup进行热备份而非mysqldump,前者能在不锁表的情况下完成一致性的全量备份。关键业务的备份必须遵循3-2-1原则:3份副本,2种不同介质,1份异地存放。每季度进行一次灾难恢复演练,用备份文件在新服务器上完整恢复业务,记录从开始恢复到服务可用的准确时间,这个RTO指标才是衡量备份策略有效性的唯一标准。
网络性能异常的综合诊断带宽跑满时,使用iftop或nethogs定位是哪个进程在疯狂发包。发现大量SYN_SENT状态连接,说明服务器正在对外发起攻击或被用作跳板,立即用ss -tun state syn-sent检查目标IP。对于间歇性丢包问题,使用mtr命令进行持续路由追踪,它能同时显示每一跳的丢包率和延迟波动,远比ping和traceroute的组合更有效。DNS解析慢会导致所有依赖域名的服务响应卡顿,修改/etc/systemd/resolved.conf设置DNSOverTLS=yes和FallbackDNS=1.1.1.1,开启本地DNS缓存并设置合理的缓存过期时间。如果服务器作为网关使用,开启ip_forward后务必配置iptables的conntrack表限制,防止连接跟踪表被占满导致新连接无法建立。
