首页 » LANMP » Linux » 正文

Linux计划任务详解

在 Linux 上有三个执行定时任务的命令:crontab 、at 和 anacron,其中 crontab 执行重复执务,at 执行一次性任务,而 anacron 则用于执行被延时的任务,应用场景不多,不再多做介绍。

 

(1) crontab 介绍

安装 crontab

CentOS/RHEL

Debian/Ubuntu


查看定时任务:
查看 a 用户的计划任务:
删除用户计划任务:
/etc/cron.deny 该文件中所列用户不允许使用 crontab 命令
/etc/cron.allow 该文件中所列用户允许使用 crontab 命令,优先于/etc/cron.deny

默认情况下,当用户建立定时任务规则后,该规则记录对应的配置文件会存在于/var/spool/cron 中,其 crontab配置文件对应的文件名与登录的用户名一致。如:root 用户的定时任务配置文件为/var/spool/cron/root。
定时任务结尾加 >/dev/null 2>&1,如果定时任务规范结尾不加 >/dev/null 2>&1,可能导致硬盘 inode 空间被占满,从而系统服务不正常。

cron格式
举例:
*/6 * * * * /bin/sh /mysqldata/dbback.sh

分 时 日 月 周 命令
第 1 列表示分钟 1~59 每分钟用*或者 */1 表示
第 2 列表示小时 1~23(0 表示 0 点)
第 3 列表示日期 1~31
第 4 列表示月份 1~12
第 5 列标识号星期 0~6(0 表示星期天)
第 6 列要运行的命令
*表示”每”的意思,“-”表示一个范围,“,”分隔时间段,“/n”即“每隔 n 单位时间”

编辑定时任务:crontab -e
用法举例:
30 21 * * * /etc/init.d/httpd restart
上面的例子表示每晚的 21:30 重启 apache。

45 4 1,10,22 * * /etc/init.d/httpd restart
上面的例子表示每月 1、10、22 日的 4 : 45 重启 apache。

10 1 * * 6,0 /etc/init.d/httpd restart
上面的例子表示每周六、周日的 1 : 10 重启 apache。

*/10 18-23 * * * /etc/init.d/httpd restart
上面的例子表示在每天 18 : 00 至 23 : 00 之间每隔 10 分钟重启 apache。

0 23 * * 6 /etc/init.d/httpd restart
上面的例子表示每星期六的 11 : 00 pm 重启 apache。

* */1 * * * /etc/init.d/httpd restart
每一小时重启 apache

* 22-7/1 * * * /etc/init.d/httpd restart
晚上 10 点到早上 7 点之间,每隔一小时重启 apache
[ 注意:这种写法在 vixie cron 里是不允许的( 不同的 cron 有不同的规则) 。跨 0 点的时间段需要逗号分割,否则会报 bad hour 的错误。因此,上面的时间应该写成 0 22-23,0-7 * * * ,或者全部使用逗号列举 0 22,23,0,1,2,3,4,5,6,7 * * *]

0 11 4 * mon-wed /etc/init.d/httpd restart
每月的 4 号与每周一到周三的 11 点重启 apache

0 4 1 jan * /etc/init.d/httpd restart
一月一号的 4 点重启 apache

*/30 * * * * /usr/sbin/ntpdate 210.72.145.44
每半小时同步一下时间

一些特殊用法:
每月执行定时任务: @monthly /home/ramesh/suse/bin/tape-backup
启动时执行:@reboot CMD
每天执行定时任务:@daily CMD

执行的日志在 /var/log/cron 里,如果计划任务可以执行但没效果,而手动执行且有效果,这种情况一般是环境变量的问题。在 crontab 的执行环境变量中,没有相应用户设置的环境变量,你需要手动设置一下环境变量,才能让它生效。做法就是在 sh 里再添加 source /etc/profile ,也可以这么写:
0 * * * * . /etc/profile;/bin/sh /var/www/java/audit.sh

