服务器 CPU 打满但业务量不高:定时任务与挖矿木马排查路径

业务量明明不高,服务器 CPU 却长期跑在 90% 以上——这是很多站长都遇到过的诡异场景:网站访问量没有明显增长,订单也没有暴增,但监控面板上的 CPU 曲线一直顶着红线。如果你也遇到这种情况,先别急着升级配置,因为大概率不是资源不够,而是有进程在“偷”你的算力。

本文要解决的正是这个问题:如何在一台业务量不高的服务器上,找出 CPU 被占满的真实原因,重点覆盖两条最常见的路径——失控的定时任务,以及近年高发的挖矿木马。整个过程只需要命令行和系统自带工具,不需要额外安装监控软件,跟着排查步骤走,大多数情况下 30 分钟内就能定位元凶。

服务器CPU过载排查主题封面插图

先定位:到底是谁在吃 CPU

排查的第一步永远是确认“嫌疑人”,而不是凭感觉重启。SSH 登录服务器后,先用 top 看整体情况:

top -b -n 1 | head -20

重点关注两列:%CPU 排名最靠前的进程,以及 us(用户态)和 sy(内核态)的占比。如果 us 长期接近 100%,说明是某个用户进程在大量消耗算力;如果 load average 远高于 CPU 核心数(比如 4 核机器 load 到 20 以上),还要警惕是否有大量等待 I/O 的进程。

找到占用最高的进程后,记下它的 PID 和所属用户。这里有一个关键细节:看进程的用户。如果业务进程都属于 www 或 nginx 用户,而某个高 CPU 进程跑在 nobody、daemon 甚至随机用户名下,这本身就是强烈的异常信号。接着用这条命令查看该进程的完整启动命令:

ps -fp <PID>

如果命令行是一串乱码路径(比如 /tmp/.x/kinsing、/var/tmp/.systemd/ 这类藏在临时目录里的可执行文件),基本可以判定不是正常业务。此时可以用 ls -l /proc/<PID>/exe 确认进程真实对应的二进制文件位置——挖矿木马最常见的藏身目录就是 /tmp、/var/tmp 和 /dev/shm,因为这三个目录重启后内容可能被清理,攻击者喜欢把样本丢在这里。

路径一:定时任务失控与被篡改

CPU 打满的第二大常见来源是定时任务。它的问题在于隐蔽:单次执行可能只跑几秒,但 cron 调度频繁,或者脚本逻辑失控(比如没有退出条件的循环、误写的递归备份),累积起来就把 CPU 吃光了。更危险的情况是定时任务被攻击者篡改,成为木马的“保活”机制——即使你手动杀掉进程,几分钟后它又会被 cron 拉起来。

先盘点系统里所有 cron 入口,把下面这些位置挨个过一遍:

crontab -l                          # 当前用户的定时任务
ls -la /etc/cron.d/ /etc/cron.daily/ /var/spool/cron/
cat /etc/crontab

审查时有三个识别要点。第一,看执行频率:* * * * * 这种每分钟执行一次的任务,如果脚本本身耗时超过 1 分钟,进程会不断堆积,CPU 就是这样被打满的。第二,看执行内容:正常业务的定时任务通常有明确语义(备份数据库、清理日志),而可疑任务往往是一行 curl 或 wget 从外部地址下载脚本再交给 bash 执行,这类“下载即执行”的任务几乎可以确定是恶意的。第三,看文件修改时间:用 stat /etc/cron.d/<文件名> 查看改动时间,如果某个你从未配置过的任务出现在最近几天,就要高度警惕。

确认可疑任务后,处置顺序有讲究:先删除任务条目,再清理它调用的脚本文件,最后杀掉进程——如果顺序反了,先杀进程而任务还在,cron 会立刻把它拉起来。另外别忘了检查 at 队列(atq 命令)和 systemd timer(systemctl list-timers),这两个位置同样是定时执行的前置入口,排查时经常被遗漏。

通过进程列表定位高CPU占用进程的示意图

路径二:挖矿木马的识别与清除

如果定时任务里发现了“下载即执行”的条目,或者高 CPU 进程藏在临时目录,基本可以按挖矿木马处理。这类木马的目的很纯粹:利用你的服务器算力挖加密货币,所以它的特征也非常鲜明——CPU 长期满载、进程名伪装成系统进程、杀掉后自动复活。

清除要按“断再生 → 杀进程 → 清残留”的顺序做。第一步先处理再生机制,除了上面说的 cron,还要检查这几个位置:

