mirozbz的运维经验

服务器选购 · 建站 · Linux 运维笔记 · 点击任意一条展开

VPS 的本质是母鸡服务器上的一台虚拟机,而虚拟化方式直接决定了这台机器的性能隔离程度和你后续能折腾的空间。市面上最常见的是 KVM 和 OpenVZ 两种,体验差距极大。

KVM 是硬件辅助的全虚拟化,每一台小鸡都拥有完整独立的内核和硬件视图,和其他用户之间是物理隔离的。OpenVZ 则是操作系统级虚拟化,所有小鸡共享母鸡的内核和内存,商家一句话就能把你的配额改小,你甚至无从察觉。

我建议一律避开 OpenVZ,理由很实在:第一,它不能自定义内核,很多内核模块和调优根本装不上,比如 TCP BBR 这类优化;第二,内存是「超卖」重灾区,商家给你标 512M,物理上可能只有一半真的可用;第三,隔离性差,邻居的机器被打满流量,你的机器也会跟着抖动;第四,部分场景下 Docker 跑不起来,因为嵌套虚拟化受限。

怎么确认自己买的是不是 KVM?下单前直接问客服,或者看商品页是否明确标注 KVM;到手后可以执行 uname -r 看内核版本,OpenVZ 的内核版本永远和母鸡官方一致,且无法更换。

KVM 的单价确实比 OpenVZ 高,但这笔钱换来的稳定性和自由度绝对值得。我目前用的 BandwagonHost 全线都是 KVM 架构,从入门套餐到高配都能选,这也是我敢放心推荐给新手的核心原因。

很多新手选机房只看地名,觉得「洛杉矶机房」听起来高级,其实同一机房不同商家给的线路可能天差地别。数据从国内到国外服务器要跨国走海底光缆,回程走哪条骨干网,直接决定延迟和丢包。

回程线路大致分四档,按国内访问体验从好到差排:

  • CN2 GIA:电信三网 CN2 骨干直连,晚高峰最稳,建站和跑业务的理想选择
  • CN2 GT:走 CN2 但只是半程,性价比高,高峰期一般
  • 9929 / CMIN2:联通、移动的优化线路,对应运营商用户表现很好
  • 普通 163 国际线路:出国绕路,晚高峰丢包明显,只适合纯海外业务

判断线路质量不要看商家广告,自己动手测最诚实:ping -c 100 看平均延迟和丢包率;再用 mtr 跟踪路由,重点观察每一跳的丢包情况,丢包集中在中段说明国际骨干拥堵,集中在回程末段说明商家线路问题。测试一定要放在晚高峰八点到十一点跑,白天的数据不能代表真实体验。

按运营商选线路也有讲究:电信用户优先 CN2 GIA;联通用户看 9929;移动用户看 CMIN2。买之前先查商家的机房线路表,别省这一步,后面天天难受。搬瓦工的套餐在线路说明里写得很清楚,GIA 和 GT 分开标注,基本不会踩坑。

新机器到手的第一件事不是装环境,而是做安全加固。VPS 的 SSH 默认端口 22 暴露在公网上,从上线那一刻起,扫描器和密码爆破就在不停打你的门。很多教程让新手裸奔上线,这是大忌。

五分钟内完成四步,安全感立刻拉满。第一步改密码,默认的临时密码必须换掉:

passwd

第二步创建普通用户并加入 sudo 组,日常操作不要用 root,防止手滑删库;第三步开启防火墙,只放行必要端口;第四步禁止 root 直接 SSH 登录,逼自己走 sudo 通道,爆破成功率直接归零:

adduser miro && usermod -aG sudo miro
ufw allow 22 && ufw allow 80,443 && ufw enable
echo 'PermitRootLogin no' >> /etc/ssh/sshd_config
systemctl restart sshd

这里有个关键顺序:先确认你创建的用户能正常登录,再重启 sshd 和禁止 root。如果先把 root 禁了又发现自己密钥没配好,就得靠面板的 VNC 兜底了。另外记得改完这些之后重新开一个 SSH 窗口测试一下,确认能连上再关掉旧窗口,这是所有 sshd 配置改动后的铁律。

防火墙的默认策略是拒绝入站,只放行明确要用的端口,SSH、HTTP、HTTPS 是大多数人的全部需求。以后每开一个新服务,就多放行一个端口,别图省事直接 ufw disable

