# 时间、时区与定时任务

系统时间、显示时区和定时任务采用的时区要一起核对。任务在“错误时间”执行，常见原因是服务器和读者所在时区不同。

更新日期：2026-09-16

规范地址：https://stock.iftalking.com/guides/time-cron/

## 1. 先确定系统时间和时区

时间戳出现在日志、证书、数据库和定时任务中。服务器可以统一使用 UTC，面向中国读者的后台再显示北京时间；也可以明确设置 Asia/Shanghai。关键是记录时区并保持同步。

```bash
timedatectl status
date -Is
date -u -Is
```

需要修改系统时区时可使用 `sudo timedatectl set-timezone Asia/Shanghai`。这改变时间显示规则，不是把硬件时钟手工快进八小时。时间同步由 chrony、timesyncd 或镜像提供的服务管理，先确认实际正在使用哪个，不要同时启动多个竞争的同步服务。

## 2. 先把任务做成可手动运行的脚本

计划任务失败最常见的原因是环境不同：工作目录、PATH、虚拟环境、权限或环境变量缺失。先使用将来运行任务的用户，在明确目录下执行一次脚本，确认结果、日志和退出状态。

例如将备份逻辑放在 `/home/deploy/bin/backup.sh`，脚本里使用绝对路径，并明确失败时返回非零状态。密码和 API 密钥放在限制权限的配置中，不要直接写在 crontab 或公开脚本里。

## 3. 看懂 Cron 的五个时间字段

运行 `crontab -e` 编辑当前用户的任务，`crontab -l` 查看。用户 crontab 的五个字段依次是分钟、小时、日、月、星期，后面直接接命令。

```cron
# 每天系统时区 03:20 运行
20 3 * * * /bin/bash /home/deploy/bin/backup.sh >> /home/deploy/backup.log 2>&1
```

`/etc/crontab` 和 `/etc/cron.d/` 还多一个运行用户名字段，不能把两种格式混用。日期与星期同时受限时可能采用“任一匹配”的语义；复杂日历规则应查本机 cron 实现说明。

## 4. 防止任务重叠并验证实际触发

如果一次备份可能超过计划间隔，用锁避免同一任务并发。以下锁文件放在该用户有权限的家目录。

```cron
20 3 * * * /usr/bin/flock -n /home/deploy/backup.lock /bin/bash /home/deploy/bin/backup.sh >> /home/deploy/backup.log 2>&1
```

先确认 `/usr/bin/flock` 存在。任务应记录开始时间、完成时间和错误，日志还需轮转。测试时临时设置一个较近的执行时间，看到真实产物后恢复正式计划，不要只因为 crontab 保存成功就认为自动化完成。

## 5. 需要错过后补跑时考虑 systemd timer

Cron 在服务器关机期间错过的任务通常不会自动补跑。systemd timer 可配合 `Persistent=true` 处理部分日历任务的补触发，并通过 journal 查看结果。需要精确时区、依赖或资源限制时，也更适合使用 timer + oneshot service。

```bash
systemctl list-timers --all
journalctl -u cron --since today
```

RHEL 系服务名可能是 `crond`。夏令时地区会有重复或不存在的本地时间，重要任务可统一用 UTC。后续按[后台服务管理](https://stock.iftalking.com/guides/persistent-jobs/)和[备份恢复](https://stock.iftalking.com/guides/backup-restore/)完善失败处理。


## 完成后检查

到期提醒涉及商业日期时，应同时核对官方账单采用的时间，不只依赖系统时区。

## 参考资料

- [Ubuntu Server 文档](https://documentation.ubuntu.com/server/)