ls -la /etc/ld.so.preload 2>/dev/null    # 动态链接劫持
systemctl list-timers --all | head -15
ls -la ~/.ssh/authorized_keys            # 是否被塞入陌生公钥

/etc/ld.so.preload 是很多挖矿木马用来隐藏自身的手段:它通过预加载一个恶意动态库,让 top、ps 等工具看不到木马进程。如果你发现这个文件存在但内容指向不明 so 文件,先把它清空,再重新执行 top——很多时候“看不到的进程”这时才会现形。

第二步是杀进程。对藏身 /tmp 的木马,直接 kill -9 <PID> 之后立刻删除对应的二进制文件和所在目录,避免 shell 历史或其它机制再次执行它。第三步清残留:检查 ~/.ssh/authorized_keys 里有没有不认识的公钥(攻击者的后门),检查 last 和 lastb 里的异常登录记录,必要时修改所有账号密码。整个流程走完之后,观察 24 小时:如果 CPU 回落正常且没有新进程复活,才算清除成功。

顺带说一句权限层面的预防:多数挖矿木马是利用弱口令或未授权服务进来的。把 SSH 改成密钥登录、禁用 root 直接登录、关闭用不到的端口,这三件事做完,中招概率会大幅下降。如果你的业务跑在多台服务器上,一台中招后其它机器也应按同样路径过一遍,攻击者拿到内网跳板后横向移动是常见操作。

定时任务审计与可疑计划任务识别示意图

服务器安全防护抵御挖矿木马示意图

一组真实对照数据

用一个典型案例说明排查的收益。某外贸站客户的服务器(4 核 8G)连续一周 CPU 跑在 85% 以上,网站打开要 8 秒多,业务高峰期甚至超时。起初运营建议直接升配到 8 核,但排查后发现:是一个每分钟执行一次的全量备份脚本失控了,每次执行要 90 秒,进程不断堆积;同时 /etc/cron.d/ 里还有一个陌生的下载任务在拉起挖矿程序。按本文路径处理完之后,同一台机器 CPU 降到 15% 以下,页面打开时间回到 1.2 秒,没有花一分钱升级费用。

这个案例的对照很直观:

场景 处理方式 CPU 占用 页面响应
升级前(脚本失控 + 挖矿木马) 未处理 85%+ 8 秒
直接升配(未排查) 4 核升 8 核 预计仍 80%+ 改善有限
按排查路径处理 清任务 + 清木马 15% 以下 1.2 秒

直接升配看似省事,实际是给失控任务和木马更多算力,问题只会被掩盖。排查定位虽然多花半小时,但解决的是根因。这也是我们在处理 服务器性能 类工单时始终坚持的原则:先确认资源去了哪里,再决定要不要加资源。

如果排查之后确认是业务真实增长导致负载上升,那么升级才是合理选择。这时可以评估迁移到更高配置的 VPS 主机(VPS 即虚拟专用服务器,资源独享、性能稳定),或负载更大的业务直接上 独立服务器(整台物理机归你独用,不存在邻居干扰)。而共享环境下的 虚拟主机 虽然有资源隔离机制,但排查思路同样适用——先看进程和定时任务,再看真实资源需求。

总结与下一步建议

回顾整条排查路径,核心逻辑只有三步:先用 top 和 ps 定位高 CPU 进程的真实身份,再检查 cron、at、systemd timer 这些定时入口有没有失控任务或被篡改的条目,最后按”断再生、杀进程、清残留”的顺序清除挖矿木马并验证 24 小时。多数”业务量不高但 CPU 打满”的情况,元凶就藏在这三步之中。

给你三条可以直接执行的建议:

  • 今天就花五分钟跑一遍 crontab -l 和 ls /etc/cron.d/,确认每一个定时任务你都能说清用途——说不清的就是风险
  • 检查 SSH 是否还允许密码登录,如果是,尽快切换到密钥登录并禁用 root 直接登录
  • 为服务器配上基础的资源告警(CPU 连续 15 分钟超 80% 就通知),早发现比事后清理成本低得多

如果你需要一台排查之后仍不够用的升级方案,或者希望托管环境自带资源隔离和监控告警,可以考虑了解 Hostease 的服务器产品线,我们建议先明确业务的真实资源画像再做选择,避免为失控任务和木马买单。把本文的排查路径存下来,下次 CPU 再飙高时按图索骥,大概率半小时内就能找到答案。

发表评论