让计划执行导出

LinuxBeginner
立即练习

介绍

在这个全新环境中,DAYMARK 已有安全的发布包装脚本。团队现在需要由专用报表账户执行的真实调度。终端里手动成功,并不说明计划任务能找到或读取输入。

你将配置配套的 systemd service 与 timer,观察重复的真实触发,再从目录和输入错误中恢复,同时保住上一份报表。Daymark 是业务网站;Workstation 从 /srv/daymark-sales 开始。基本终端能力即可;这里沿用前一引导实验的 shell 包装概念。提供的计算程序和包装脚本无需安装。

通过真实 timer 执行导出

在这一步,你将建立正确的业务结果,并让 systemd 运行两次导出。从 Daymark 开始,打开 Records:初始源数据包含 11 项、价值 3450 分。Reports 仍提供包含 TOTAL,1,100 的上次闭店报表。任务必须用本次实际汇总替换该文件。

切换到 Workstation。这个环境独立初始化:正确包装脚本已经备好,但尚未安装报表 timer。cat 打印文件;pwd 打印当前目录:

pwd
cat publish.sh

包装脚本在目标旁写入,只有计算成功后才重命名;它接受输入与输出参数。id 显示账户身份;ls -ld 显示目录所有者及权限位。穿越目录需要搜索权限,创建文件需要写权限。

id daymark-report
ls -ld reports

预配置的系统账户拥有 reports/。输入文件的读权限和父目录的搜索权限使它能读取 orders.csv;报表目录的所有权允许它发布。不要用 root 或所有人可写权限走捷径。

systemd 是本 instance 的服务管理器。.service 文件描述一次执行,同名 .timer 描述何时请求该执行。Type=oneshot 等待这个有限任务结束。User 选择实际执行账户。WorkingDirectory 决定相对路径 orders.csv 从哪里解析。ExecStart 对可执行程序、包装脚本与输出使用绝对路径。终端的当前目录和交互 shell 设置不会传入系统服务。不要设置 RemainAfterExit:完成的任务必须变为 inactive,下一次 timer 事件才能再次运行它。

sudo tee FILE 在写入受保护文件的同时打印内容。<<'UNIT' 是带引号的 here-document;一直粘贴到匹配的结束词。只创建指定的 D10 units:

sudo tee /etc/systemd/system/d10-sales.service <<'UNIT'
[Unit]
Description=Daymark sales export
[Service]
Type=oneshot
User=daymark-report
WorkingDirectory=/srv/daymark-sales
ExecStart=/bin/bash /srv/daymark-sales/publish.sh orders.csv /srv/daymark-sales/reports/sales.csv
UNIT

该演练 timer 在激活五秒后开始,并在前次激活二十秒后请求下一次运行。AccuracySec=1s 允许一个小的调度窗口;机器还可能产生延迟。这是短周期演练,不是每日生产计划。每日墙钟计划可用 OnCalendar=*-*-* 23:00:00 替代这两条相对时间配置,并明确选择服务器时区;本实验始终使用短周期,以便你观察真实执行。

sudo tee /etc/systemd/system/d10-sales.timer <<'UNIT'
[Unit]
Description=Daymark short training schedule
[Timer]
OnActiveSec=5s
OnUnitActiveSec=20s
AccuracySec=1s
[Install]
WantedBy=timers.target
UNIT

daemon-reload 重新读取 unit 定义。enable --now 将 timer 接到 timers.target,用于以后启动,并立即启动它。它启动的是 timer,不是手动导出:

sudo systemctl daemon-reload
sudo systemctl enable --now d10-sales.timer

sleep 50 只等待,不运行任务。不要手动启动 service,也不要用 shell 循环冒充 timer。

sleep 50

list-timers 显示实际的 LAST 和 NEXT 触发信息。--no-pager 直接打印,而不打开滚动查看器:

systemctl list-timers d10-sales.timer --no-pager

journal 是 systemd 的真实事件日志。-u 选择该 unit,-n 20 限制输出条数。它应包含至少两次完整执行,并显示 uid=... cwd=/srv/daymark-sales、报表哈希及成功完成:

