Ubuntu 运维系列 | 第 14 天:定时任务与自动化——cron、systemd timer 与脚本化运维

在运维工作中,有一句流传很广的话:”能交给机器做的,就不要让人重复做。”定时任务与自动化,正是这句话最直接的落地方式。无论是每天凌晨自动备份数据库、定期清理日志,还是按需重启服务、批量巡检服务器,都离不开 Ubuntu 上的任务调度机制。Ubuntu 作为一款成熟的 Linux 发行版,提供了两种主流的定时调度方案:传统而经典的 cron,以及功能更强大、与现代 systemd 生态深度整合的 systemd timer。今天我们就围绕”定时任务与自动化”这条主线,系统讲解两者的原理、配置方式与实战技巧,并穿插脚本化运维的常用套路,帮你把重复劳动真正解放出来。

Ubuntu 运维 第14天

核心概念:cron 与 systemd timer 的定位

cron 是 Unix/Linux 世界历史悠久的守护进程,通过读取 crontab 文件,在特定时间点触发命令或脚本。它的配置简单直观,语法经过几十年的验证,几乎每一台 Linux 服务器上都有它的身影。cron 的最小调度粒度是”分钟”,对绝大多数定时需求已经足够。它适合轻量、独立、与登录会话无关的后台任务。

systemd timer 则是 systemd 引入的替代方案。它以 .timer 单元文件的形式存在,配合对应的 .service 单元共同工作。相比 cron,systemd timer 的优势在于:支持更丰富的时间表达式(如单调时间、日历事件)、可以记录每次触发的日志、具备依赖关系与资源控制能力、支持 OnBootSec 这类”开机后多久执行”的语义,还能方便地用 systemctl 统一管理启停与查看状态。

简单来说:如果你是快速写一条临时定时任务,cron 更顺手;如果你要构建一套可维护、可观测、可随服务一起交付的自动化体系,systemd timer 更值得优先考虑。

实战步骤

1. 使用 crontab 配置定时任务

先查看当前用户的定时任务列表:

crontab -l

编辑当前用户的 crontab(首次运行会提示选择编辑器):

crontab -e

crontab 每一行的格式为:分 时 日 月 周 命令。下面是一个典型示例,表示每天凌晨 2 点执行数据库备份脚本:

# 每天 02:00 执行备份脚本,并将输出追加到日志
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

# 每 30 分钟执行一次磁盘空间检查
*/30 * * * * /usr/local/bin/check_disk.sh

# 每周一凌晨 3 点清理临时文件
0 3 * * 1 find /tmp -type f -mtime +7 -delete

保存后 cron 会自动加载。可以通过以下命令确认服务运行状态:

sudo systemctl status cron

2. 编写可复用的自动化脚本

脚本化运维的核心是”参数化 + 日志 + 幂等”。下面是一个带日志输出的数据库备份脚本示例:

#!/usr/bin/env bash
set -euo pipefail

# 数据库备份脚本 backup.sh
BACKUP_DIR="/data/backup/mysql"
LOG_FILE="/var/log/backup.log"
DB_NAME="appdb"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

mkdir -p "$BACKUP_DIR"
log "开始备份数据库 ${DB_NAME}"

mysqldump --single-transaction "$DB_NAME" 
    | gzip > "${BACKUP_DIR}/${DB_NAME}-$(date '+%Y%m%d%H%M').sql.gz"

# 只保留最近 7 天的备份
find "$BACKUP_DIR" -name '*.sql.gz' -mtime +7 -delete
log "备份完成,保留最近 7 天文件"

赋予执行权限后再交给 cron 调用:

chmod +x /usr/local/bin/backup.sh

3. 使用 systemd timer 实现定时任务

systemd timer 需要两个文件:一个定义”做什么”的 .service,一个定义”何时做”的 .timer。先创建服务单元:

sudo tee /etc/systemd/system/backup.service > /dev/null <<'EOF'
[Unit]
Description=Daily MySQL backup service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=root

[Install]
WantedBy=multi-user.target
EOF

再创建对应的 timer 单元,实现每天凌晨 2 点触发,并允许开机后 5 分钟内补跑一次:

sudo tee /etc/systemd/system/backup.timer > /dev/null <<'EOF'
[Unit]
Description=Run backup daily at 02:00

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=60

[Install]
WantedBy=timers.target
EOF

启用并启动 timer,然后查看状态与下次触发时间:

sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer

# 查看 timer 列表与下次执行时间
systemctl list-timers --all | grep backup

每次触发都会产生日志,方便排查问题:

journalctl -u backup.service -n 20 --no-pager

常见问题

Q1:cron 任务没有执行,怎么办?
先确认 cron 服务是否在运行:systemctl status cron。再检查 /var/log/syslog 中是否出现 CRON 相关记录。最常见的原因是脚本路径或环境变量问题——cron 执行的环境和登录 shell 不同,脚本里最好使用绝对路径,必要时在脚本开头显式设置 PATH

Q2:crontab 和 /etc/crontab 有什么区别?
crontab -e 编辑的是当前用户的个人 crontab;而 /etc/crontab 是系统级 crontab,格式上多了一个”执行用户”字段,由系统管理员维护。系统级任务还可以放到 /etc/cron.d/ 目录,规则格式与 /etc/crontab 一致。

Q3:systemd timer 和 cron 可以同时使用吗?
可以,但要避免同一个任务被重复调度。建议一个任务只选择一种调度方式,避免出现重复执行导致的数据覆盖或并发冲突。

Q4:如何测试定时任务而不等到触发时间?
cron 任务可以直接在 shell 里手动运行命令验证;systemd timer 则可以用 sudo systemctl start backup.service 手动触发一次服务,观察日志确认行为是否符合预期。

总结

定时任务与自动化是运维工程师的”效率放大器”。cron 以其简单直接、无处不在的特点,仍然是处理轻量定时任务的首选;而 systemd timer 凭借更强大的时间语义、日志能力与 systemctl 的统一管理接口,正在成为现代 Ubuntu 运维体系中更规范、更可观测的选择。掌握了这两套机制,再配合参数化、幂等、带日志的脚本化思路,你就能把备份、巡检、清理、发布等重复性工作逐步交给系统自动完成,把精力聚焦在更有价值的架构与排障上。

下期预告:第 15 天,我们将进入《Shell 脚本编程——从基础语法到运维自动化脚本》,带你系统掌握变量、分支、循环、函数等核心语法,并动手写出真正可用的运维自动化脚本,敬请期待。

微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容