本文目录导读:

我来详细介绍PHP定时任务的部署方法,从简单到复杂,适合不同场景的使用。
Linux Crontab(最常用)
基本用法
# 编辑定时任务 crontab -e # 查看定时任务 crontab -l # 格式:分 时 日 月 周 命令 * * * * * command
PHP脚本示例
# 每分钟执行一次 * * * * * /usr/bin/php /var/www/html/cron.php # 每天凌晨2点执行 0 2 * * * /usr/bin/php /var/www/html/cron.php # 每周一凌晨3点执行 0 3 * * 1 /usr/bin/php /var/www/html/cron.php # 每月1号凌晨4点执行 0 4 1 * * /usr/bin/php /var/www/html/cron.php
安全执行方式
# 使用日志记录 0 2 * * * /usr/bin/php /var/www/html/cron.php >> /var/log/cron.log 2>&1 # 限制执行时间 0 2 * * * timeout 300 /usr/bin/php /var/www/html/cron.php
Windows任务计划程序
创建批处理文件
@echo off C:\PHP\php.exe C:\www\cron.php
设置任务计划
# 创建定时任务(管理员权限) schtasks /create /tn "PHP任务" /tr "C:\cron.bat" /sc daily /st 02:00
使用PHP实现守护进程
无限循环执行
<?php
// daemon.php
set_time_limit(0);
ini_set('memory_limit', '512M');
while (true) {
// 执行任务
echo date('Y-m-d H:i:s') . " - Task executed\n";
// 写入日志
file_put_contents('/var/log/php_cron.log',
date('Y-m-d H:i:s') . " - Task executed\n", FILE_APPEND);
// 休眠60秒
sleep(60);
// 检查内存使用
if (memory_get_usage() > 100 * 1024 * 1024) {
gc_collect_cycles(); // 触发垃圾回收
}
}
?>
启动守护进程
# 后台运行 nohup php daemon.php > /dev/null 2>&1 & # 查看进程 ps aux | grep daemon.php # 停止进程 kill $(pgrep -f daemon.php)
使用Supervisor(推荐)
安装配置
# 安装 apt install supervisor # 配置守护进程 vim /etc/supervisor/conf.d/php-worker.conf [program:php-worker] command=php /var/www/app/worker.php directory=/var/www/app autostart=true autorestart=true startsecs=3 startretries=5 redirect_stderr=true stdout_logfile=/var/log/php-worker.out.log stderr_logfile=/var/log/php-worker.err.log
管理命令
# 重新加载配置 supervisorctl reread supervisorctl update # 启动/停止/重启 supervisorctl start php-worker supervisorctl stop php-worker supervisorctl restart php-worker # 查看状态 supervisorctl status
使用Redis队列(适合分布式)
生产者代码
<?php
// add_to_queue.php
require 'vendor/autoload.php';
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 添加任务到队列
$task = [
'type' => 'send_email',
'to' => 'user@example.com',
'data' => ['message' => 'Hello World']
];
$redis->lpush('task_queue', json_encode($task));
消费者代码
<?php
// worker.php
require 'vendor/autoload.php';
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
while (true) {
// 阻塞读取队列
$task = $redis->brpop('task_queue', 30);
if ($task) {
processTask(json_decode($task[1], true));
}
usleep(1000000); // 1秒延迟
}
function processTask($data) {
switch ($data['type']) {
case 'send_email':
sendEmail($data['to'], $data['data']);
break;
// 其他任务类型
}
}
使用消息队列组件
RabbitMQ示例
<?php
// 消费消息
require_once __DIR__ . '/vendor/autoload.php';
use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare('task_queue', false, true, false, false);
echo "等待任务... Ctrl+C 退出\n";
$callback = function ($msg) {
echo "收到任务: ", $msg->body, "\n";
// 处理任务
processTask($msg->body);
$msg->ack();
};
$channel->basic_qos(null, 1, null);
$channel->basic_consume('task_queue', '', false, false, false, false, $callback);
while (count($channel->callbacks)) {
$channel->wait();
}
最佳实践配置
基础Crontab配置模板
# 编辑定时任务 crontab -e # ===== 常用PHP定时任务 ===== # 每小时执行数据备份 0 * * * * /usr/bin/php /var/www/html/backup.php >> /var/log/backup.log 2>&1 # 每天清理临时文件 0 2 * * * /usr/bin/php /var/www/html/cleanup.php >> /var/log/cleanup.log 2>&1 # 每周生成统计报表 0 3 * * 1 /usr/bin/php /var/www/html/report.php >> /var/log/report.log 2>&1 # 每月清理旧数据 0 4 1 * * /usr/bin/php /var/www/html/archive.php >> /var/log/archive.log 2>&1 # 节假日提醒(每天检查) * * * * * /usr/bin/php /var/www/html/check_holiday.php >> /var/log/holiday.log 2>&1
PHP脚本最佳实践
<?php
// cron.php
class CronTask
{
private $logFile;
public function __construct($logFile = '/var/log/php_cron.log')
{
$this->logFile = $logFile;
}
public function execute()
{
try {
$this->log('任务开始执行');
// 1. 检查是否已在运行
if (!$this->checkRunning()) {
$this->log('任务已在运行,跳过执行');
return false;
}
// 2. 设置锁
$this->setLock();
// 3. 执行任务
$this->doTask();
// 4. 清理锁
$this->removeLock();
$this->log('任务执行完成');
return true;
} catch (Exception $e) {
$this->log('任务执行失败: ' . $e->getMessage());
$this->removeLock();
return false;
}
}
private function checkRunning()
{
// 检查PID文件
return !file_exists('/tmp/cron.lock');
}
private function setLock()
{
file_put_contents('/tmp/cron.lock', getmypid());
}
private function removeLock()
{
@unlink('/tmp/cron.lock');
}
private function doTask()
{
// 实际业务代码
// ...
}
private function log($message)
{
$log = date('Y-m-d H:i:s') . " - " . $message . "\n";
file_put_contents($this->logFile, $log, FILE_APPEND);
}
}
$cron = new CronTask();
$cron->execute();
选择建议
| 场景 | 推荐方案 | 优点 | 缺点 |
|---|---|---|---|
| 简单定时任务 | Crontab | 简单、效率高 | 不支持并行 |
| Windows环境 | 任务计划程序 | 系统自带 | 可扩展性差 |
| 复杂任务管理 | Supervisor | 可监控、自动重启 | 需要安装 |
| 分布式任务 | Redis/RabbitMQ | 可扩展、解耦 | 需要维护额外服务 |
| 长期运行任务 | 守护进程 | 实时执行 | 资源占用高 |
注意事项
- 防止重复执行:使用锁机制或检查PID
- 错误处理:记录日志、发送邮件告警
- 资源控制:设置内存和执行时间限制
- 性能监控:记录执行时间和内存占用
- 容错机制:失败自动重试或继续下次计划
选择哪种方案取决于你的具体需求,建议从简单的Crontab开始,随着业务增长再考虑更复杂的方案。