前言
大概从两年前开始,我就有意识到这台服务器运行半年左右内存就会被吃满,当时还没怎么注意,只觉得是系统运行时间太长了重启就好。
直到从去年开始,服务器几乎一个多月内存就会被满,然后没过多久 CPU 就直接满载,在此期间服务器会失去响应,自己的博客挂了问题倒是不大,关键是服务器上仍负载有尝鲜派的业务。几乎每个月都会来一次 502,每个月都要重启,这着实让我感觉很迷惑,两三个月前已经把 Ubuntu 从 16.04 升级到了 18.04,但问题依旧没能解决。
之前有跟 Hintay 研究过一两次,但因为监控得到的数据是在有限,都以失败告终。
这两天,它又开始了。
这次下定决心要来解决,得益于 Hintay 的帮助,我们找到并解决了问题。
寻找根源
进入监控,找到服务器无响应的时间点,将范围定在 18:15-18:19 之间
得到下图,无响应期间 CPU 几乎处于 100%,内存已经基本上满了。
查看无响应期间的活跃进程排名第一的就是 unknown,PID 41 看起来是个系统级别的进程。
然后我直接来个 ps aux 查看所有进程,找到 pid 41
呃 什么鬼,kswapd0
这玩意不是搞内存交换的吗。那看来系统并没有染上什么病毒,只是由于物理内存耗尽导致服务器需要频繁进行内存交换,进而导致 CPU 满载。那么问题来了,nginx mysql php 在监控里看到的内存占用都不高,把他们三个全部关闭后内存占用率仅下降了 10%?这特么是内存泄漏?就很无语。
然后我装了个 htop
来看内存的情况,Hintay 装了个 longview(linode 的监控)
然后他发现,我们服务器上的 python3 居然发了疯的占了 2GB 的内存,与此同时我在 htop 也看到了与 python3 有关的进程占了一整页???离谱。
从 htop 中得知 python3 打开的脚本是我们的一个需要定时执行的任务。
总结一下就是这两年来我们的服务器每天晚上都会执行一次某脚本,执行完之后 python3 没有退出。进入19年某业务升级后,服务器每十分钟都会执行一次这个脚本,然后还没退出,刚好对上了近两年服务器平均只能跑一个月就要重启,不然就要内存满了。
解决
那么现在知道内存满了是因为 python3 的锅,找到 crontab 执行的命令是 /usr/bin/python3 xxx.py >> xxx.log
这看起来很正常啊,但从 htop 里观测到的结果是,这条语句会被解析成 /bin/sh -c /usr/bin/python3 xxx.py >> xxx.log
好家伙,一跑起来压根就没执行 xxx.py 脚本,直接进入 python3 Interpreter 而且还不会 exit()。
我上来直接 killall python3
内存使用量直接降到30%
离谱
后来解决了定时执行 python 脚本
将命令存入 sh 脚本中
#!/bin/bash
SCRIPT=$(readlink -f "$0")
SCRIPTPATH=$(dirname "$SCRIPT")
cd "$SCRIPTPATH"
/usr/bin/python3 xxx.py > xxx.log 2>&1
/usr/bin/python3 xxx.py > xxx.log 2>&1
重新修改 crontab 的配置为
*/10 * * * * bash /path/to/cron.sh
问题大概就解决了,现在定时正常跑,不会出现 python 不退出的情况了。
离谱,困扰我们两年多的问题终于解决了。
文章最后修订于 2021年7月16日
果然搞技术就是不一样,技术文章看了老半天,一知半解。
@飞牛士: 这就对了 我乱写的
@Jacky: 优秀。
求一个主题包
@jiao: 这个做不到哈 他这个主题加密了
我给你我自己的授权就没了
请支持正版
@jiao: 这个主题不太适合博客,你需要可以去找免费的主题,我推荐一个给你lovestu.com,主题是果核大佬写的,速度快,bug少。我用过一段时间。
@飞牛士: 确实 建议尝试其他主题