Linux 幕后黑手 crontab

cody · 2020年04月18日 · 最后由 cody 回复于 2020年04月24日 · 3031 次阅读

前端时间搭了一服务,这个服务需要每隔一定的时间处理一些业务,因为用的 Mac 系统很自然就想到了使用 crontab,网上查了一下 crontab 的用法很快就配置完毕了。但是好景不长,自从配置完定时任务后,每隔一段时间这台服务器就会莫名的卡死,头几次单蠢的认为只是简单的机器故障,我使用了大招【重启大法】解决了。但是因为上面有些服务不能启动自拉启,重启一次有些麻烦。恰好今天又出现了,就详细排查了一下原因,当我查看进程的时候,我这个人都麻了

... 这里我省略了N行类似的记录

root               499   0.0  0.0  4298116    376   ??  S    12:15PM   0:00.00 /usr/sbin/cron
root               251   0.0  0.0  4290180    964   ??  Ss   12:14PM   0:00.01 /usr/sbin/cron
root              1007   0.0  0.0  4298116    376   ??  S    12:48PM   0:00.00 /usr/sbin/cron
root              1173   0.0  0.0        0      0   ??  Z    12:50PM   0:00.00 (cron)
root              1090   0.0  0.0        0      0   ??  Z    12:49PM   0:00.00 (cron)
root              1017   0.0  0.0        0      0   ??  Z    12:48PM   0:00.00 (cron)

启了这么多进程,而且还有 N 多僵尸进程,妈个鸡。

为什么会启这么多进程?为什么还有这么多僵尸? 小朋友我真的有很多问号??????

难道定时执行的脚本有 Bug?我手动执行了一下,输出正常。
难道定时执行的脚本权限不对?我又查看一下脚本的权限,所有组别都有执行权限。
我在哪儿?我是谁?我要干啥??? 好吧,我上个厕所冷静一下。

这么成熟的东西不应该有问题,肯定是我打开姿势不对,又在网上看看了别人写的例子,偶然发现都把输出干掉了 /dev/null 2>&1
我尝试着加了一下,妈呀! 好了。。。

有修改了一下关键词查了查,发现有人确实也有对应的情况,但是他解释了因为脚本的日志输出会触发系统sendmail,因为内容多就堆积了。。。好吧,我大概也是如此了。

共收到 10 条回复 时间 点赞

需要干掉输出的内容 就没事了?

cody #2 · 2020年04月19日 Author
向阳 回复

是的,干掉就 OK 了

以上 ---> crontab 产生日志,没有处理导致机器挂了(说实在我感觉写文的人自己都不确定,这难道是写小说么)

这个问题挺有意思的。

我本地试了下:

$ crontab -l
* * * * * /bin/date
* * * * * cat /Users/hengjiechen/pgadmin.log > ~/crontab.log 2>&1

# 确认 date 是不是会持续存在
$ ps aux | grep date
...
hengjiechen      45574   0.0  0.0        0      0   ??  Z    10:32PM   0:00.00 (date)
hengjiechen      45542   0.0  0.0        0      0   ??  Z    10:31PM   0:00.00 (date)

# 看下 mail 是不是有增加
$ mail
No mail for hengjiechen

# 查看同时段其它进程情况
$ ps aux | grep 10:32
root             45573   0.0  0.0  4297100     92   ??  S    10:32PM   0:00.00 /usr/sbin/cron
root             45575   0.0  0.0        0      0   ??  Z    10:32PM   0:00.00 (cron)
hengjiechen      50546   0.0  0.0  4269212    476 s002  R+   11:16PM   0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn 10:32
hengjiechen      45574   0.0  0.0        0      0   ??  Z    10:32PM   0:00.00 (date)

# 查看这几个进程之间的关系
$ pstree 45573
-+- 45573 root /usr/sbin/cron
 |--= 45574 hengjiechen (date)
 \--- 45575 root (cron)

# 删掉最上层的 crontab 进程
$ sudo kill 45573

# 确认删除结果
$ ps aux | grep 10:32
hengjiechen      50608   0.0  0.0  4287752    728 s002  S+   11:18PM   0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn 10:32

从现象上看:
1、crontab 定时执行,每次执行会新建一个进程。
2、如果任务中有些命令没有重定向输出,会持续存在,进程不会自动结束。而有重定向的会自动结束。
3、mail 默认收不到 crontab 日志通知。至于什么原因,待探究。

至于原因嘛,还在查询中,这方面资料太少了,大多只是说要用重定向,但基本都没提及不用的话会怎样。

cody #5 · 2020年04月20日 Author
hellohell 回复

感谢指正
这个问题确实和脚本输出的日志,crontab 中产生输出就会发送 mail
可以在 crontab 中加入 MAILTO="",也可以解决这个问题。目前我了解到的这个应该跟 mac osx 10.15.1 系统有关系,我本地 crontab 正常运行并且可以在/var/mail 下找到对应的邮件内容,但是服务器上没有,具体为什么没有确实不得而知。另外抱歉个人文笔不好,我一定努力提高。

cody #6 · 2020年04月20日 Author
陈恒捷 回复

兄弟,你系统版本是多少?

cody 回复

10.15.1 (19B88)

cody #3 · 2020年04月22日 Author
陈恒捷 回复

那就是新系统的锅,石锤了。10.15 后根目录都变成只读了。

前端 or 前段?

cody #10 · 2020年04月24日 Author
开普敦人 回复

细心如你,感谢指正。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册