最近笔记本经常使用一段时间后变卡,应用程序无故无法启动和关闭,打开系统软件(系统偏好设置、Finder等)会出现迷之报错。
原本2、3个月才会重启一次的我,现在1天1重启。
如果遇到进程已经满负荷状态下的锁定/卡死时,运行中的应用程序无法退出(强制退出,kill进程都无效),重启就会卡住怎么都不会重启,只能强制关机再开机了。如果你运气好,有个进程退出了,让你有足够的资源打开命令行的话,可以执行命令重启:sudo reboot
。
错误提示:fork fails : resource temporarily unavailable
当遇到这个错误时,就说明你的进程数量太多,已经达到了系统最大进程限制。但是我就开了几个软件,并没有大刀阔斧的开十几个程序的盛况。
ulimit -u # 查看最大进程值
查看问题进程
上网搜索了下相关信息,基本可以确定是某个程序一直在不断的fork新的进程消耗系统资源了。
用ps aux
大致的预览一下有多少cron进程,它们全都是僵尸进程(Status : Z )。
随便找一个僵尸cron进程看看它的父进程是谁:
ps -ef | grep [pid]
你可能需要多找几次父进程才能追溯到源头。我的源头是PID=1 的/sbin/launchd
…… 这说明我拿它没办法。
确保检查crontab
首先我们要用从最简单的角度出发,确保你没有意料之外的任务计划!
这个问题在Google了一圈后发现还是有不少人遇到的,而且发生在Catalina里,甚至有人6年前的脚本遗忘在里crontab计划中,却没有造成进程负担,而升级到Catalina后问题才暴露出来。
注意,每个用户都有自己的crontab 清单,sudo crontab -l
和crontab -u [username] -l
会有不同。确保检查了所有用户包括root的计划任务内容。
sudo crontab -l # 查看root用户的任务清单
crontab -l # 查看当前用户的任务清单
crontab -u [username] -l #查看其他用户的任务清单
别忘了,还有cat /etc/crontab
和sudo cat /usr/lib/cron/tabs/crontab
中也许会有意想不到的收获。
活动监控器
系统的“活动监控器” 采样cron
的信息没有参考价值。不看也罢。
查看系统日志来找活动服务迹象
在我找到问题根源之前,我会每隔一小会儿执行一个查看cron进程总数的命令:
ps -ef | grep cron | wc -l
大概每隔一分钟左右会增长几个,比较有规律。我想到去查看下系统日志:
#查看最后100行日志
tail -n 100 /var/log/system.log
com.apple.xpc.launch[1]
引起了我的注意,因为它的PID是1:
有一项服务com.qiuyuzhou.shadowsocksX-NG.local
每隔10秒一直在请求什么。这个频率跟cron进程数的增长有点接近。
这是一个后台运行的服务,shadowsocksX-NG的github README 中有这么一段话:
ss-local
is run as a background service through launchd, not as an in-app process. So after you quit the app, thess-local
might be still running.
我想起上个月才删掉的小飞机的确是开启了ss-local的,这个服务做为Launch Agent还一直在后台运作。
我现在只需要把这个服务给删除就行了,由于小飞机已经被我删了,所以这里无法用launchctl unload
命令了。
cd ~/Library/LaunchAgents
#确认名称
ls
# 停止服务
launchctl stop com.qiuyuzhou.shadowsocksX-NG.http.plist com.qiuyuzhou.shadowsocksX-NG.kcptun.plist com.qiuyuzhou.shadowsocksX-NG.local.plist
# 取消服务
launchctl unload com.qiuyuzhou.shadowsocksX-NG.http.plist com.qiuyuzhou.shadowsocksX-NG.kcptun.plist com.qiuyuzhou.shadowsocksX-NG.local.plist
# 删除服务
rm com.qiuyuzhou.shadowsocksX-NG.http.plist com.qiuyuzhou.shadowsocksX-NG.kcptun.plist com.qiuyuzhou.shadowsocksX-NG.local.plist
后续补充:由于我当时删的比较快,不确定小飞机的plist中的服务有没有调用cron
。也就是无法确定与本文的问题中心是否有关联性,不过我仍然愿意分享下这块处理的过程,因为在下边提到launchctl
时,或许对你们会有帮助。
然后重启系统。如果重启后还有cron进程大于1的情况(当没有计划任务时,cron进程为1才是正常的),那就是还有其他cron任务随系统启动了。
查看随系统启动的脚本
如果上边的方式仍然没能让cron进程停止增长,那么就需要稍稍进阶一点的排查方式。本方式有风险,建议先Time Machine下。
launchctl
命令负责收集和提供基于plist注册的脚本启动服务,有别于crontab
,但性质很接近。
sudo launchctl list
输出具有以下含义:
- 第一个数字是进程的PID,如果它正在运行,如果它不运行,它显示一个‘-’
- 第二个数字是进程的退出代码,如果它已经完成。如果是负数,则是杀死信号的数量
- 第三列是进程名称
如果你无意中发现有个叫com.vix.cron
的可疑份子,不用理它,因为它就是crontab,由系统接管(via)。
plist文件的位置:
- ~/Library/LaunchAgents 由用户自己定义的任务项
- /Library/LaunchAgents 由管理员为用户定义的任务项
- /Library/LaunchDaemons 由管理员定义的守护进程任务项
- /System/Library/LaunchAgents 由Mac OS X为用户定义的任务项
在这几个目录下,如果你遇到了可疑的、不明确的,建议问下搜索引擎。比如你曾用过VM虚拟机、百度输入法、搜狗输入法,后来删掉了App,但是含有VM、baidu 、sogou字样的plist还在,你就可以直接rm
它的plist。
如果你是因为中毒引起的cron爆增,在这里找启动脚本,绝对是正确的。
你可以在重启后等几分钟再登入你的用户,然后立刻查看cron的进程数来判断服务是在登录前还是登录后,还是系统启动就立刻追加了进程。根据这些判断,前往对应的plist文件目录,勘查里边的文件。
这一步会很麻烦,我没有找到更高效的办法。一台使用了10年的OS X必定会有一大堆的文件垃圾等待着你整理和收拾。配合system.log
会事半功倍,但是对于已经删除的App,一些见都没见过的服务在跳动着努力奉献年迈感的日志信息,会让你的眼睛很难受。这一刻,没有关键字(目标)的时刻,无高亮!
以上,能够解决Catalina中cron进程爆多的有效方法,分别为crontab
彻底排查和plist文件排查。
扩展阅读
有一篇文章提供了给我很重要的思路,大家可以点击这里前往阅读。
发表回复