介绍
Linux 管理员可以通过多种方式调度任务。at 命令用于调度一次性任务;cron 用于根据简单的时间字段调度周期性任务;而 systemd 定时器则利用 systemd 的依赖关系和日志模型来调度 systemd 服务。
在本实验中,你将创建一个命令脚本,并分别通过这三种方式进行调度。你将检查调度程序服务、排队一个一次性的 at 任务、配置一个 cron 插入式(drop-in)文件、创建一个 systemd 服务与定时器对,并手动测试定时器背后的服务。
检查调度程序并创建任务脚本
在此步骤中,你将确认调度程序服务正在运行,并创建一个供所有调度任务调用的脚本。
进入项目目录。
cd /home/labex/project
检查一次性任务守护进程和 cron 守护进程。当服务正在运行时,systemctl is-active 会输出 active。
systemctl is-active atd crond
列出现有的 systemd 定时器。输出内容显示了下一次运行时间、定时器单元以及它所激活的服务单元。
systemctl list-timers --all --no-pager | sed -n '1,10p'
创建一个脚本,将带有时间戳的行追加到日志文件中。第一个参数 $1 将作为标识哪个调度程序运行了该脚本的标签。
cat > /home/labex/project/scheduled-note.sh <<'EOF'
#!/bin/bash
echo "$(date '+%F %T') $1" >> /home/labex/project/schedule-events.log
EOF
使脚本具有可执行权限。
chmod 755 /home/labex/project/scheduled-note.sh
手动运行一次该脚本。
/home/labex/project/scheduled-note.sh manual-run
tail -n 1 /home/labex/project/schedule-events.log
日志行的末尾应显示 manual-run。
排队一次性 at 任务
在此步骤中,你将使用 at 调度一个一次性任务。这对于需要在未来某个时间点执行一次的工作(例如临时维护任务)非常有用。
将脚本排队,使其在两小时后运行。要运行的命令通过管道传递给 at。
echo "/home/labex/project/scheduled-note.sh at-job" | at now + 2 hours
列出已排队的任务。
atq
保存第一个 atq 行中的任务 ID。任务 ID 是输出中的第一个字段。
job_id="$(atq | awk 'NR==1 {print $1}')"
echo "$job_id" > /home/labex/project/at-job.id
cat /home/labex/project/at-job.id
检查已排队任务的内容。at -c 会打印生成的任务脚本;最后几行应包含你所排队的命令。
at -c "$job_id" | tail -n 12
配置 cron 插入式文件
在此步骤中,你将通过 /etc/cron.d 中的文件配置一个周期性的 cron 任务。该目录下的文件包含一个用户字段,因此系统知道应该以哪个账户运行该命令。
创建一个 cron 文件,以 labex 用户身份每分钟运行一次该脚本。PATH 行确保 cron 拥有可预测的命令搜索路径。
sudo tee /etc/cron.d/rhcsa-schedule-demo >/dev/null <<'EOF'
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
* * * * * labex /home/labex/project/scheduled-note.sh cron-job
EOF
将文件模式设置为 644。Cron 文件必须可读,且不应允许普通用户写入。
sudo chmod 644 /etc/cron.d/rhcsa-schedule-demo
重新加载 crond 以使其立即识别该文件。
sudo systemctl reload crond
检查你创建的文件。
sudo cat /etc/cron.d/rhcsa-schedule-demo
调度字段 * * * * * 表示每分钟执行一次。
创建 systemd 服务和定时器
在此步骤中,你将创建一个 systemd 服务以及一个激活该服务的定时器。定时器不会直接运行命令,而是启动一个服务单元。
系统服务应从系统可执行路径执行命令,而不是从用户的工作目录。将脚本的副本安装到 /usr/local/bin 下。
sudo install -m 755 /home/labex/project/scheduled-note.sh /usr/local/bin/rhcsa-scheduled-note
sudo restorecon /usr/local/bin/rhcsa-scheduled-note 2>/dev/null || true
ls -l /usr/local/bin/rhcsa-scheduled-note
创建服务单元。对于运行后即退出的命令,Type=oneshot 是合适的选择。
sudo tee /etc/systemd/system/rhcsa-schedule-demo.service >/dev/null <<'EOF'
[Unit]
Description=Write RHCSA schedule demo entry
[Service]
Type=oneshot
User=labex
ExecStart=/usr/local/bin/rhcsa-scheduled-note timer-job
EOF
创建定时器单元。OnBootSec=2min 设置开机后首次运行的时间,OnUnitActiveSec=5min 设置后续运行相对于上一次激活的时间间隔。
sudo tee /etc/systemd/system/rhcsa-schedule-demo.timer >/dev/null <<'EOF'
[Unit]
Description=Run RHCSA schedule demo periodically
[Timer]
OnBootSec=2min
OnUnitActiveSec=5min
Unit=rhcsa-schedule-demo.service
[Install]
WantedBy=timers.target
EOF
重新加载 systemd,启用定时器以实现开机自启,并立即启动它。将 enable 和 start 分开执行,可以清楚地分辨出哪个命令使定时器持久化,哪个命令使其立即生效。
sudo systemctl daemon-reload
sudo systemctl enable rhcsa-schedule-demo.timer
sudo systemctl start rhcsa-schedule-demo.timer
检查定时器。
systemctl list-timers rhcsa-schedule-demo.timer --all --no-pager
定时器应出现在列表中,并且它应该会激活 rhcsa-schedule-demo.service。
测试定时器服务并移除 at 任务
在此步骤中,你将手动启动定时器所使用的服务。这可以立即验证命令,而无需等待下一次定时器触发。你还将移除已排队的 at 任务,因为它仅用于练习。
手动启动服务。
sudo systemctl start rhcsa-schedule-demo.service
检查日志。
tail -n 5 /home/labex/project/schedule-events.log
其中一行应以 timer-job 结尾。
使用之前保存的任务 ID 移除已排队的 at 任务。
job_id="$(cat /home/labex/project/at-job.id)"
atrm "$job_id"
确认任务已不再排队。
atq
总结
你练习了三种调度方法。你检查了 atd、crond 和 systemd 定时器,创建了一个可重用的调度命令脚本,排队并检查了一个一次性的 at 任务,配置了一个周期性的 cron 插入式文件,在 /usr/local/bin 下安装了一个服务安全命令,创建了一个 systemd 服务与定时器对,手动测试了定时器服务,并移除了临时的 at 任务。



