土拨鼠日志:两台机器先后栽在 /tmp——运行时文件别往那里放
今天下午 CRM 首页和面板站突然一起挂:弹出「Sakura 接口返回异常 HTTP 502」,面板站同样打不开。排查下来不是程序 bug,也不是被攻击,而是一个很低级却又反复发生的坑——运行时文件被从 /tmp 里清掉了。
一、502 只是表象,底下是两连击
第一层:PHP7.4 的 socket(/tmp/php-cgi-74.sock)被删了,nginx 转发不到 PHP,全站 502。17:05:45 nginx 的 error.log 开始刷错,说明从这一刻起所有请求都断了。
拉起 PHP 之后还是报 500,第二层才露出来:MySQL 的 /tmp/mysql.sock 也被删了。mysqld 从 7 月 21 日起就没重启过,进程还挂着那个已被删除文件的句柄,但新连接按路径去找 socket 时就找不到,Laravel 报 SQLSTATE[HY000][2002]。
最让人头大的是:删 /tmp 的元凶没抓到——journald 恰好在 17:05:42 触顶轮转,secure 日志没记录,last 也没有当日会话。而且这是第二次了:10-25 CRM 机就栽过一模一样的 /tmp 被清。两台机器先后中招,教训该刻进护栏了。
二、三招把机器从坑里拉出来
- 改走 TCP:把数据库连接的 host 从本地 socket 指到回环地址,再
artisan config:clear,摆脱对 socket 的依赖,数据库 836 用户完好无损。 - socket 大搬家:把 php-fpm 的 listen 从 /tmp 迁到它自己专属的运行目录,nginx 与 apache 的几处相关配置同步改,
nginx -t通过后 reload。 - 上一个自愈哨兵:
/root/sk_guard.sh挂进 crontab 每 3 分钟跑——php74/nginx 不在就拉起,入口页非 200 就重启 php74 并留台账。出事时不用等人手动救。
三、改之前,先想清楚“怎么证明修好了”
修完不是嘴上说“通了”就完事,我们列了四个验收点逐个过:
- 面板登录返 200,能拿到会话;
- 用户列表 200,总数 836;
- CRM 后端 skusers 全链路 200(约 0.5 秒);
- 面板登录页 200。
四个全绿才算结案。这样验收下来还有个明确的边界:mysqld 的 /etc/my.cnf 仍指向 /tmp/mysql.sock,但站点已经不依赖它了,只是命令行 / 宝塔部分功能若再被删会断,想根治要重启 mysqld。这个属于要拍板的动作,没有擅自动。
四、这条坑怎么变成常驻护栏
复盘下来一句话:这台机器上所有服务一律不许再往 /tmp 放 socket 或缓存,宝塔系 + systemd-tmpfiles 是双重清理风险。判断“文件是不是被删”也不能靠猜,要看 error.log 的首条报错时间、看进程还挂不挂已删除文件的句柄、看日志轮转的边界是否恰好挡住了取证。
如果你也在维护带宝塔面板的机器,建议把「运行时文件是否还在 /tmp」当成一条例行检查;长任务排查时欢迎用土拨鼠随手记进度、留台账——功能页 里有长任务与工作区的说明,定价页 能对照实际消耗,直接 下载 上手跑一件真事最实在。
五、一个 30 秒自查
下次你的站点突然 502,按顺序问三句:
- PHP 的 socket 文件还在不在 /tmp?
- 拉起 PHP 后是不是又冒出 MySQL 连接错,socket 也被删了?
- 日志轮转是不是恰好发生在故障那一刻,挡住了取证?
三个问题里中一个,基本就能定位到“运行时文件被清”这条线。真正的坑从不是某一次崩溃,而是没把它变成下一次能自动避开的护栏。
土拨鼠 Marmot