// ... // 正常的php执行程序 // .. // 远程请求(不获取内容)函数,下面可以反复使用 function _sock($url) { $host = parse_url($url,PHP_URL_HOST); $port = parse_url($url,PHP_URL_PORT); $port = $port ? $port : 80; $scheme = parse_url($url,PHP_URL_SCHEME); $path = parse_url($url,PHP_URL_PATH); $query = parse_url($url,PHP_URL_QUERY); if($query) $path .= '?'.$query; if($scheme == 'https') { $host = 'ssl://'.$host; } $fp = fsockopen($host,$port,$error_code,$error_msg,1); if(!$fp) { return array('error_code' => $error_code,'error_msg' => $error_msg); } else { stream_set_blocking($fp,true);//开启了手册上说的非阻塞模式 stream_set_timeout($fp,1);//设置超时 $header = "GET $path HTTP/1.1rn"; $header.="Host: $hostrn"; $header.="Connection: closernrn";//长连接关闭 fwrite($fp, $header); usleep(1000); // 这一句也是关键,如果没有这延时,可能在nginx服务器上就无法执行成功 fclose($fp); return array('error_code' => 0); } } _sock('www.yourdomain.com/script.php'); // ... // 继续执行其他动作 // ..
把这段代码加入到某个定时任务提交结果程序中,在设置好时间后,提交,然后执行上面这个代码,就可以激活该定时任务linux空间,而且对于提交的这个用户而言,没有任何页面上的堵塞感。
借用用户的访问行为来执行某些延迟任务
但是上面使用sleep来实现定时任务,是效率很低的一种方案。我们希望不要使用这种方式来执行,这样的话就可以解决效率问题。我们借用用户访问行为来执行任务。用户对网站的访问其实是一个非常丰富的行为资源,包括搜索引擎蜘蛛对网站的访问,都可以算作这个类型。在用户访问网站时,内部加一个动作,去检查任务列表中是否存在没有被执行的任务,如果存在,就将这个任务执行。对于用户而言,利用上面所说的fsockopen,根本感觉不到自己的访问竟然还做出了这样的贡献。但是这种访问的缺点就是访问很不规律,比如你希望在凌晨2点执行某项任务,但是这个时间段非常倒霉,没有用户或任何行为到达你的网站,直到早上6点才有一个新访问。这就导致你原本打算2点执行的任务,到6点才被执行。
这里涉及到一个定时任务列表,也就是说你需要有一个列表来记录所有任务的时间、执行什么内容。一般来说,很多系统会采用数据库来记录这些任务列表,比如wordpress就是这样做的。我则利用文件读写特性,提供了托管在github上的开源项目php-cron,你可以去看看。总之,如果你想要管理多个定时任务,靠上面的单个php是无法合理布局的,必须想办法构建一个schedules列表。由于这里面的逻辑比较复杂,就不再详细阐述,我们仅停留在思路层面上。
借用第三方定时任务跳板
很好玩的是,一些服务商提供了各种类型的定时任务,例如阿里云的ACE提供了单独的定时任务,你可以填写自己应用下的某个uri。百度云BCE提供了服务器监测功能,每天会按照一定的时间规律访问应用下的固定uri。类似的第三方平台上还有很多定时任务可以用。你完全可以用这些第三方定时任务作为跳板,为你的网站定时任务服务。比如说,你可以在阿里云ACE上建立一个每天凌晨2点的定时任务,执行的uri是/cron.php。然后你创建一个cron.php,里面则采用fsockopen去访问你真正要执行某些任务的网站的url,例如上面的,而且在cron.php中还可以访问多个url。然后把cron.php上传到你的ACE上面去linux计划任务执行url,让ACE的定时任务去访问/cron.php,然后让cron.php去远程请求目标网站的定时任务脚本。
循环利用include包含文件(待验证)
php面向过程的特性使得其程序是从上往下执行的,利用这个特性,在我们使用include某个文件时,就会执行被引入的文件linux计划任务执行url,知道include的文件内程序执行完之后,再往下执行。如果我们创建一个循环,再利用sleep,不断的include某个文件,使循环执行某段程序,则可以达到定时执行的目的。我们再进一步,并不是利用while(true)来实现循环,而是利用被include文件本身再include自身来实现循环,比如我们创建一个do.phplinux qq,它的内容如下:
if(...) exit(); // 通过某个开关来关闭执行 // ... // 执行某些程序 // ... sleep($loop); // 这个$loop在include('do.php');之前赋值 include(dirname(__FILE__).'/do.php');
其实通过这种方法执行和while的思路也像。而且同样用到sleep,效率低。
PHP定时任务是一个非常有意思的东西,虽然说实话,用系统的php.exe去直接执行php文件的效率更高,但是对于很多普通站长而言,虚拟主机是无法做到直接php执行原生程序的。本文仅提供一些解决的思路,我也仅仅是在学习中,有很多问题或表述都不正确,希望你指出来;你可以通过本文的思路,开发出自己的一种解决方案,希望你能将方案发布,并与我一起探讨。
转 :
优质内容筛选与推荐>>
1、28款数据恢复软件对比测试
2、#python-练习
3、BZOJ.1951.[SDOI2010]古代猪文(费马小定理 Lucas CRT)
4、Docker:容器间互联的应用zabbix监控项目 [十]
5、Java RTTI运行时类型识别
长按二维码向我转账
受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。