
Cron 作业是一个预定任务,可在设定的间隔自动运行脚本或命令。常见用途包括发送每日电子邮件、在夜间清除缓存、运行数据库备份或按计划触发 PHP 脚本。本分步指南向您展示如何在 DirectAdmin 虚拟主机上配置 Cron 作业以自动运行 PHP 脚本。
什么是 Cron 作业?
Cron 是 Linux 上的基于时间的作业调度程序,以定义的间隔自动运行任务。调度使用具有五个字段的 Cron 表达式:
* * * * * 命令 │ │ │ │ └── 星期几 (0-7, 0/7 = 星期日) │ │ │ └──── 月份 (1-12) │ │ └────── 月份中的日期 (1-31) │ └──────── 小时 (0-23) └────────── 分钟 (0-59)
常见 Cron 表达式示例
0 * * * *— 每小时0 0 * * *— 每天午夜0 8 * * *— 每天 08:000 0 * * 1— 每周一午夜0 0 1 * *— 每月第一天午夜*/15 * * * *— 每 15 分钟*/30 * * * *— 每 30 分钟
常见日程的 Cron 表达式参考
除了五字段语法基础外,这里是在真实虚拟主机场景中使用的表达式的实用参考表,以及其典型用例:
| 表达式 | 日程 | 典型用例 |
|---|---|---|
*/5 * * * * |
每 5 分钟 | 队列处理、WP-Cron 替代 |
0 */6 * * * |
每 6 小时 | 数据同步、缓存清除 |
0 2 * * * |
每天 02:00 | 夜间数据库备份 |
0 9 * * 1-5 |
周一–周五 09:00 | 每日商务报告电子邮件 |
0 0 1,15 * * |
每月 1 号和 15 号 | 半月发票生成 |
0 23 * * 0 |
每周日 23:00 | 每周完整网站备份 |
不确定语法?使用免费的 Cron 表达式生成器 — 用普通英文输入你想要的日程,立即获得正确的表达式。
在 DirectAdmin 中设置 Cron 作业
- 登录 DirectAdmin
- 转到高级功能 → Cron 作业
- 填入分钟 / 小时 / 日期 / 月份 / 星期几字段
- 输入要运行的命令
- 点击添加
运行 PHP 脚本的命令
格式 1 — 直接 PHP 二进制文件
/usr/local/php83/bin/php /home/username/public_html/cron/script.php
格式 2 — php-cli
/usr/bin/php /home/username/public_html/cron/script.php
格式 3 — wget(基于 HTTP 的 Cron)
wget -q -O /dev/null "https://yourdomain.com/cron/run.php" > /dev/null 2>&1
格式 4 — curl
curl -s "https://yourdomain.com/cron/run.php" > /dev/null 2>&1
提示:始终为 PHP 二进制文件和脚本文件使用完整绝对路径。Cron 在最小环境中运行,没有与普通 shell 会话相同的 PATH 变量。如果不确定 PHP 二进制路径,请在 SSH 中运行 which php。
编写 Cron 友好的 PHP 脚本
设计为通过 cron 运行的脚本应处理锁定、错误报告和与 Web 请求的环境差异。以下是三个最重要的模式:
使用锁文件防止重叠运行
如果您的 cron 每 5 分钟触发一次,但脚本需要 8 分钟完成,第二个实例将在第一个实例完成之前启动,可能导致数据损坏或重复工作。
<?php
$lockFile = '/home/username/cron.lock';
if (file_exists($lockFile)) {
// If lock is older than 10 minutes, it is stale — remove it
if (time() - filemtime($lockFile) < 600) {
exit("Script already running\n");
}
}
file_put_contents($lockFile, getmypid());
try {
// ... main work ...
} finally {
unlink($lockFile); // always remove lock, even on error
}
捕获错误并发送警报
Cron 作业是隐形的 — 它们在后台运行,除非构建错误处理,否则会无声地失败。在每个 cron 脚本顶部添加此块:
<?php
set_error_handler(function($errno, $errstr, $errfile, $errline) {
$msg = date('Y-m-d H:i:s')." ERROR [$errno] $errstr in $errfile:$errline\n";
file_put_contents('/home/username/cron-error.log', $msg, FILE_APPEND);
mail('[email protected]', 'Cron Error Alert', $msg);
});
register_shutdown_function(function() {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR])) {
$msg = date('Y-m-d H:i:s')." FATAL: ".$error['message']."\n";
file_put_contents('/home/username/cron-error.log', $msg, FILE_APPEND);
}
});
设置正确的时区
Cron 在服务器时区运行,通常是 UTC。如果您的日程逻辑取决于本地时间,请在脚本顶部明确设置时区:
<?php
date_default_timezone_set('Asia/Bangkok'); // UTC+7
// For database operations, also set MySQL timezone:
$pdo = new PDO('mysql:host=localhost;dbname=mydb', 'user', 'pass');
$pdo->exec("SET time_zone = '+07:00'");
echo date('Y-m-d H:i:s'); // Bangkok local time
实际 Cron 作业示例
在 08:00 发送每日报告电子邮件
0 8 * * * /usr/bin/php /home/username/public_html/send-email.php
每晚午夜清除缓存
0 0 * * * /usr/bin/php /home/username/public_html/clear-cache.php
用真实 Cron 作业替换 WP-Cron
添加到 wp-config.php:define('DISABLE_WP_CRON', true);
然后添加此 Cron 作业:
*/5 * * * * /usr/bin/php /home/username/public_html/wp-cron.php > /dev/null 2>&1
共享虚拟主机限制及其解决方法
共享虚拟主机的约束与 VPS 显著不同。提前了解它们将为您节省生产中的意外故障。
| 约束 | 共享虚拟主机现实 | 解决方案 |
|---|---|---|
| 最小频率 | 每 1 分钟(DirectAdmin) | 足够满足大多数任务 |
| 执行超时 | 通常限制在 60–300 秒 | 在脚本中添加 set_time_limit(0) |
| 内存限制 | 根据套餐 128–512 MB | 运行 php -d memory_limit=256M |
| 输出处理 | 未重定向的输出可能会发送电子邮件给 crontab 所有者 | 对每条命令追加 > /dev/null 2>&1 |
| PATH 环境 | Cron 以最小 PATH 启动 — 二进制文件可能无法解析 | 始终为 PHP 二进制文件和脚本使用绝对路径 |
对于运行时间超过 5 分钟、消耗大量内存或需要每分钟运行多次的脚本,请考虑升级到 VPS,在 VPS 上没有共享资源限制,您可以使用完整的系统 crontab。
验证您的 Cron 作业运行
让您的脚本每次执行时都写一个日志条目,以便之后验证:
<?php
file_put_contents('/home/username/cron.log',
date('Y-m-d H:i:s') . " - Script ran\n", FILE_APPEND);
// ... your script code
具有完整 Cron 作业支持的虚拟主机
AsiaGB 虚拟主机通过 DirectAdmin 支持 Cron 作业,PHP 7.4 / 8.2 / 8.3。从 500 泰铢/年起,提供 99% 正常运行时间。
查看虚拟主机套餐