公网上的 SSH 密码爆破每分钟都在发生,弱密码机器平均撑不过几个小时就会被人登上。密码登录是一条永远在漏水的船,而密钥登录可以从根上把漏洞补上。

密钥对是一公一私两把钥匙:私钥放在你自己的电脑上,公钥放到服务器的 ~/.ssh/authorized_keys 里。登录时服务器用公钥验证你的私钥签名,只要私钥不泄露,别人猜一万年也登不进来。整个过程不需要在网络上传任何密码。

三步配置,全程无脑:

ssh-keygen -t ed25519 -C "miro@laptop"
ssh-copy-id miro@你的IP
echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config
systemctl restart sshd

第一行在你的电脑上执行,生成 ed25519 密钥对,这种曲线比 RSA 更安全更短;第二行把公钥推送到服务器;第三、四行在服务器上禁用密码认证并重启服务。

几个安全细节要注意:私钥文件权限必须是 600,chmod 600 ~/.ssh/id_ed25519,否则 SSH 会拒绝使用;生成时建议加一个 passphrase 给私钥上锁,这样即使电脑丢了,别人拿到私钥文件也打不开;换电脑前记得把公钥加回服务器,别把自己锁在门外。

禁用密码认证前务必先验证密钥登录已经可用——新开一个终端窗口测试通过后,再改配置重启 sshd。做过这一步,你的服务器就从「爆破目标」变成了「无懈可击」,剩下的就是定期检查 auth.log 里有没有可疑登录记录。

Linux 防火墙的底层是 iptables/nftables,规则复杂容易把人劝退,而 UFW 把它封装成了几个直观的命令,对绝大多数个人服务器来说完全够用。它的哲学很简单:默认拒绝入站,只放行明确要开的端口。

一套基础配置长这样:

ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

逐条解释:入站默认拒绝,出站默认放行;然后显式允许 SSH、HTTP、HTTPS 三个端口。执行 ufw enable 后防火墙立即生效,用 ufw status verbose 查看规则清单。

新手最容易踩的坑就是把自己锁在门外。两个保命技巧:第一,ufw enable 之前一定要确认 ufw allow 22 已经执行,否则 SSH 一断你只能靠面板 VNC 救场;第二,改规则时保持当前 SSH 连接不断开,新开一个窗口验证没问题再操作。

进阶用法:用 ufw limit ssh 代替 ufw allow ssh,这个规则会限制单个 IP 的连接频率,对暴力破解有很好的抑制效果,比单纯放行安全得多。查端口占用可以配合 ufw status numbered 编号删除多余规则,用 ufw delete 编号 精准移除。

swap 是内存的「硬盘替补」,内存不够时内核会把暂时不用的数据换到磁盘上,防止进程因为内存不足直接被 OOM 干掉。问题在于,很多人以为 swap 越多越好,实际未必。

swap 的读写速度比内存慢几个数量级,一旦系统频繁换页,磁盘 IO 会被拖垮,机器表现为「看着还活着,但响应奇慢」。所以 swap 的正确用途是兜底——平时不该被用到,只在突发内存压力时缓冲一下,而不是把它当内存用。

给一台 2G 内存的机器加 2G swap,命令如下:

fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab

解释一下这几步:创建文件、收紧权限、格式化为 swap、挂载启用、写进 /etc/fstab 保证开机自动挂载。用 free -h 验证 swap 是否生效。

另一个相关的参数是 vm.swappiness,它控制内核使用 swap 的积极程度,取值 0 到 100,默认 60。对服务器来说建议调低到 10 左右,让内核尽量优先使用物理内存:echo 'vm.swappiness=10' >> /etc/sysctl.confsysctl -p 生效。

注意 swap 是应急方案不是扩容方案。如果 swap 使用率长期居高不下,说明内存真的不够,正确做法是升级内存套餐或者优化进程的内存占用,而不是无限加大 swap 掩盖问题。另外建议优先考虑 zram(压缩内存交换),压缩后有效容量更大且不走磁盘,但对 SSD 使用场景收益有限。

低价 VPS 翻车,十有八九是超售惹的祸。超售的意思是商家在一台母鸡上卖了远超物理能力的配额:一台 64G 内存的母鸡,敢开出 200 台 512M 的 VPS。平时大家都很安静没事,一遇到高峰期,抢 CPU、抢内存、抢带宽,你的机器就变成幻灯片。

