# 定时任务
# at
:用于设置一次性的定时任务。
- 定时任务是指在某些时刻执行某些命令。
# 用法
- 命令:
$ at 11:30 2019-08-16 < run.sh # 将.sh 脚本的内容设置成定时任务 -l # 显示所有尚未执行的任务 -c <任务序号> # 显示某个任务的内容 -r <任务序号> # 删除一个任务
- 当一次性的定时任务被执行或超时之后,就会被从任务表删除。
- 例:将要执行的命令通过管道符传给 at
echo "systemctl restart docker" | at 23:00
- at 指定的时间可以是多种格式:
at 23:00 # 在今天的指定时刻(如果已超过该时刻,则定位到明天的该时刻) at now + 3 minutes # 在 3 分钟之后 at now + 3 hours # 在 3 小时之后 at 23:00 + 3 days # 在 3 天之后的 23:00
# crontab
:用于设置定时执行的任务。
- 在 Linux 主机上,默认会启动 crond 服务,没有的话就执行
systemctl start crond
启动。- 在容器中,建议执行
/usr/sbin/crond -i
,作为 daemon 进程启动。
- 在容器中,建议执行
- 每过一分钟,crond 就会检查一次配置文件中的所有定时任务。如果某个任务的定时时间与当前时刻匹配,则创建一个子进程去执行它。
# 命令
$ crontab
-e # 编辑当前用户的任务
-u <user> # 编辑指定用户的任务
-l # 显示任务内容
-r # 删除任务内容
# 配置
crond 会读取以下路径的配置文件:
/var/spool/cron/ # 该目录下存在与各个用户同名的文件,用于保存用户用 crontab -e 命令编辑的定时任务 /etc/crontab # 保存系统的定时任务,默认为空 /etc/cron.d/ # 保存系统的定时任务 /etc/cron.hourly/ # 被 /etc/cron.d/ 调用,每小时执行一次 /etc/cron.daily/ # 老版本的 daily、monthly、weekly 是被 /etc/cron.d/ 调用,现在是被 anacron 进程调用 /etc/cron.monthly/ /etc/cron.weekly/
用户可以用
crontab -e
命令编辑自己的定时任务,格式如下:*/1 * * * * echo hello &>> /var/log/cron # 每分钟执行一次,并记录输出内容 0 0 * * 6,0 echo hello &> /dev/null # 在周六、周日的 00:00 时刻执行任务,并丢弃输出 0 * * * 1-5 echo hello # 在周一至周五,每小时执行一次任务 @reboot /root/init.sh # 每次重启时执行一次
- 用 # 声明单行注释。
- 每行定义一条定时任务,格式为
<time> <command>
。 - 定时任务的 time 包含五个参数:
min # 分钟,取值为 0~59 hour # 小时,取值为 0~23 day # 日期,取值为 1~31 month # 月份,取值为 1~12 weekday # 周几,取值为 0~7 ,其中 0、7 都表示周日
- 将参数填写为 * 代表没有限制,只要符合其它条件就行。
- 如果同时填写了 day、weekday ,则只要符合其中一个参数就算匹配。
- 例:
0 * * * *
表示到 **:00 时刻执行一次,即每小时的第一分钟执行一次,相当于0 */1 * * *
。* */1 * * *
表示每小时的每分钟执行一次。*/1
表示每 1 个单位时间一次,等价于*
。
- 最小的时间精度为分钟,因此每个定时任务每分钟最多执行一次。如果需要每分钟执行多次,可采用以下方案:
- 编写一个 shell 脚本,循环运行,每隔几秒执行一次定时任务。
- 创建多个同样功能的定时任务,每分钟延迟不同时间再执行:
* * * * * /root/test.sh * * * * * ( sleep 30; /root/test.sh )
- crond 在执行任务时:
- 会切换到用户的家目录。
- 只会加载很少的环境变量,比如
PATH=/usr/bin:/bin
。
因此,填写待执行的命令时,应该尽量使用绝对路径,避免找不到文件。或者先执行source /etc/profile
。
/etc/cron.d/
目录下保存了系统的定时任务。格式如下:SHELL=/bin/bash # 声明少量的环境变量 PATH=/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root # 将命令输出的 stdout、stderr 发送到邮箱 /var/mail/root 0 * * * * root echo hello # 每行的格式为:执行时间 + 执行用户 + 待执行的命令
crond 会在
/var/log/cron
文件中记录执行的每个任务、执行时刻,如下:Jul 3 11:01:01 localhost CROND[4701]: (root) CMD (run-parts /etc/cron.hourly) # 执行 /etc/cron.hourly Jul 3 11:01:01 localhost CROND[4699]: (root) CMD (echo hello &> /dev/null) # 执行用户自定义的任务 Jul 3 11:01:01 localhost run-parts(/etc/cron.hourly)[4701]: starting 0anacron Jul 3 11:01:01 localhost run-parts(/etc/cron.hourly)[4712]: finished 0anacron Jul 3 11:01:14 localhost crontab[4749]: (root) BEGIN EDIT (root) # root 用户执行了 crontab -e 命令 Jul 3 11:01:16 localhost crontab[4749]: (root) END EDIT (root)
- 该文件不会记录定时任务输出的 stdout、stderr 。
- 该文件每过 7 天就会归档一次,最多保存最近一个月的记录。如下:
[root@CentOS ~]# ls -lh /var/log/cron* -rw------- 1 root root 148K 7 月 3 13:45 /var/log/cron -rw------- 1 root root 192K 6 月 7 03:21 /var/log/cron-20200607 -rw------- 1 root root 192K 6 月 14 03:30 /var/log/cron-20200614 -rw------- 1 root root 192K 6 月 21 03:49 /var/log/cron-20200621 -rw------- 1 root root 192K 6 月 28 03:35 /var/log/cron-20200628
# 登录时执行脚本
/etc/profile
- 主要包含 PATH 等环境变量的定义语句,还会调用脚本 /etc/profile.d/*.sh 。
/etc/bashrc
- 不会自动执行,只会被 ~/.bashrc 调用。
- 主要包含一些函数、 alias 的定义语句。
- /etc/profile、/etc/bashrc 两个脚本是 Linux 自带的。
- 新建一个用户时,默认会给它创建 ~/.bashrc、~/.bash_profile、~/.bash_logout 三个脚本。
~/.bashrc
- 当用户创建交互模式的 shell 时自动执行。
- 其默认内容如下,会调用 /etc/bashrc :
if [ -f /etc/bashrc ]; then . /etc/bashrc fi
- 例:
[root@CentOS ~]# bash # 交互模式,执行顺序如下 /root/.bashrc start /etc/bashrc start /etc/bashrc end /root/.bashrc end
[root@CentOS ~]# bash -c pwd # 非交互模式,一个也不会执行 /root
~/.bash_profile
- 当用户创建 login shell 时自动执行。
- 其默认内容如下,会调用 ~/.bashrc :
if [ -f ~/.bashrc ]; then . ~/.bashrc fi PATH=$PATH:$HOME/.local/bin:$HOME/bin export PATH
~/.bash_logout
- :当用户退出 login shell 时自动执行。
- 默认内容为空。
例:
- 通过
su
切换用户时,没有创建 login shell ,所以只会执行 ~/.bashrc 。相当于直接执行 bash 创建一个普通 shell 。 - 通过
su -
切换到当前用户时,创建了 login shell ,所以会执行 /etc/profile、~/.bash_profile 。 - 当用户退出一个普通 shell 时不会执行上述任何脚本。
- 通过