13
10
月
2026
服务器上有大量"定期做一次"的事情:每天备份数据库、每周清理日志、每小时检查服务是否还活着。手动做会忘,写个脚本定时跑才是正解。
这篇讲 crontab 的语法、常见写法、排错方法,以及和 systemd timer 的对比。
常驻任务需要一台稳定在线的服务器。财富云计算 的云服务器 7×24 运行;内网服务、游戏服务端可选 NAT 型(无独立公网 IP,价格比带独立 IP 机型省一半以上)。
一、crontab 是什么
cron 是 Linux 自带的定时任务守护进程,crontab 是它的配置文件。
systemctl status cron # Debian/Ubuntu 服务名是 cron
systemctl status crond # CentOS 是 crond
crontab -l # 查看当前用户的任务
crontab -e # 编辑(第一次会让你选编辑器)
crontab -r # 删除所有任务(危险)
crontab -l -u root # 查看指定用户的(需 root)
crontab -e -u www-data # 以指定用户身份编辑用户级 vs 系统级:
| 位置 | 说明 |
|---|---|
crontab -e | 用户级,存在 /var/spool/cron/crontabs/用户名 |
/etc/crontab | 系统级,多一个"用户"字段 |
/etc/cron.d/* | 系统级,按文件拆分,软件包常用 |
/etc/cron.hourly/ daily/ weekly/ monthly/ | 放脚本,按周期自动执行 |
二、语法:五个星号
* * * * * 命令
│ │ │ │ │
│ │ │ │ └── 星期 (0-7, 0和7都是周日)
│ │ │ └───── 月 (1-12)
│ │ └──────── 日 (1-31)
│ └─────────── 时 (0-23)
└────────────── 分 (0-59)特殊符号
| 符号 | 含义 | 例子 |
|---|---|---|
* | 任意值 | * * * * * 每分钟 |
, | 多个值 | 0,30 * * * * 每小时的 0 分和 30 分 |
- | 范围 | 0 9-18 * * * 9点到18点每小时 |
/ | 步长 | */10 * * * * 每 10 分钟 |
@reboot | 开机时 | @reboot /opt/start.sh |
@daily | 每天 0 点 | 等同 0 0 * * * |
@hourly | 每小时 | 等同 0 * * * * |
@weekly | 每周 | 等同 0 0 * * 0 |
@monthly | 每月 | 等同 0 0 1 * * |
@yearly | 每年 | 等同 0 0 1 1 * |
常用写法速查
*/5 * * * * 每 5 分钟
0 * * * * 每小时整点
30 3 * * * 每天 3:30
0 3 * * * 每天 3:00
0 0 * * 0 每周日 0:00
0 2 1 * * 每月 1 号 2:00
0 9 * * 1-5 工作日(周一到周五)9:00
0 9,18 * * * 每天 9:00 和 18:00
*/10 9-18 * * 1-5 工作日 9-18 点每 10 分钟
0 0 1,15 * * 每月 1 号和 15 号在线校验写法:https://crontab.guru
三、注意事项(踩坑合集)
1)命令要写绝对路径
cron 的 PATH 环境和你的交互式 shell 不一样,很多命令找不到。
# 错误
0 3 * * * mysqldump -uroot db > /backup/db.sql
# 正确
0 3 * * * /usr/bin/mysqldump -uroot db > /backup/db.sql查绝对路径:
which mysqldump tar rsync或者在 crontab 顶部声明 PATH:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
0 3 * * * mysqldump -uroot db > /backup/db.sql2)% 需要转义
在 crontab 里 % 有特殊含义(表示换行),必须写成 \%:
# 错误
0 3 * * * tar -czf /backup/$(date +%F).tar.gz /data
# 正确
0 3 * * * tar -czf /backup/$(date +\%F).tar.gz /data或者把命令写进脚本文件,crontab 只调用脚本(推荐,不容易出错)。
3)环境变量不继承
cron 不会加载 ~/.bashrc、/etc/profile。需要环境变量就在脚本里显式设置:
#!/bin/bash
export LANG=en_US.UTF-8
export PATH=/usr/local/bin:$PATH
source /opt/app/env.sh
...或者在 crontab 里写:
SHELL=/bin/bash
LANG=en_US.UTF-84)输出要去向明确
cron 默认会把输出通过邮件发给用户(通常没配邮件,就丢掉了)。建议重定向:
# 丢弃所有输出
0 3 * * * /opt/backup.sh > /dev/null 2>&1
# 记日志
0 3 * * * /opt/backup.sh >> /var/log/backup.log 2>&1
# 只记错误
0 3 * * * /opt/backup.sh > /dev/null 2>>/var/log/backup.err2>&1 表示把标准错误合并到标准输出。
5)脚本要有执行权限和 shebang
chmod +x /opt/backup.sh
head -1 /opt/backup.sh # 必须是 #!/bin/bash6)避免并发执行
任务执行时间超过间隔时会重叠。用 flock 加锁:
*/5 * * * * flock -n /tmp/backup.lock -c '/opt/backup.sh'-n 表示拿不到锁就立即退出,不等待。
7)随机延迟,避免"惊群"
多台服务器同时执行会同时打数据库/存储:
# 在脚本开头加随机延迟
sleep $((RANDOM % 300))四、实战任务示例
1)每天备份数据库
脚本 /usr/local/bin/backup_mysql.sh:
#!/bin/bash
DATE=$(date +%F)
DIR=/backup/mysql
mkdir -p $DIR
/usr/bin/mysqldump -uroot --single-transaction --all-databases \
| gzip > $DIR/all-$DATE.sql.gz
find $DIR -name "all-*.sql.gz" -mtime +30 -delete
echo "$(date) 备份完成" >> /var/log/backup.log0 3 * * * /usr/local/bin/backup_mysql.sh >> /var/log/backup.log 2>&12)每天备份网站文件
10 3 * * * /usr/bin/tar -czf /backup/www-$(date +\%F).tar.gz /var/www/html 2>>/var/log/backup.log3)异地同步
30 3 * * * /usr/bin/rsync -azP --delete -e "ssh -p 2222" /backup/ root@备份机:/backup/ >> /var/log/rsync.log 2>&14)每周清理日志
0 4 * * 0 /usr/bin/journalctl --vacuum-time=7d >> /var/log/clean.log 2>&1
0 4 * * 0 /usr/bin/find /var/log -name "*.gz" -delete5)证书自动续期
0 3 * * * /usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx"6)定时重启服务(游戏服常用)
0 5 * * * /usr/bin/systemctl restart gameserver配合提前广播通知(游戏内):
#!/bin/bash
/usr/bin/screen -S cs2 -X stuff "say 服务器将在 1 分钟后重启\n"
sleep 55
/usr/bin/screen -S cs2 -X stuff "say 服务器重启中\n"
sleep 5
/usr/bin/systemctl restart cs27)服务存活检查(简易看门狗)
#!/bin/bash
if ! systemctl is-active --quiet nginx; then
systemctl start nginx
echo "$(date) nginx 已重启" >> /var/log/watchdog.log
fi*/5 * * * * /usr/local/bin/watchdog.sh更优雅的做法是用 systemd 的 Restart=on-failure,见《systemd 服务编写与开机自启实战》。8)磁盘空间告警
#!/bin/bash
THRESHOLD=85
df -h | awk -v t=$THRESHOLD '$5+0 > t {print $6": "$5}' | while read line; do
echo "$(date) 磁盘告警: $line" >> /var/log/disk-alert.log
done*/30 * * * * /usr/local/bin/disk-check.sh9)定时同步时间
0 */6 * * * /usr/sbin/ntpdate -u ntp.aliyun.com > /dev/null 2>&1
# 或用 systemd-timesyncd / chrony10)网站健康检查
#!/bin/bash
CODE=$(curl -s -o /dev/null -w "%{http_code}" https://example.com)
if [ "$CODE" != "200" ]; then
echo "$(date) 网站异常: $CODE" >> /var/log/site-check.log
# 可以加钉钉/企业微信告警
fi*/5 * * * * /usr/local/bin/site-check.sh五、怎么确认任务真的跑了
这是最容易被忽略的:写了任务不代表它在正常执行。
1)看 cron 日志
# Debian/Ubuntu
grep CRON /var/log/syslog
tail -f /var/log/syslog | grep CRON
# CentOS
tail -f /var/log/cron看到类似:
Oct 13 03:00:01 host CRON[12345]: (root) CMD (/usr/local/bin/backup.sh)说明任务被触发了。
2)让任务自己写日志
最可靠的方式:
0 3 * * * /opt/backup.sh >> /var/log/backup.log 2>&1然后检查日志有没有新内容、有没有报错。
3)主动验证
# 手动跑一遍脚本
bash /opt/backup.sh
echo $? # 返回 0 才是成功
# 用同样的环境模拟 cron
env -i /bin/bash -c '/opt/backup.sh'4)加成功/失败告警
#!/bin/bash
if /usr/local/bin/backup.sh; then
echo "$(date) OK" >> /var/log/cron-status.log
else
echo "$(date) FAILED" >> /var/log/cron-status.log
curl -s -X POST 'https://oapi.dingtalk.com/robot/send?access_token=xxx' \
-H 'Content-Type: application/json' \
-d '{"msgtype":"text","text":{"content":"备份任务失败!"}}'
fi六、常见故障排查
| 现象 | 原因 | 解决 |
|---|---|---|
| 任务没执行 | cron 服务没启动 | systemctl start cron |
| 命令找不到 | 没用绝对路径 | which 查路径,或声明 PATH |
date +%F 不生效 | % 未转义 | 改成 \%F |
| 脚本手动能跑,cron 不行 | 环境变量差异 | 脚本里显式设环境变量 |
| 输出丢失 | 没重定向 | 加 >> log 2>&1 |
| 任务重复执行 | 执行时间超过间隔 | 用 flock 加锁 |
| 时区不对 | 系统时区设置 | timedatectl set-timezone Asia/Shanghai,改完重启 cron |
| 权限问题 | 以错误用户执行 | 用 crontab -u 用户 -e |
/etc/crontab 里的任务不跑 | 缺用户字段 | 系统级格式是 分 时 日 月 周 用户 命令 |
改时区后必须重启 cron:
timedatectl set-timezone Asia/Shanghai
systemctl restart cron七、cron vs systemd timer
| 对比 | cron | systemd timer |
|---|---|---|
| 语法 | 五个星号,需要记 | 配置文件,语义清晰 |
| 日志 | 要自己重定向 | 自动进 journalctl |
| 错过执行 | 关机期间的任务直接丢失 | Persistent=true 可开机补跑 |
| 依赖管理 | 无 | 可声明依赖(如网络就绪) |
| 随机延迟 | 自己写 sleep | RandomizedDelaySec |
| 资源限制 | 无 | 可设 MemoryMax、CPUQuota |
| 调试 | 麻烦 | systemctl list-timers 看下次执行时间 |
建议:
- 简单任务(备份、清理)→ crontab,够用
- 重要任务、需要日志和可靠性 → systemd timer
systemd timer 写法详见《systemd 服务编写与开机自启实战》。
八、安全注意
# 限制谁能用 cron
cat /etc/cron.allow # 白名单(存在时只有名单内用户可用)
cat /etc/cron.deny # 黑名单
# 检查有没有可疑任务(入侵排查必做)
crontab -l
crontab -l -u root
ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/
cat /etc/crontab⚠️ 木马最常用的持久化手段就是写一条 cron 任务。排查入侵时务必检查,详见《服务器被入侵应急排查与处置》。
九、速查
crontab -l 查看
crontab -e 编辑
crontab -r 删除全部
crontab -l -u root 查看 root 的
grep CRON /var/log/syslog 看执行记录
systemctl status cron 服务状态
systemctl restart cron 改时区后要重启# 模板
分 时 日 月 周 /绝对路径/命令 >> /var/log/xxx.log 2>&1
0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1定时任务需要服务器长期在线。财富云计算 的云服务器 7×24 稳定运行,配合 systemd 可实现开机自启与崩溃自动恢复;内网服务、游戏服务端可选 NAT 型(无独立公网 IP,价格比带独立 IP 机型省一半以上)。
相关阅读:
- 《systemd 服务编写与开机自启实战》
- 《服务器备份与快照策略》
- 《Linux 日志管理与 logrotate 配置》
延伸阅读
- 网站环境怎么选:LNMP 手动 / 宝塔面板 / Docker / 云开发
- 问卷表单系统搭建:SurveyKing / Formbricks,数据自己收
- 图床搭建:Lsky Pro / Lychee,自托管图片托管方案
- 邮件列表搭建:listmonk 自托管 Newsletter,把读者握在自己手里
- 文档站点搭建:MkDocs / VuePress / Docsify,产品文档与技术手册方案
- RSS 阅读器搭建:FreshRSS 自托管,把信息流拿回自己手里
- 短链接服务搭建:Shlink 自托管,链接数据自己掌握
- 网站状态监控页搭建:Uptime Kuma,服务器挂了第一时间知道

