PHP定时任务怎么部署

wen PHP项目 1

本文目录导读:

PHP定时任务怎么部署

  1. Linux Crontab(最常用)
  2. Windows任务计划程序
  3. 使用PHP实现守护进程
  4. 使用Supervisor(推荐)
  5. 使用Redis队列(适合分布式)
  6. 使用消息队列组件
  7. 最佳实践配置
  8. 选择建议
  9. 注意事项

我来详细介绍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 可扩展、解耦 需要维护额外服务
长期运行任务 守护进程 实时执行 资源占用高

注意事项

  1. 防止重复执行:使用锁机制或检查PID
  2. 错误处理:记录日志、发送邮件告警
  3. 资源控制:设置内存和执行时间限制
  4. 性能监控:记录执行时间和内存占用
  5. 容错机制:失败自动重试或继续下次计划

选择哪种方案取决于你的具体需求,建议从简单的Crontab开始,随着业务增长再考虑更复杂的方案。

抱歉,评论功能暂时关闭!