本文目录导读:

我来介绍几种在PHP中实现定时任务/计划任务的方法:
使用系统Cron(最常用)
Linux/Mac系统
# 编辑crontab crontab -e # 每分钟执行一次 * * * * * /usr/bin/php /path/to/your/script.php # 每天凌晨2点执行 0 2 * * * /usr/bin/php /path/to/your/script.php # 每小时执行 0 * * * * /usr/bin/php /path/to/your/script.php
Windows系统
使用任务计划程序,或创建批处理文件:
@echo off php C:\path\to\your\script.php
PHP纯代码实现(无需系统Cron)
<?php
// simple_cron.php
class SimpleCron {
private $tasks = [];
private $running = true;
public function addTask($name, $interval, $callback) {
$this->tasks[$name] = [
'interval' => $interval,
'last_run' => 0,
'callback' => $callback
];
}
public function run() {
echo "Cron Job Started at: " . date('Y-m-d H:i:s') . "\n";
while ($this->running) {
$current_time = time();
foreach ($this->tasks as $name => &$task) {
if ($current_time - $task['last_run'] >= $task['interval']) {
echo "Running task: $name\n";
try {
call_user_func($task['callback']);
$task['last_run'] = $current_time;
} catch (Exception $e) {
echo "Error in task $name: " . $e->getMessage() . "\n";
}
}
}
sleep(1); // 每秒检查一次
}
}
public function stop() {
$this->running = false;
}
}
// 使用示例
$cron = new SimpleCron();
// 添加任务:每5秒执行一次
$cron->addTask('task1', 5, function() {
echo "Task 1 executed at: " . date('H:i:s') . "\n";
});
// 添加任务:每10秒执行一次
$cron->addTask('task2', 10, function() {
echo "Task 2 executed at: " . date('H:i:s') . "\n";
});
// 启动计划任务
$cron->run();
使用时间间隔的精确实现
<?php
// precise_cron.php
class PreciseCron {
private $tasks = [];
public function schedule($expression, $callback) {
$this->tasks[] = [
'expression' => $expression,
'callback' => $callback
];
}
private function shouldRun($expression) {
// 解析cron表达式(简化版本)
$parts = explode(' ', $expression);
$now = getdate();
if (count($parts) < 5) {
return false;
}
// 匹配分钟 (0-59)
if ($parts[0] != '*' && $now['minutes'] != (int)$parts[0]) {
return false;
}
// 匹配小时 (0-23)
if ($parts[1] != '*' && $now['hours'] != (int)$parts[1]) {
return false;
}
// 匹配日 (1-31)
if ($parts[2] != '*' && $now['mday'] != (int)$parts[2]) {
return false;
}
// 匹配月 (1-12)
if ($parts[3] != '*' && $now['mon'] != (int)$parts[3]) {
return false;
}
// 匹配星期 (0-7, 0和7都代表周日)
if ($parts[4] != '*') {
$weekday = $now['wday'] == 0 ? 7 : $now['wday'];
if ($weekday != (int)$parts[4]) {
return false;
}
}
return true;
}
public function run() {
while (true) {
foreach ($this->tasks as $task) {
if ($this->shouldRun($task['expression'])) {
echo "[" . date('Y-m-d H:i:s') . "] " .
"Executing: " . $task['expression'] . "\n";
call_user_func($task['callback']);
}
}
sleep(60); // 每分钟检查一次
}
}
}
// 使用示例
$cron = new PreciseCron();
// 每天凌晨2点执行
$cron->schedule('0 2 * * *', function() {
echo "每天的数据清理任务\n";
});
// 每小时执行
$cron->schedule('0 * * * *', function() {
echo "每小时的数据同步\n";
});
// 每分钟执行
$cron->schedule('* * * * *', function() {
echo "每分钟的检查\n";
});
$cron->run();
使用文件锁防止重复执行
<?php
// cron_with_lock.php
class CronWithLock {
private $lockFile;
public function __construct($lockFile = '/tmp/cron.lock') {
$this->lockFile = $lockFile;
}
public function execute($taskName, $callback, $maxExecutionTime = 3600) {
$lockHandle = fopen($this->lockFile . '.' . $taskName, 'w');
if (!$lockHandle) {
echo "无法创建锁文件\n";
return false;
}
// 尝试获取独占锁
if (!flock($lockHandle, LOCK_EX | LOCK_NB)) {
echo "任务 $taskName 已经在运行中\n";
return false;
}
echo "开始执行任务: $taskName\n";
try {
// 设置执行超时时间
set_time_limit($maxExecutionTime);
// 执行任务
call_user_func($callback);
echo "任务 $taskName 执行完成\n";
} catch (Exception $e) {
echo "任务 $taskName 执行失败: " . $e->getMessage() . "\n";
} finally {
// 释放锁
flock($lockHandle, LOCK_UN);
fclose($lockHandle);
}
return true;
}
}
// 使用示例
$cron = new CronWithLock();
// 在cron中调用
$cron->execute('daily_backup', function() {
// 备份数据库
exec('mysqldump -u root database > backup.sql');
echo "数据库备份完成\n";
}, 600); // 10分钟超时
使用第三方库(推荐)
使用 cron-expression 库
composer require dragonmantank/cron-expression
<?php
require 'vendor/autoload.php';
use Cron\CronExpression;
class CronScheduler {
private $jobs = [];
public function addJob($cronExpression, $callback) {
$this->jobs[] = [
'expression' => new CronExpression($cronExpression),
'callback' => $callback
];
}
public function run() {
while (true) {
foreach ($this->jobs as $job) {
if ($job['expression']->isDue()) {
echo "执行任务: " . $job['expression']->getExpression() . "\n";
call_user_func($job['callback']);
}
}
sleep(60);
}
}
}
$scheduler = new CronScheduler();
$scheduler->addJob('*/5 * * * *', function() {
echo "每5分钟执行\n";
});
$scheduler->run();
完整的任务管理器示例
<?php
// task_manager.php
class TaskManager {
private $db;
private $tasks = [];
public function __construct($dbPath = 'tasks.db') {
$this->db = new SQLite3($dbPath);
$this->initDatabase();
$this->loadTasks();
}
private function initDatabase() {
$this->db->exec("
CREATE TABLE IF NOT EXISTS tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
interval_seconds INTEGER NOT NULL,
command TEXT NOT NULL,
last_run INTEGER DEFAULT 0,
status TEXT DEFAULT 'active',
created_at INTEGER DEFAULT (strftime('%s', 'now'))
)
");
}
public function addTask($name, $interval, $command) {
$stmt = $this->db->prepare("
INSERT INTO tasks (name, interval_seconds, command)
VALUES (:name, :interval, :command)
");
$stmt->bindValue(':name', $name, SQLITE3_TEXT);
$stmt->bindValue(':interval', $interval, SQLITE3_INTEGER);
$stmt->bindValue(':command', $command, SQLITE3_TEXT);
return $stmt->execute();
}
public function removeTask($id) {
$stmt = $this->db->prepare("DELETE FROM tasks WHERE id = :id");
$stmt->bindValue(':id', $id, SQLITE3_INTEGER);
return $stmt->execute();
}
private function loadTasks() {
$result = $this->db->query("SELECT * FROM tasks WHERE status = 'active'");
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
$this->tasks[] = $row;
}
}
public function run() {
echo "Task Manager Started at: " . date('Y-m-d H:i:s') . "\n";
while (true) {
$currentTime = time();
foreach ($this->tasks as &$task) {
if ($currentTime - $task['last_run'] >= $task['interval_seconds']) {
echo "[" . date('Y-m-d H:i:s') . "] " .
"Running task: {$task['name']}\n";
// 执行命令
$output = [];
$returnVar = 0;
exec($task['command'], $output, $returnVar);
// 更新最后执行时间
$stmt = $this->db->prepare("
UPDATE tasks SET last_run = :last_run
WHERE id = :id
");
$stmt->bindValue(':last_run', $currentTime, SQLITE3_INTEGER);
$stmt->bindValue(':id', $task['id'], SQLITE3_INTEGER);
$stmt->execute();
$task['last_run'] = $currentTime;
echo "Task {$task['name']} completed. Output: " .
implode("\n", $output) . "\n";
}
}
sleep(1);
}
}
}
// 使用示例
$manager = new TaskManager();
// 添加任务
$manager->addTask('Check Server', 300, 'curl -s http://localhost/health');
$manager->addTask('Clear Cache', 3600, 'rm -rf /tmp/cache/*');
// 启动管理器
$manager->run();
使用建议
- 生产环境推荐使用系统Cron
- 如果无法使用系统Cron,考虑使用PHP实现
- 注意设置合适的执行超时时间
- 添加日志记录便于排查问题
- 使用数据库或文件存储任务状态
需要根据实际应用场景选择最适合的方案,对于大多数Web应用,使用系统Cron + PHP脚本是最简单可靠的方案。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播