sudo journalctl -u d10-sales.service -n 20 --no-pager

将数字 uid 与 id daymark-report 比较。成功的 oneshot 结束后显示 inactive (dead) 是正常现象;活动 timer 会请求未来执行。show -p 选择特定状态属性:

systemctl show d10-sales.service -p User -p WorkingDirectory -p Result -p ExecMainStatus --no-pager

预期看到 User=daymark-report、正确目录、Result=success 及 ExecMainStatus=0。没有触发时,读取 systemctl status d10-sales.timer --no-pager,只修正这些 unit 文件,重新执行 daemon-reload,并仅重启 d10-sales.timer。restart 通过停止和启动该 timer 应用 timer 编辑。再次等待并查看 journal。出现 CHDIR 时检查 WorkingDirectory;出现 Permission denied 时检查输入及报表目录所有权,不要放宽权限。

回到 Daymark,刷新 Reports 并下载新的 CSV。总数应为 TOTAL,11,3450。再次打开 Records 并返回首页,正常业务页面仍应可用。

通过下一次计划运行恢复

在这一步,你将观察真实计划任务失败、保留上一份报表,并在恢复后发布新闭店汇总。从 Workstation 开始,只处理 D10 units 和本练习输入;绝不要停止无关服务。

先制造工作目录错误。sed -i 就地编辑指定文件;s|old|new| 替换匹配文字。这是刻意注入的故障:

sudo sed -i 's|WorkingDirectory=/srv/daymark-sales|WorkingDirectory=/tmp|' /etc/systemd/system/d10-sales.service
sudo systemctl daemon-reload
sleep 30
sudo journalctl -u d10-sales.service -n 15 --no-pager

进程仍以报表账户运行,但 orders.csv 在 /tmp 下解析,因此出现 Export failed: ... No such file ...。如果工作目录本身不存在,则会在包装脚本运行前出现 CHDIR。daemon-reload 更新定义,不会运行任务。这次失败尝试由 timer 触发。

cat reports/sales.csv

报表仍必须以 TOTAL,11,3450 结尾。在 Daymark 刷新 Reports 并下载,确认相同内容仍然可用。返回 Workstation 修正目录:

sudo sed -i 's|WorkingDirectory=/tmp|WorkingDirectory=/srv/daymark-sales|' /etc/systemd/system/d10-sales.service
sudo systemctl daemon-reload

现在演练输入失败。cp 将预备的错误 fixture 复制到且仅覆盖 orders.csv;计算程序必须返回非零,包装脚本必须保留最后一份完整报表:

cp fixtures/broken.csv orders.csv
sleep 30
sudo journalctl -u d10-sales.service -n 15 --no-pager

预期出现刻意安排的非法数字失败。show 显示真实的上次退出状态,不受 journal 查看命令本身是否成功影响:

systemctl show d10-sales.service -p Result -p ExecMainStatus --no-pager

预期为 Result=exit-code 和 ExecMainStatus=1。确认上一份报表保留下来:

cat reports/sales.csv

用多出两份 Tea 的有效新闭店汇总恢复。下一次触发必须将总数更新到 13 项、3950 分:

cp fixtures/next.csv orders.csv
sleep 30
sudo journalctl -u d10-sales.service -n 15 --no-pager
cat reports/sales.csv

预期出现 Tea,5,1250 与 TOTAL,13,3950,并在 journal 中看到时间更晚的真实发布。如果仍是旧结果,读取最新错误,修正目录、输入拼写或包装脚本,再等待下一次 timer 事件。不要手写替换 CSV,也不要手动启动 service。失败的 oneshot 仍能在这个 timer 上再次运行。

在 Daymark 刷新 Records 和 Reports,再次下载,将变化后的源数据与 TOTAL,13,3950 比较。保留活动 timer 供评分。本练习不测试重启恢复、时区策略、多机并发或漏日记账。

总结

你练习了完整 CSV 发布、有意义的失败状态与恢复。计划报表只有在实际执行身份、触发记录与业务总数一致时才有用。本单机练习使用合成数据与短周期演练,不是完整的生产报表平台。