前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Cron运行原理

Cron运行原理

作者头像
一见
发布2018-08-10 17:59:40
3.8K0
发布2018-08-10 17:59:40
举报
文章被收录于专栏:蓝天蓝天

Cron运行原理.pdf

1.?前言

本文介绍的是由Paul?Vixie开发的运行在SuSE?Linux上的Cron。可以通过“man?cron”进行确认。

2.?示例

#?示例用来配合本文的说明

*/1?*?*?*?*?echo?hello?>>?/tmp/hello.txt

3.?工作过程

Cron每分钟做一次检查,看看哪个命令可执行。

从上图可以看到,有4次fork,这4次fork分别是:

1)?第一个fork,让Cron自己成为Daemon进程,即成为守护进程;

2)?第二个fork,当Cron检查到有命令需要执行时被创建,但注意它并不执行命令,执行命令由它的子进程来做;

3)?第三个fork,有些版本调用的是vfork,但有些版本却是fork,它是负责执行Cron命令的进程,即会调用execle()的进程;

4)?第四个fork不是必须的,只有为Cron命令配置了标准输入才会用:

*/1?*?*?*?*?/tmp/X/x%1234567890

像上面有个百分符“%”,后面跟一串,则会有第四个fork,它的作用是将“%”后面的内容作为标准输入传递给第三个fork出来的进程。

注意fork出来的进程没有忽略(ignore)管道信号(SIGPIPE),所以如果遇到SIGPIPE,则会导致进程无声无息的退出,比如标准输主输出重定向管道的读端被关闭了,写时就会触发SIGPIPE。

实践中,可能会遇到child_process()在做上述所说的第三个fork前因SIGPIPE信号退出,导致难以理解的问题。其中一个现象是:Cron命令被执行了若干次,但之后再也不执行了,原因在于第二个fork出来的进程因SIGPIPE退出了,导致没有进行第三个fork,因此Cron命令没有被调用(总是由execle()调用)。

4.?一个诡异的问题

你有可能遇到这样的情况,假设在cron中有如下一条配置:

*/1?*?*?*?*?echo?hello?>>?/tmp/hello.txt

观察到它正常运行几次后,就不再运行了,或者一次也不能,但确认无其它问题,因此十分诡异。

这个问题的原因,有可能是因为有共享库Hook了cron,共享库代码触发了SIGPIPE,导致了第二个fork出的进程退出,没来得及执行vfork。

fork出来的子进程,没有对SIGPIPE进行任何处理,默认行为是悄悄退出进程。通过修改/etc/ld.so.preload,可以将共享库注入到非关联的进程中,可通过ldd观察到这种依赖,使用LD_PRELOAD也可以达到同样的效果。

5.?cron&crontab

cron是一个在后台运行的守护进程,而crontab是一个设置cron的工具。cron调度的是/etc/crontab文件。

6.?cron.allow&cron.deny

crontab使用的两个文件,cron不会用到它们。

7.?cron.daily&cron.hourly&cron.weekly&cron.monthly

cron.daily、cron.hourly、cron.weekly和cron.monthly这四个目录均位于/etc下,但cron和crontab两个并不处理。它们是由配置在/etc/crontab中的run-crons处理,run-crons是位于目录/usr/lib/cron下的一个Shell脚本文件:

#?cat?/etc/crontab

SHELL=/bin/sh

PATH=/usr/bin:/usr/sbin:/sbin:/bin:/usr/lib/news/bin

MAILTO=root

#

#?check?scripts?in?cron.hourly,?cron.daily,?cron.weekly,?and?cron.monthly

#

-*/15?*?*?*?*???root??test?-x?/usr/lib/cron/run-crons?&&?/usr/lib/cron/run-crons?>/dev/null?2>&1

8.?crontab编辑后cron异常

使用crontab编辑后,cron卡住不动(不是指进程卡住了,而是指命令没有被调用),原因可能是因为“tcb?table?full”,最简单的办法是重启cron。

建议避免写下面这样的嵌套命令语句,它有可能导致cron不能正常工作:

*/1?*?*?*?*?echo?"`date?+%H:%M:%S`?hello"?>>?/tmp/hello.txt

“echo”中嵌套了“date”,可以改成脚本调用,或者不嵌套命令,如:

*/1?*?*?*?*?echo?"hello"?>>?/tmp/hello.txt

一个现象是有一个cron子进程(如下述的14786)不退出了:

#?ps?-ef|grep?cron

root?????10325?????1??0?15:08??????????00:00:00?/usr/sbin/cron

root?????14786?10325??0?15:13??????????00:00:00?/usr/sbin/cron

gdb看到的调用栈为:

#0??0xffffe410?in?__kernel_vsyscall?()

#1??0xb7e88a63?in?__read_nocancel?()?from?/lib/libc.so.6

#2??0xb7e38e38?in?_IO_file_read_internal?()?from?/lib/libc.so.6

#3??0xb7e3a0bb?in?_IO_new_file_underflow?()?from?/lib/libc.so.6

#4??0xb7e3a7fb?in?_IO_default_uflow_internal?()?from?/lib/libc.so.6

#5??0xb7e3bb2d?in?__uflow?()?from?/lib/libc.so.6

#6??0xb7e35b7b?in?getc?()?from?/lib/libc.so.6

#7??0x80005d73?in????()?from?/usr/sbin/cron

strace看到如下:

#?strace?-f?-p?14786

Process?14786?attached

read(7,?

借助lsof可以看到:

cron????14786?root????7r??FIFO????????0,6?????????117960708?pipe

为一个管道,read()挂住的原因可能是因为管道另一端所在进程调用_exit()退出而不是调用exit()退出。

这个时候只有人工kill这个挂起的cron子进程。

本文参与?腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015-04-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体同步曝光计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.?前言
  • 2.?示例
  • 3.?工作过程
  • 4.?一个诡异的问题
  • 5.?cron&crontab
  • 6.?cron.allow&cron.deny
  • 7.?cron.daily&cron.hourly&cron.weekly&cron.monthly
  • 8.?crontab编辑后cron异常
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com