cron 是一个在后台运行调度的守护进程,而 crontab 是一个设置 cron 的工具。
1. 安装 cron 服务
安装服务
# Debian/Ubuntu 系统
sudo apt-get install cron
# CentOS/RHEL 系统中
sudo yum install cronie
开机自启
# Debian/Ubuntu 系统
sudo systemctl start cron
sudo systemctl enable cron
# CentOS/RHEL 系统中
sudo systemctl start crond
sudo systemctl enable crond
管理任务
crontab -e # 编辑当前用户的 crontab 任务列表
crontab -l # 列出当前用户的 crontab 任务列表
crontab -r # 移除当前用户的 crontab 任务列表
2. 定义配置文件
所有用户定义的 crontab 文件都被保存在 /var/spool/cron/crontabs
目录中。其文件名与用户名一致。
# /var/spool/cron/crontabs/root
* * * * * /opt/scripts/docker_health_check.sh > /dev/null 2>&1
* * * * * docker exec web /bin/sh -c "/usr/local/bin/php /var/www/html/check.php >> /dev/null 2>&1"
3. 查看执行日志
使用 journalctl -u cron.service
查看
使用 tail -f /var/log/cron.log
查看日志
debian 默认没有开启 crontab 的日志,以下步骤开启 crontab 的日志。
# 安装服务
sudo apt install rsyslog
# 启动服务
sudo systemctl start rsyslog
sudo systemctl enable rsyslog
sudo systemctl status rsyslog # 检查状态
- 检查 rsyslog 配置,确保
/etc/rsyslog.conf
中包含了生成 syslog 的配置行
# cat /etc/rsyslog.conf
# 修改 #cron.* /var/log/cron.log这一行
# 删除 #
sed -i 's/#cron\.\*/cron\.\*/g' /etc/rsyslog.conf
# 重启服务
/etc/init.d/rsyslog restart
# 查看日志
tail -f -n100 /var/log/cron.log
4. 实现秒级定时任务
crontab 的粒度最小是到分钟,但是我们还是可以通过变通的方法做到隔多少秒运行一次。
传统暴力法
# 每 10 秒执行一次
* * * * * /usr/bin/ping -c 1 8.8.8.8
* * * * * sleep 10; /usr/bin/ping -c 1 8.8.8.8
* * * * * sleep 20; /usr/bin/ping -c 1 8.8.8.8
* * * * * sleep 30; /usr/bin/ping -c 1 8.8.8.8
* * * * * sleep 40; /usr/bin/ping -c 1 8.8.8.8
* * * * * sleep 50; /usr/bin/ping -c 1 8.8.8.8
但如果 2 秒要执行一次,就要写 30 条,这样实在是太不优雅了。所以采用 shell 脚本实现如下
#!/bin/bash
# * * * * * /opt/scripts/crontab.sh
step=2 # 间隔的秒数,不能大于 60
for (( i = 0; i < 60; i=(i+step) )); do
$(date -R >> /var/log/crontab.log) # 执行脚本
sleep $step
done
exit 0
添加执行任务,查看日志可以看到,实现了每 2 秒将系统时间写入文件
* * * * * /opt/scripts/crontab.sh
5. Docker 定时任务最佳方式
Docker 环境下,在主机和在容器中使用 cron 执行定时任务,大概有以下三种方式:
- 使用主机的 cron 实现定时任务
- 创建一个新容器专门执行定时任务
- 在原有容器上安装 cron,里面运行“服务 + cron” 2 个进程
最佳的方式应该是方式1,因为它最为简单。在主机中的 crontab -e 中可以:
* * * * * docker exec web /bin/sh -c "/usr/local/bin/php /var/www/html/check.php >> /dev/null 2>&1"
注意:这里 docker 命令不需要加 -it,因为加 -it 就要开启了一个终端,而计划任务是无法进入任何终端。
6. Docker 构建和定义定时任务
FROM php:8.3.2-fpm-alpine3.18
# Install cron
RUN apk add --no-cache dcron
# Crontab
COPY deploy/cronjobs /etc/cron.d/cronjobs
RUN dos2unix /etc/cron.d/cronjobs
RUN /usr/bin/crontab /etc/cron.d/cronjobs
RUN chmod 0644 /etc/cron.d/cronjobs && mkdir /var/log/cron
其中 /etc/cron.d/cronjobs
文件内容
# /etc/cron.d/cronjobs
# Run the scripts every minute
* * * * * echo "this is crontab" $(date +%Y-%m-%d" "%H:%M:%S) >> /var/log/crontab_output.log 2>&1
以上,通过定义 /etc/cron.d/cronjobs
配置文件,从而实现构建启动后具自动执行指定脚本的镜像。
7. 在线工具
crontab 的辅助工具很多,下面是用过多款工具后收藏至今的两款。两者都可以直观的查看指定计划后,下次执行的时间点,从而检查设置是否有误。