定时任务与综合实践

备份不能每天依赖管理员手动敲命令执行,必须交给系统按计划自动运行。

在 Linux 中,定时任务由 cron 守护进程负责调度。它会在后台按照预定时间自动执行指定命令,是系统管理员必须掌握的基础能力之一。

本节目标:

  • 学会编写标准的 crontab 定时规则;
  • 独立完成“九月通知发布”综合实践,作为全课通关考核。

配置 crontab 定时任务

每个用户都可以通过 crontab -e 配置自己的定时任务表。

编写定时任务时,建议把命令和文件路径都写成绝对路径。 原因是 cron 运行时的环境变量比较简洁,不会像登录终端一样完整继承用户当前的 PATH。如果只写命令名或相对路径,任务可能会因为找不到文件而执行失败。

crow@opsbox:~/work$ mkdir -p /home/crow/work/scheduled
crow@opsbox:~/work$ systemctl is-active cron
active
crow@opsbox:~/work$ EDITOR=nano crontab -e

在打开的编辑器末尾添加下面这一行,然后保存退出:

* * * * * /usr/bin/tar -czf /home/crow/work/scheduled/latest.tar.gz -C /home/crow/work source >> /home/crow/work/scheduled/backup.log 2>&1

这行任务的含义是:

  • 每分钟执行一次;
  • 使用绝对路径调用 tar;
  • 将 /home/crow/work/source 打包成压缩包;
  • 输出文件写入 /home/crow/work/scheduled/latest.tar.gz;
  • 标准输出和错误输出都追加写入 backup.log。

其中:

>> ... 2>&1

表示把普通输出和错误输出都重定向到同一个日志文件。这样即使定时任务失败,也能从日志里排查问题。

等待 1 分钟后,可以查看执行结果:

crow@opsbox:~/work$ crontab -l
crow@opsbox:~/work$ ls -l scheduled/latest.tar.gz
crow@opsbox:~/work$ tar -tzf scheduled/latest.tar.gz

如果能看到新的压缩包,并且 tar -tzf 能列出里面的文件,说明 cron 定时备份已经成功运行。

读懂 Crontab 的五个时间字段

Crontab 的基本格式如下:

┌───────────── 分钟 (0 - 59)
│ ┌─────────── 小时 (0 - 23)
│ │ ┌───────── 日期 (1 - 31)
│ │ │ ┌─────── 月份 (1 - 12)
│ │ │ │ ┌───── 星期几 (0 - 7,0 和 7 都是周日)
│ │ │ │                    │
* * * * *  要执行的命令

可以简单记为:

分 时 日 月 周 命令

常见写法示例:

30 2 * * *

表示每天凌晨 02:30 执行。

0 */2 * * *

表示每隔 2 小时的整点执行一次,例如 00:00、02:00、04:00……

15 3 * * 1

表示每周一凌晨 03:15 执行。

读懂执行时间

练习

一条用户 crontab 以 15 3 * * 1 开头。 它会在每星期一的几点十五分执行?只提交小时数字。

提交答案

题解 Hint

完成小测后,请运行:

crontab -e

把刚才用于测试的“每分钟执行”任务删掉。定时任务练习到此完成。

综合实践:发布九月通知

现在进入本课最后的综合练习。

发布九月通知

Lab

打开新的 OPSBOX 终端 OPSBOX 终端(启动 Lab 后显示)。 九月通知位于 /srv/archive/bulletin-september.tar.gz。先查看归档结构,再把它恢复到 /srv/september 下,并保留原有 /srv/bulletin 目录。 修改 bulletin.service 所使用的配置,让服务以 bulletin 身份在 127.0.0.1:8090 上提供恢复后的通知。要求请求路径为 /notice.txt,不要在 URL 中添加其他目录层级。 启动服务并设置开机自启。通过 curl 读取通知内容,再查看对应访问日志,最后提交响应中的完整 COIN 发布编号。

加载会话状态…

提交 coin

题解 Hint

操作步骤提示

  1. 查看并解压归档文件

    先查看压缩包结构:

    tar -tzf /srv/archive/bulletin-september.tar.gz
    

    确认里面包含哪些目录和文件后,再创建目标目录并解压:

    sudo mkdir -p /srv/september
    sudo tar -xzf /srv/archive/bulletin-september.tar.gz -C /srv/september
    

    解压完成后,重点确认:

    notice.txt
    

    到底在哪个实际路径下。

    这一步很关键。服务最终要提供的是:

    http://127.0.0.1:8090/notice.txt
    

    所以不能只把压缩包解压进去就结束,还需要判断 ROOT 应该指向哪一个目录。

  2. 检查服务账号权限

    本任务要求服务以用户 bulletin 身份运行。

    因此不仅要让 bulletin 能读取 notice.txt,还必须允许它沿路径逐级进入目录。

    换句话说:

    • 对上级目录,服务账号需要进入目录的权限;
    • 对目标文件,服务账号需要读取权限。

    常见排查思路包括:

    ls -l /srv
    ls -l /srv/september
    ls -l /srv/september/notice.txt
    

    如果权限不足,文件存在也可能访问失败。

  3. 修改服务配置

    编辑服务实际使用的配置文件:

    /etc/bulletin/server.env
    

    至少需要确认以下两项:

    • PORT 改为 8090
    • ROOT 指向存放 notice.txt 的实际目录

    要求最终访问路径为:

    /notice.txt
    

    如果解压后的真实文件位置是:

    /srv/september/notice.txt
    

    那么 ROOT 应指向:

    /srv/september
    

    如果 notice.txt 位于更深的一层目录,则 ROOT 要指到它的上一级目录,不能把 URL 层级额外写进请求路径里。

  4. 启动服务并设置开机自启

    如果只修改了 server.env 这类配置文件,而没有修改 systemd unit 文件本身,可以直接启动并设置开机自启:

    sudo systemctl enable --now bulletin
    

    如果服务之前已经启动过,修改配置后需要重启服务,让新配置生效:

    sudo systemctl restart bulletin
    

    如果修改的是 systemd unit 文件本身,例如服务定义文件,通常还需要先重载 systemd 配置:

    sudo systemctl daemon-reload
    

    再重启服务。

  5. 验证服务是否正常工作

    使用 curl 访问目标地址:

    curl -sS http://127.0.0.1:8090/notice.txt
    

    正常结果应该能看到九月通知内容。

    如果请求失败,可以按这个顺序排查:

    • 服务是否处于运行状态;
    • 是否监听了正确的地址和端口;
    • ROOT 配置是否指向了正确的目录;
    • bulletin 账号是否有目录进入权限和文件读取权限;
    • 访问日志是否记录了失败原因。

    常见检查命令如下:

    sudo systemctl status bulletin
    ss -ltnp | grep 8090
    sudo journalctl -u bulletin -n 50 --no-pager
    

    最后,从返回的通知内容中提取完整的:

    COIN{...}
    

    并将对应编号提交到任务卡。