今天突然发现网站文章无法发布。这个站点是用 Hexo 框架生成的静态网站,执行 hexo clean && hexo g && hexo d 时,之前一直正常的流程这次报出 Error: Spawn failed。
这串报错信息本身不太友好,点开官方提供的 troubleshooting 链接,也看不出和当前问题有多大关系。由于从没遇到过 Hexo 的这类报错,我第一反应是 node_modules 依赖不完整。
排查思路如下:
- 进入站点根目录:
cd D:\GitBog3.0
- 删除
node_modules 目录,重新安装依赖
- 清除缓存:
npm cache clear --force
- 重新安装依赖:
npm install
再次执行 hexo clean && hexo g && hexo d,结果仍然是同样的报错,基本可以判定不是依赖问题。
随后去网上搜索 Error: Spawn failed,常见的解决方案是:
- 进入站点根目录:
cd D:\GitBog3.0
- 删除 Git 提交目录:
rm -rf .deploy_git
- 执行命令:
git config --global core.autocrlf false
- 重新执行:
hexo clean && hexo g && hexo d
可惜这套操作试完后,问题依旧。不能再继续盲目折腾了,于是重新查看完整日志,才发现最上面还有两行一直被忽略:
ssh: connect to host 121.xx.xx.xx port 22: Connection timed out
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
FATAL Something's wrong. Maybe you can find the solution here: https://hexo.io/docs/troubleshooting.html
Error: Spawn failed
at ChildProcess.<anonymous> (D:\GitBog3.0\node_modules\_hexo-util@2.7.0@hexo-util\lib\spawn.js:51:21)
at ChildProcess.emit (events.js:315:20)
at ChildProcess.cp.emit (D:\GitBog3.0\node_modules\_cross-spawn@7.0.3@cross-spawn\lib\enoent.js:34:29)
at Process.ChildProcess._handle.onexit (internal/child_process.js:277:12)
这两行已经说得很明确:SSH 连接失败了。
这让我想起最近服务器一直被频繁攻击。24 号那天还被恶意登录,短短 2 分钟就塞进来一堆木马文件。

当时我正在打游戏,手机短信、微信、邮箱不停收到腾讯云的安全告警,响个不停。

当时倒没有慌,先登录服务器后台,二话不说先关闭服务器,然后继续把游戏打完。

等游戏结束,才开始处理这次攻击:
- 查看登录日志,发现登录的是 root 账户,还是国外这种可疑的 IP 地址,问题比较严重。
- 先把 root 账号的密码升级成更复杂的密码。
- 木马文件通常会被隐藏,直接在服务器里手动查找很难发现。如果不想逐个排查,可以借助云厂商的主机安全能力,以腾讯云为例:
- 登录腾讯云控制台,搜索“主机安全”;
- 进入左侧“主机列表”,选择对应主机;
- 点击左侧导航“入侵检测” → “文件查杀”;
- 将扫描出的可疑文件全部隔离。


一看基本都是挖矿木马,我这服务器配置挺一般,居然也被盯上了。接着检查服务器端口、CPU、内存、磁盘等各项指标,确认没有其他异常后,才开始慢慢恢复网站服务,并重启各种中间件容器,折腾了整整一晚上。如果还不行,可以参考腾讯云官方文档 Linux 入侵类问题排查思路。
但是过了几天,服务器又被国外 IP 异常登录。这个时候我发现,攻击者的破解能力很强,root 密码已经加到 20 多位,还是没用几天就被破解了。可以想象,服务器的常用端口一直在被扫描,尤其是 SSH 默认的 22 端口。为了稳妥起见,直接把默认的 22 端口禁掉,换成一个不常用的端口。
修改 SSH 端口步骤如下:
- 以 root 权限登录系统,执行:
vim /etc/ssh/sshd_config
- 找到
#Port 22
- 在下面新增端口号,例如:
Port 9999(自己设定,最大不超过 65535,注意不要泄露端口)
- 编辑完成后,先按
ESC,再输入 wq 保存退出
- 重启 SSH 服务:
systemctl restart sshd.service。新增或删除端口都必须重启,否则不生效
- 最后别忘了在防火墙放行新端口
9999
为了更安全,还可以进一步把 root 用户直接禁用,权限太高有时反而麻烦。
这时我才意识到,之前已经改掉了 SSH 默认端口,而 hexo d 通过 git 将网站部署到服务器上时,会去访问 ssh 登录端口。服务器侧端口改了,但本地 Hexo 配置文件没有同步修改,所以推送一直连不上。于是直接到电脑站点根目录修改 _config.yml:
deploy:
type: git
repository: git@111.11.1.11:/home/git/hexo.git
branch: master
这里因为我们使用 hexo-deployer-git 插件完成 Git 部署,它无法直接指定 SSH 登录端口,需要改成下面这种写法:
deploy:
type: 'git'
repo:
site: ssh://git@111.11.1.11:port/home/git/hexo.git,master
branch: master
其中:
git 是用户名
111.11.1.11 是服务器 IP 地址
port 是 SSH 端口
master 是 Git 私有库分支
/home/git/hexo.git 是服务器上 Git 仓库路径
保存配置后,再次执行 hexo clean && hexo g && hexo d,网站内容就正常推送到服务器了。
回过头看,本文提到的各个解决方案本身并不复杂,真正关键的是如何找到原因。拿到报错后,先不要急着把错误信息直接丢给搜索引擎,而应该停下来先读完完整日志。像这次,只要看到日志最前面的 SSH 连接超时,方向就清楚了:修改 SSH 端口、同步 Hexo 部署配置、恢复服务。
服务器被攻击之后也不用慌张,按“先止损隔离、再排查清理、然后检查资源、最后恢复服务”的流程操作,通常能少走很多弯路。平时遇到问题,多分析异常信息,尝试后根据反馈继续推进;搜索可以用,但不能完全依赖搜索引擎。