[...]sudo systemctl start palworld存档目录:Pal/Saved/SaveGames/,世界进度、玩家、公会全在里面。游戏大版本更新经常改存档格式,升级前必须备份,备份策略见服务器备份与快照策略和游戏服务器数据备份与恢复。九、常见问题现象原因与解法服务端起不来缺 32 位库,回到第一节装依赖自己人能进、外人进不来8211/UDP 没放行(安全组+ufw 双重检查)玩几小时内存[...]
2026-10-15 回复
[...]docker run -d --name alist -p 5244:5244 -v /data/alist:/opt/alist/data xhofe/alist:latest注意:自建网盘服务别放重要数据当唯一副本,它的定位是「方便访问」,不是「可靠存储」。五、带宽分配:共存的隐形瓶颈多服务共存,带宽是共享的。规划原则:场景带宽建议说明游戏服为主,网站没人看10-15M网站静态化,几乎不吃带宽[...]
2026-10-18 回复
[...]find /backup -name "save_*" -mtime +14 -delete方案细节见rsync 同步与定时备份实战,对象存储选型见对象存储分离静态资源,定时任务见crontab 计划任务完全指南。备份必须验证(大多数人漏掉的一步)# 每月抽一个备份,实际解压测试[...]
2026-10-18 回复
[...]# 0 4 * /usr/local/bin/backup-save.sh完整方案见crontab 计划任务完全指南和rsync 同步与定时备份实战。六、脚本使用的三个注意SSH 端口改完后,当前连接不会断(sshd 重启不影响已建立连接),但下次连接要用新端口——先测试新端口能连,再关旧会话。防火墙先放行 SSH 端口再 enable,脚本里的顺序就是对的,别手动打乱。游戏端口别在脚本里[...]
2026-10-18 回复
[...]sqlite3 /path/to/data.db "VACUUM INTO '/backup/data_$(date +%F).db'"挂 crontab 每天跑,见crontab 计划任务完全指南。2. WAL 模式提升并发(重要)# 开启 WAL,读写不互斥,个人站也够用了[...]
2026-10-18 回复
[...]netsh advfirewall firewall add rule name="GameRange" dir=in action=allow protocol=UDP localport=26901-26903完整的 Windows 环境准备(远程桌面连接、运行库安装、SteamCMD 用法、开机自启、8 个常见坑)见:《Windows 云服务器开服通用前置教程》→ htt[...]
2026-10-18 回复
[...]find /backup -name 'vw-*.tar.gz' -mtime +30 -deletersync 增量备份方案见rsync 同步与定时备份实战,定时任务见crontab 计划任务完全指南。导出密码库要加密:Bitwarden 支持加密导出(.json 加密格式),明文导出只用于迁移,导完立刻删。六、安全加固清单密码库是"一把钥匙开所有锁"的地方,安全按最高标准:[ ] SIGNUP[...]
2026-10-18 回复
[...]# 方式二:FreshRSS 内置的简单定时(设置里开)频率建议:15–30 分钟。抓太频浪费资源,抓太慢失去"阅读器"的意义。cron 配置细节见crontab 计划任务完全指南。资源账:几百个源、15 分钟一轮,1核1G 完全无压力;但源里有大量全文抓取(curl 全文)时,CPU 会上去一截——2G 更稳。五、手机端接入:Fever APIFreshRSS 原生支持 Fever API,这是[...]
2026-10-18 回复