PHP-PHP怎么写定时任务?
用的是虚拟主机,没有SSH权限,所以用不了crontab,请问PHP如何实时类似crontab定时任务。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
用的是虚拟主机,没有SSH权限,所以用不了crontab,请问PHP如何实时类似crontab定时任务。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(3)
有几个方法:
1.使用ignore_user_abort(true)来设置当用户请求中断后,继续执行脚本。discuz里面有一个使用ignore_user_abort实现的cron类,可以拿来参考一下。
2.如果有fsockopen权限,可以使用fsockopen("127.0.0.1", 80, $errno, $errstr, 30);来让服务器脚本请求自己的脚本:
$fp = fsockopen("127.0.0.1", 80, $errno, $errstr, 30);
if($fp){
$out = "GET /?act=XXXX HTTP/1.1rn";
$out .= "Host: ".$_SERVER['HTTP_HOST']."rn";
$out .= "Cookie:PHPSESSID=xxxxxxrn";
$out .= "Connection: Closernrn";
fputs($fp, $out);
}
上面的代码让其反复请求一个接口就行,这个要注意拿一个数据库来标示cron是否在运行中
3.如果PHP是用fastcgi方式运行的,可以用fastcgi_finish_request()函数提前终止HTTP请求,然后后面用循环+sleep实现cron的功能。
如果可以使用 cli 模式的话,那么完全可以使用 php xx.php 的形式来执行计划任务,使用set_time_limit方法来限定时间,如果需要跑多个实例,可以使用文件锁的形式来确保;
如果是web形式的话,则可以使用js来配合,像wp里面的cron其实就是这么实现的...
之前在团购平台上实现了一个这样的应用,此处我给出一些代码:
/**
* 任务计划类 taskschedule
*
* 读取指定的 任务配置文件 来执行任务计划
*/
class TaskSchedule {
/**
* 运行时目录,存放 锁定文件 和 日志文件 所在地
*
* @var string
*/
static $rtDir = null;
/**
* 锁定文件标识,确保单台机器内存中只有一个运行实例
*/
const LOCK_PID = 'taskschedule.pid';
private function __construct(){
// 此处可以扩展成 读取配置文件
$this->_tasks = require 'tasks.php';
}
/**
* 返回 TaskSchedule 单例对象
*
* @return TaskSchedule
*/
static function getInstance(){
static $inst = null;
if (!$inst)
$inst = new self();
return $inst;
}
/**
* 运行 任务实例
*/
function dealTask($id){
if (isset($this->_tasks[$id])){
$inst = isset($this->_tasks[$id]['inst']) ? $this->_tasks[$id]['inst'] : null;
if ($inst instanceof TaskBase){
// Only a instance can execute
}else {
$className = $this->_tasks[$id]['class'];
if (!class_exists($className,false)){
require_once $this->_tasks[$id]['file'];
}
if (isset($this->_tasks[$id]['config']))
$inst = new $className($this->_tasks[$id]['config']);
else
$inst = new $className();
$this->_tasks[$id]['inst'] = $inst;
$inst->run();
}
}else {
CoreApp::writeLog("task: {$id} not defined ",'error');
}
}
}
class TaskScheduleException extends Exception {}
abstract class TaskBase {
/**
* 任务标题
*
* @var string
*/
public $title;
/**
* 起始时间
*
* @var int
*/
public $st;
/**
* 结束时间
*
* @var int
*/
public $et;
/**
* 执行任务,由任务制定者实现
*/
abstract function run();
}
调用的时候
ignore_user_abort();
$op = "你定义的标识"
TaskSchedule::getInstance()->dealTask($op);
php文档中有这样的例子:
If you want to simulate a crontask you must call this script once and it will keep running forever (during server uptime) in the background while "doing something" every specified seconds (= $interval):
<?php
ignore_user_abort(1); // run script in background
set_time_limit(0); // run script forever
$interval=60*15; // do every 15 minutes...
do{
// add the script that has to be ran every 15 minutes here
// ...
sleep($interval); // wait 15 minutes
}while(true);
?>
我感觉这不是最好的解决方法。。。
其实有一些变通的方法,比如 在一个有SSH权限的主机上定时请求 你的虚拟主机,你必须先给这个主机一个请求的接口。。