应用举例:
我要删除 12 小时前的文件:
先新建一个 sh 脚本:
touch clear

然后 crontab -e 编辑计划任务列表:

最后重启:
service crond restart

如果不会写 sh 脚本,只会 PHP,可以写 PHP 脚本来做某些事,curl 来调用执行。
要调试计划任务,可以通过日志看执行情况。tail -f /var/log/cron
crontab 的粒度最小是到分钟,但是我们还是可以通过变通的方法做到隔多少秒运行一次。以下方法将每 20 秒执行一次:
crontab -e

这种做法去处理隔几十秒的定时任务还好,要是每 1 秒运行一次就得添加 60 条记录,如果每秒运行还是写 sh 脚本吧,其实每秒都运行很多情况下真的没必要。

另外,如 crontab 中有特殊符号,需要转义。例如下面的命令:

这个是无法执行成功的,如果去看 cron 日志可以发现实际执行的 CMD 被截断了,应该这么写:

这是因为”%”在 Cron 文件中,有”结束命令行”,”换行”,”重定向”的作用,假如不需要”%”的特殊作用,需要使用转义符转义。

下面是两条配置不同的日志,比较一下就看出来了:

 
 

(2) at 介绍

除了 cron 外,at 也可以用来做计划任务。一般在 debian 系的操作系统里,at 是默认开启的。at 比较适合做一些简单的、只运行一次的任务。

用法举例:

添加计划任务:
at 22:10 tomorrow
>date >log.txt
>Ctrl+D 确认
查看等待中的计划任务:
atq 或者 at -l
删除 Linux at 命令任务:
at -r 序列号
atrm 序列号

时间格式:
at now + 5 minutes 任务在 5 分钟后运行
at now + 1 hour 任务在 1 小时后运行
at now + 3 days 任务在 3 天后运行
at now + 2 weeks 任务在两周后运行
at midnight 任务在午夜运行
at 10:30pm 任务在晚上 10 点 30 分开始
at 1:00 12/20/04 任务在 2004 年 12 月 20 日凌晨 1 点开始

 
 

(3) 使用 systemd 中的定时器

systemd 是 centos7 中的工具包。假设你有一个脚本叫:/usr/local/bin/myscript ,你想要每隔一小时就运行一次。

第一步,创建一个 service 文件,根据你 Linux 的发行版本放到相应的系统目录(这个目录可以是/etc/systemd/system/ 或 /usr/lib/systemd/system)

myscript.service

注意,务必将 Type 变量的值设置为”simple”而不是”oneshot”。使用”oneshot”使得脚本只在第一次运行,之后系统会认为你不想再次运行它,从而关掉我们接下去创建的定时器(Timer)。

第二步,创建一个 timer 文件,把它放在第一步中 service 文件放置的目录。

myscript.timer

第三步,授权。注意,授权并运行的是 timer 文件,而不是 service 文件。

# 以 root 身份启动定时器
systemctl start myscript.timer
# 在系统引导起来后就启用该定时器
systemctl enable myscript.timer

在同一个 Timer 上运行多个脚本
现在我们假设你在相同时间想要运行多个脚本。这种情况,你需要在上面的文件中做适当的修改。

Service 文件
像我之前说过的那样创建你的service文件来运行你的脚本,但是在每个service 文件最后都要包含下面的内容:

如果在你的service文件中有一些依赖顺序,确保你使用 Description 字段中的值具体指定After=something.service 和 Before=whatever.service 中的参数。
另外的一种选择是(或许更加简单),创建一个包装脚本来使用正确的顺序来运行命令,并在你的 service 文件中使用这个脚本。

Timer 文件
你只需要一个 timer 文件,创建 mytimer.timer。

target 文件
你可以创建一个以上所有的脚本依赖的 target 文件。

mytimer.target

授权 / 启动
你需要将所有的 service 文件和 timer 文件授权。

发表评论

正在加载验证码......

请先完成验证