识别超售有四个实用手段,不用懂原理也能测出来。第一测 CPU:用 sysbench 连跑两次单线程,两次分数差得离谱,说明你的核是共享的且有人抢:

apt install -y sysbench
sysbench cpu run --threads=1
sysbench cpu run --threads=1

第二看 steal 时间,这是最直接的证据。执行 top 看 %st 列,或者 vmstat 1 看 st 列,如果 steal 经常超过 5%,说明母鸡正在被其他人挤压。第三查内存:free -h,可用内存远低于标称值,往往意味着商家用 swap 或者超卖充数。第四测带宽:speedtest-cli 反复测取最低值,别信广告里写死的「1Gbps」,实际高峰期能有十分之一就不错了。

还有一个容易被忽略的点:CPU 核数也要防。有些商家只给了你「1 核」,但用的是一整块大核超线程的残值,跑分时看起来还行,一上负载就露馅。建议用 nproclscpu 核对真实核数和型号。

如果测试结果证实超售严重,直接换商家,别浪费时间跟工单掰扯。选商家时看三点:运营年限、老用户续费评价、是否支持随时退款。这三条全中的商家,超售一般控制在合理范围内,用起来才安心。

线路不满意,或者机房出现故障,很多时候不用重新买机器,直接在面板里迁移机房就行。搬瓦工的 KiwiVM 面板内置了跨机房迁移功能,整个过程不用重装系统,IP 会变更,但数据会整体搬过去。

迁移前有三件事必做。第一件也是最关键的:打快照。迁移过程万一中断,快照就是你最后的退路:

KiwiVM → Snapshot → 创建快照

第二件:停掉对时效敏感的服务并做好心理准备,迁移期间机器不可用,大概 10 到 30 分钟。第三件:记下当前 IP 和所有依赖它的配置,比如 DNS 解析、本地 SSH 的 known_hosts、防火墙白名单。

具体步骤在 BandwagonHost 搬瓦工 面板里走:KiwiVM 左侧菜单点 Migrate to another DC,选好目标机房确认即可。搬瓦工的机房覆盖洛杉矶、圣何塞、香港、东京、荷兰等地,线路从 CN2 GIA 到普通都有,价格不会因为迁移而变。

迁移完成后立刻做三件事:用新 IP 登录验证系统完整;把 DNS 解析切到新 IP 并确认生效;更新本地 ~/.ssh/known_hosts 里的旧指纹。最后跑一遍 mtr 确认新机房的线路质量符合预期,如果迁移到的是 GIA 机房,晚高峰再去测一次丢包率。

提醒一句:迁移不是无限次免费的,不同商家规则不同,搬瓦工一般按次或按套餐限制,动手前先看面板提示,别白白浪费迁移次数。

数据库是一个网站最值钱的资产,代码丢了可以重写,数据丢了就是永久损失。但很多人的备份策略有问题:备份文件就放在同一台机器上,磁盘一坏,备份和数据一起归西,这等于没备份。

正确的备份姿势包含两层:定时 + 异地。先看定时怎么配。用 mysqldump 导出并压缩,文件名带上日期方便追溯:

mysqldump -u root -p数据库密码 dbname | gzip > /backup/db_$(date +%F).sql.gz

然后写进 cron,每天凌晨 3 点执行,保留最近 7 份自动清理:

0 3 * * * root mysqldump -u root -p密码 dbname | gzip > /backup/db_$(date +%F).sql.gz && find /backup -mtime +7 -delete

注意 cron 里的密码别写在命令行明文里太长,更稳妥的做法是把备份脚本写进一个带 ~/.my.cnf 凭据的脚本文件,并设置 600 权限。脚本写好后用 chmod +x 授权,手动跑一次确认能生成文件再挂 cron。

异地这一步同样重要。最简单的做法是用 scp 推到另一台机器:scp /backup/db_*.gz user@other-ip:/backup/;更现代的做法是用 rclone 同步到对象存储,比如 R2、S3、Backblaze,成本极低:rclone sync /backup remote:backup/。定时任务推一次,异地备份就自动完成了。

最后永远记住这句话:备份没有恢复验证,等于白备份。每季度把备份恢复到一台临时机器上跑一遍,确认数据完整、能启动,才算真正闭环。

日志不轮转,磁盘迟早被撑爆。Nginx、MySQL、系统日志每天都会写新的内容,一台安静的小服务器一年也能攒出几个 G 的日志,更别说被扫描攻击刷屏的时候。logrotate 就是负责定期归档、压缩、清理日志的标准工具,Debian/Ubuntu 默认装了但没人配置等于没用。

一份典型的 Nginx 日志轮转配置长这样:

/var/log/nginx/*.log {
    daily
    rotate 7
    compress
    missingok
    notifempty
    create 640 www-data adm
    sharedscripts
    postrotate
        [ -f /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
    endscript
}

逐行说明:daily 每天轮转一次;rotate 7 保留最近 7 份;compress 把旧日志 gzip 压缩;missingok 日志文件不存在不报错;notifempty 空日志不轮转;create 指定新日志的权限属主;postrotate 里向 Nginx 发 USR1 信号让它重新打开日志文件,否则 Nginx 会一直往被重命名的旧文件里写。

把配置文件丢进 /etc/logrotate.d/ 目录即可生效。部署前先用试运行模式检查语法,不带任何副作用:logrotate -d /etc/logrotate.conf。手动强制轮转一次验证效果:logrotate -f /etc/logrotate.d/nginx

两个常见坑:第一,MySQL 这类进程对日志文件句柄很执着,必须在 postrotate 里 flush 日志或者 reload,否则日志一直在旧文件里增长等于没轮转;第二,别把 rotate 0 或太大的保留份数写进配置,否则压缩文件堆起来照样占满磁盘,个人服务器保留 7 天足够,生产环境按合规要求另算。

静态博客的流量特征非常明确:读多写少,资源几乎全部可缓存。Nginx 负责高效地吐文件,Cloudflare 在全球边缘缓存,两者配合能让源服务器负载趋近于零,这也是我博客零成本跑在低配 VPS 上的核心。

Nginx 侧,站点根目录配置好 try_files 和静态资源的强缓存:

location / {
    try_files $uri $uri/ =404;
}
location ~* \.(js|css|png|jpg|svg|woff2)$ {
    expires 30d;
    add_header Cache-Control "public, max-age=2592000";
}

静态文件给 30 天长缓存,前提是文件名带 hash(构建工具自动生成),这样更新文件等于换了个新 URL,不会踩缓存不更新的坑。入口的 index.html 只给 5 分钟,保证文章更新能及时看到。

Cloudflare 侧做三件事:域名 NS 改到 Cloudflare 并开启橙色云朵(代理模式),让流量先走边缘;在缓存规则里按扩展名设置「Cache Everything + 30 天」;开启 Always Use HTTPS,证书由 Cloudflare 边缘免费签发,源站连证书都不用装。

注意区分两层缓存:浏览器缓存由 Cache-Control 控制,边缘缓存由 Cloudflare 规则控制。改完文章要立刻生效时,可以在 Cloudflare 面板一键 Purge Cache,或者用 API 定向清除单个 URL。

还有一条红线:动态内容、登录态页面、带参数查询的接口千万别开长缓存,一旦边缘缓存了带用户信息的响应,就是事故。拿不准的资源宁可不缓存,也不要把错误缓存住。

网站报错不可怕,可怕的是不知道往哪查。HTTP 错误码本身就在告诉你是哪一层出的问题,按图索骥,绝大多数问题几分钟就能定位。

403 Forbidden,表示请求被拒,但服务器活着。90% 的 403 是权限问题:Nginx 的 worker 进程没有权限读你的文件。检查目录 755、文件 644,确认属主是不是运行 Nginx 的用户(一般是 www-data 或 nginx)。命令一条搞定:ls -l /var/www,看到权限不对就 chmod -R 755 /var/www。剩下 10% 是防火墙或安全模块拦截,查 Nginx 错误日志会直接告诉你原因。

502 Bad Gateway,Nginx 作为反向代理连不上后端。先查后端进程活着没:systemctl status php-fpmsystemctl status mysql,看端口监听:ss -lntp | grep 9000。最常见的两个原因:PHP-FPM 的 socket 路径和 Nginx 配置里的 fastcgi_pass 不一致,或者后端崩了没起来。看 Nginx 错误日志 /var/log/nginx/error.log 里会直接写出连接失败的具体原因。

504 Gateway Timeout,后端响应超时了。多半是慢 SQL、单进程阻塞或者外部 API 调太久。方向是去后端日志找慢请求,Nginx 的 proxy_read_timeout 默认 60 秒,可以适当调大,但要先解决慢的根因而不是单纯加大超时。

最后给个通用方法论:排障第一件事永远是看 /var/log/nginx/error.log/var/log/nginx/access.log,日志比任何猜测都诚实。用 tail -f 边复现边看,错误发生时现场就抓到了。

Let's Encrypt 免费证书的寿命是 90 天,这是有意设计的——缩短有效期倒逼自动化。但也意味着忘了续期,网站就会在某个深夜挂着大红锁,访问者纷纷流失。配好自动续期,一劳永逸。

用 certbot 从申请到自动续期走一遍。首次申请,如果有 Nginx 插件直接改配置并重载:

apt install -y certbot python3-certbot-nginx
certbot certonly --nginx -d example.com -d www.example.com

然后验证续期链路本身是否通畅,certbot 提供了试运行命令,不会真的改证书:certbot renew --dry-run。这一步输出 Success 就说明续期机制是通的,第一次必须做。

Ubuntu 上 certbot 的包自带 systemd timer,默认每 12 小时检查一次,无需手动加 cron;如果是手动安装或者其他发行版,自己挂一条 cron 每天检查:0 3 * * * certbot renew --quiet && systemctl reload nginx。续期成功后记得 reload Nginx,让它加载新证书文件,这是最容易漏的一步。

常见失败原因:第一,防火墙或者 Cloudflare 的橙色云朵没放行 80 端口,certbot 的 HTTP-01 验证连不上;第二,DNS 解析没生效,域名指向还是旧的;第三,定时任务环境里找不到 certbot 的 PATH,cron 里写全绝对路径解决。

证书文件路径一般是 /etc/letsencrypt/live/example.com/fullchain.pemprivkey.pem,Nginx 配置里指向这里。用 certbot certificates 可以随时查看所有证书的到期时间,心里有数。

cron 是 Linux 里最常用也最阴险的定时任务工具,表面上「按点执行」很简单,实际翻车率极高。十个 cron 失灵,九个栽在这两个坑里:环境变量缺失和路径不完整。

第一个坑,环境变量。cron 执行任务时用的是极简环境,PATH 只有 /usr/bin:/bin,你日常 shell 里能直接敲的 dockerpython3certbot,在 cron 里统统找不到。解法有两个:任务命令写绝对路径,或者让任务走 login shell:

0 3 * * * /usr/local/bin/backup.sh > /var/log/backup.log 2>&1
# 或者
0 3 * * * bash -lc '/usr/local/bin/backup.sh' > /var/log/backup.log 2>&1

第二个坑,日志。很多人写完 cron 就再也不管了,出错了也不知道。任何可能失败的任务,输出都必须重定向到文件,> /var/log/xxx.log 2>&1,这样排查时至少有个日志可看。嫌日志文件乱可以用 logger 直接打进 syslog。

另外两个高频问题:时区。服务器默认 UTC 的话,你写的 0 3 * * * 是凌晨三点 UTC,等于北京时间上午 11 点。先 timedatectl 确认时区,重要任务显式写对。还有任务重叠:上一轮任务跑超过一小时,下一轮又启动了,两个进程抢同一份资源。处理办法是在脚本开头加锁:flock -n /tmp/task.lock -c '你的命令',抢不到锁直接退出,避免并发叠加。

如果 cron 已经满足不了你(要精细控制时间、失败重试、日志),直接上 systemd timer,配置更规范、独立环境变量、还能看上次运行状态,是 cron 的现代替代品。

「Address already in use」是新手启动服务时最常见的报错之一。80 端口被占用,十有八九是 Nginx 和 Apache 同时装了或者两个站点抢同一个端口;8080 被占用,多半是上次启动的服务没退干净。处理思路就两步:找到它,再决定杀还是让。

第一步找是谁占的。用 ss 直接查端口对应进程,一目了然:

ss -lntp | grep :80
lsof -i :80

ss 输出里的 pid 和进程名直接告诉你是谁;lsof -i :80 是另一种查法,适合没有 pid 权限的情况。Debian 系自带的 netstat 已经淘汰,别再用它。

确认占用的进程确实可以杀,再动手:fuser -k 80/tcp 按端口杀,或者 kill -9 PID 按进程杀。杀之前先确认它不是数据库这类重要服务,误杀数据进程就得不偿失了。还有一个细节:如果进程杀了端口还占着,可能是 TIME_WAIT 状态的残留连接,等一会儿或者 ss -tane 确认一下即可。

不过「杀进程」只是治标。治本的做法是搞清楚为什么两个服务抢同一个端口:要么在配置里把其中一个改到别的端口,要么停掉旧服务并设置开机不启动,systemctl disable 服务名。以后每次部署前先 ss -lntp 扫一眼端口,把冲突消灭在服务启动之前。

顺带一提,端口排查在容器时代同样适用:Docker 的 -p 80:80 映射如果和宿主机已有服务冲突,容器会启动失败并报同样的错误,排查方法完全一致。

「服务为什么自己挂了?」这是运维问题排行榜前三。很多情况下不是程序有 bug,而是内存耗尽,内核的 OOM Killer 出手了——它会在系统内存告急时挑选一个进程杀掉来保住系统,而它选中的,往往就是你那个吃内存最多的业务进程。

确认是不是 OOM,第一步看内核日志,OOM 事件一定会记在这里:

dmesg | grep -i "out of memory" | tail -20
journalctl -k | grep -i "oom" | tail -20

输出里能看到被杀进程的名字和当时的进程列表。第二步看当前内存水位:free -h,如果 available 长期接近零,说明机器一直贴着上限跑。

定位到进程后分三层处理。第一层临时救急:加 swap,命令参见第 06 条,能撑过突发压力;第二层治本:查这个进程为什么吃这么多内存,是不是配置了过大的缓冲池、缓存没回收、或者真的业务增长需要更多内存;第三层升级:如果优化不动,就升级到内存更大的套餐,内存是服务器里最不能省的资源。

防患于未然的习惯也重要:装个监控,内存使用率超过 85% 就告警,别等 OOM 真发生了才后知后觉。轻量方案是 cron 里跑一段 free -m | awk 'NR==2{print $7}' 比较阈值后发通知,成熟方案直接上 netdata 或者 Prometheus + node_exporter,五分钟就能搭好。

最后提醒:OOM 杀进程这件事,内核的选择逻辑是「挑最不值得留的」,但它对业务的伤害是一样的。所以别指望内核帮你保命,尽早把内存水位和进程内存占用这两个指标纳入日常巡检。

ping 只能告诉你「通不通」,真要判断线路质量——丢包在哪一跳、延迟是稳定还是抖动、是不是被限速——就得看数据包层面的证据。tcpdump 是抓包界的老炮,服务器上自带,直接就能用。

最基本的用法,抓指定网卡上的流量。默认的 eth0 在大多数 VPS 上叫 eth0,用 ip link 确认后执行:

tcpdump -i eth0 -c 100 icmp

这条命令抓 100 个 ICMP 包(就是 ping 包)。配上 ping 一起用,能直观看到请求发出去了、回应有没有回来、回来用了多久。如果想看全量进出流量,去掉 icmp 过滤即可,但输出会很吵,建议加上 -n 不做 DNS 反解。

抓包配合 mtr 更专业。mtr 同时做 ping 和 traceroute,每一跳的丢包和延迟都列出来:mtr -rwzc 100 目标IP,重点看前三跳和最后一跳。如果丢包集中在中间国际段,那是骨干线路问题,换什么都一样;如果集中在最后一跳,那是商家机房或者你的本地 ISP 问题,可以针对性投诉或换线路。

读 tcpdump 输出有个小技巧:看 TCP 握手的三次握手包(SYN/SYN-ACK/ACK),如果 SYN 发出去一直没有 SYN-ACK 回来,说明回程丢包严重;如果一直重传(retransmission),说明线路质量很差或者被限速了。

抓包是临时的诊断手段,抓完就关。线上环境流量大,别让 tcpdump 一直跑着刷磁盘。真要长期监控,用 tcpdump -w file.pcap 落盘后离线分析,或者直接上带统计功能的监控工具。

「我重装一下系统,应该没事吧?」——这句话几乎是事故的开始。换系统、升级内核、改关键配置、装大型软件之前,花两分钟打一个快照,出事就能一键回滚,十分钟的事变十秒钟,这是性价比最高的运维习惯。

快照(Snapshot)是磁盘在某一个时刻的完整副本,包含系统、数据、配置,等于给机器拍了个「后悔药」。它和备份的区别在于:备份通常只保数据,快照是整机级别的还原点,换系统这种操作只有快照兜得住。

搬瓦工的 KiwiVM 面板里,快照功能就在左侧菜单,操作非常简单:

KiwiVM → Snapshot → Create New Snapshot
# 等待生成,几十 MB 的机器一般几分钟内完成
# 需要回滚时:Snapshot → 选快照 → Restore

打快照的两个纪律:第一,操作前打,养成条件反射;第二,重要变更比如系统升级、数据库迁移,打完快照再动手,万一失败直接 Restore,不用在错误现场挣扎。

快照也有局限性,别把它当万能保险。第一,快照占存储空间,商家对快照数量有上限,定期清理旧的,只留最近几个;第二,快照是「回退」工具不是「恢复」工具,它回滚的是整个磁盘状态,如果机器整体挂了(比如被挖矿、被入侵),快照可能连同坏状态一起存着;第三,真正要防「整机没了」的场景,还是得靠异地备份,也就是第 09 条讲的那套。

一句话总结:快照管操作失误,异地备份管天灾人祸,两个都要有。

面板上显示的流量和实际出口流量经常对不上,原因很多:面板按网卡统计,可能漏掉环路流量;商家计费口径和你的理解不一致;还有的自己测数据本身就是估算。真想精确掌握自己用了多少流量,在机器上装 vnstat,让数据自己说话。

Debian/Ubuntu 装 vnstat 一条命令,初始化网卡后就能看统计:

apt install -y vnstat
vnstat -u -i eth0
vnstat -d

第一行安装,第二行让 vnstat 从当前时刻开始统计指定网卡,第三行看按天的统计表。vnstat 是常驻后台的服务,装完就自动采集,几分钟后就能看到第一个小时的数据,一天后就有日报了。它默认保存完整历史,还能用 vnstat -m 看月统计、vnstat -l 看实时流量。

流量超标是有成本的,尤其按流量计费的套餐,超了要么限速要么加钱。所以养成习惯:装好 vnstat 的第一天,就配一个每日流量报告到邮箱。cron 里一行搞定:0 8 * * * vnstat -d | mail -s "今日流量" you@example.com,或者更简单,每周自己看一眼 vnstat -m 的月度余额。

如果你的机器被恶意攻击或者中了马,流量会异常飙升,vnstat 的日报就是最好的预警——某天流量突然翻三倍,别犹豫,马上去看是不是被扫描了、被人拿去当肉鸡跑流量了,检查 ss -lntp 的对外连接和进程列表。

最后说口径:面板流量一般统计的是网卡收发总和,vnstat 统计的也是网卡层,两者理论上应该接近。如果差距大,优先信自己机器上的数据,再拿着数据去和商家工单掰扯。

没验证过的备份等于没有备份。备份成功只能证明「文件写出来了」,证明不了「灾难发生时数据能回来」。有多少人直到服务器真的宕机,才发现备份文件是坏的、恢复流程是断的、关键依赖是缺的——而这一切,本可以在平时花一小时演练就发现。

恢复演练的标准动作是「异地还原」:把备份拉到一台临时机器上,完整走一遍还原流程,然后验证两点——数据是不是完整的,服务能不能正常启动。对数据库就是 gunzip db.sql.gz | mysql 导回去,然后跑一条关键查询确认记录数对得上;对网站就是把文件解包到临时目录,确认页面能打开。

演练的频次建议一季度一次,正好和服务器硬件寿命、证书续期周期错开,不重不漏。每次演练都记录三样东西:用的哪个备份、耗时多久、有没有问题。一份简单的文档就够,格式随意,关键是下次能照着做。

演练不是走过场,发现的问题是金矿。常见演练翻车点:备份文件在传输中损坏(gzip 校验不过)、恢复流程依赖某台机器上的工具没装、数据库版本对不上导致导入失败、异地备份其实早就因为磁盘满没推上去。每发现一个,修复一个,你的恢复能力就实打实强一分。

真出事那天,你靠的不是运气,是平时那几次无聊的演练。把「季度恢复演练」写进你的运维日历,这是全文最后一条,也是最贵的一条经验——免费,但价值千金。