php执行定时任务

来源:互联网 发布:知乎 mpacc值得读吗 编辑:程序博客网 时间:2024/04/25 21:15

php定时发邮件,其实是一个‘很古老’的话题!因为php不像jsp那么‘强大’,不能执行一些定时任务,所以有好多想定时实现的功能无法实现,或者虽然实现了,但终究是把负担加在了访客,或是管理员身上!因为很大一部分的是通过客服端 浏览器 请求时触发一个事件的,用这个方法的系统/应用不在少算。下面我就说三种方法吧!
最典型、应该也是使用最广泛的一个就是:像 DEDECMS(不要说,你不知道DEDECMS是什么东西)一样通过客服端 浏览器 触发的方式,DEDECMS他们后台有个计划任务管理,其中就有一个方法是通过js触发,下面是他们的原文一个说明:

计划任务执行的说明

·为了确保任务能执行完全,建议使用Dede的客户端工具,否则只能通过JS触发,但JS触发有很多不确定因素会导致任务不能完成;
·JS触发方式:在所有文档页面中用JS调用/plus/task.php?client=js(必须禁用计划任务的密码,系统配置参数->其它选项);
·自行定制客户端:直接访问“http://网址/plus/task.php?clientpwd=管理密码”,会返回其中一个可执行任务的网址(没有可用任务则返回串:notask),然后客户端运行这个网址即可。

他们的说明很清楚的指出:通过js触发,js这就是一个客服端的代码,所以必须要客服端触发他们的计划任务。第一种方法先说到这里

第二种方法:相信很多人都去谷歌(php 定时发送邮件),百度搜过‘php 定时发送邮件’,发现一大部分说通过系统的任务计划去实现(xp通过at命令/控制面板添加任务计划;linux的crontab命令实现),本人觉得这是一个最垃圾的办法,一般人的空间用的都是 虚拟主机 ,哪有你接触到服务器的可能,主机提供商当然也不可能为你在服务器上去添加什么 定时任务 。所以,这种方法虽然是网上查到的最多的,但它其实就是一个完全不现实的东西,自己没事拿来玩玩还是可以,真正要有所用途是不可能的!

下面再介绍本人的一个思路:在第一种方法中我们提到 客服端 请求,不过一直强调的是通过浏览器,可是你想想 访问网站的方法就只有浏览器吗!?当然不止,比如:在dos下,我们可以用telnet命令‘登陆’web服务器,在其他程序里面同样可以,比如java 可以通过java.net.url 读取网页内容,其实这就是一次相当于浏览器的请求,当然php就更不用说了:file、file_get_contents、fsockopen、还有强大的curl扩展(当然要使用这些方法,都有一定的条件)。既然这样我们实现 定时发送邮件 的功能方法就多了很多,因为只要你请求了一次web服务器,服务器就会执行对应的程序(发送到时间的邮件),那是不是就算你开个迅雷下载一下你的 任务页面也可以实现定时发送邮件了,答案是肯定的!!!

可这次,我要说的一个方法跟上面的都不同。搜索引擎,大家都用吧!应该对它们大概的工作模式还是了解吧!?它们的蜘蛛会 定时/不定时 的去抓取网页,这是不是也是一个web请求,当然是的!!那么我们的定时发送邮件,是不是有更好的实现方法了。我们在自己的网页里,加一个小小的判断,就可以知道来访的是 搜索引擎的蜘蛛了,还是普通的访客了!!在php里有一个环境变量:$_SERVER['HTTP_USER_AGENT'],可以很容易的读取到向服务器请求的是‘谁’。既然我们知道了,来访的是‘谁’,那么我们就可以对不同的来访者 执行不同的代码!当我们,发现时搜索引擎时,就执行一个 已经到指定时间的邮件,是不是就解决了定时发邮件的问题!!有人肯定会有疑问,搜索引擎到底多久会来我的网站抓取一次了,这个问题 还是请你自己到谷歌网站管理员找答案吧,我就不解释了!!当然这个方法也不是就完美无缺的,它应该对网站SEO会有些影响,所以在你使用该方法时还是全面考虑一下,权衡一下你自己需求!(为了更好的说明搜索引擎抓取的速度,附个图。这个是谷歌抓取我博客的统计信息)谷歌抓取记录

当然,你可能会问:第一种通用的方法不是也可以吗?那是自然。我们现在做个假设:每天有100封邮件等待发送,上网高峰肯定是出现在早上8点到晚上10点,这个没得怀疑,那么这中间时间的跨度是14小时,那么平均下来就是每小时得发送7封邮件左右,这个发送邮件的动作肯定是由一个游客触发。这也就意味着这位游客得等你的系统发送7封邮件之后才能看到你的网页内容。你想想这是一个多长到时间,只恐怕人家早就没耐心等下去了!所以这就是有搜索引擎触发的好处!

乱七八糟说了这么多,具体代码我就不给出了,相信文章写到这个地步,你懂的(当然,如果仍有什么问题可以在下面留言)。时间到时过得蛮快的啊!!看看右下角,qq早就安静的睡了,只留下一时间还在加速的跑着,还是定时的东西好啊!时间不早了,写写睡吧:

时隔这么久,再来补上一点吧!网上还有一种比较‘火’的方法,使用php的两个系统函数,分别是:ignore_user_abort、set_time_limit。我简单我一下实现方法吧!主要是通过设置php执行脚本最大超时时间来实现,set_time_limit(0),确保php脚本不会因为超时而,停止脚本的执行;通过ignore_user_abort(true),保证脚本不会因为客服端放弃请求而停止脚本的执行!采用这种方法起码要保证一点:服务器没有禁用:ignore_user_abort函数(因为一般的虚拟空间都是禁用这个函数的)。这个方法本人以前也试用过,不过没有得到期望的结果:我的方法是用php做gtalk机器人,实现微博更新。结果是这样的:机器人一般能保证2–3小时不等的在线时间,然后会自动下线!这也就说明用这个方法来定时发送邮件还是可以的,即便是一两小时内没人访问你的网站,也完全有可能实现在这接下来的一段时间内实现邮件的发送。不过这个方法最大的缺的就是对服务器性能 的消耗特别大,这也就是为什么虚拟主机禁用ignore_user_abort函数的原因吧!

php定时计划任务实现方法
我在uchome 中 分析到, uchome是这样做的
1. 把所有的计划任务存放到数据库
2. 每次用户进行操作或打开页面的时候都按排序执行一条计划任务. 也就是轮番判断,时间到了的, 就在用户进程中执行.
uchome的计划任务代码在 ./source/function_cron.php
上面只自己分析uchome代码关于计划任务大概的结果, 抛砖引玉. 希望谁有好的方法拿出来共享.
ignore_user_abort()
我前一段时间彻底研究过计划任务,认为计划任务的思路很多,但最适合Web的还是触发式的,就是类似于DZ和PHPWind的,似乎大多数web应用也都是这么做的,再说几种其他的供参考
1,为了提供稳定的触发,用crontab+wget或者ab提供定时访问
2,nohup + php写守护程序
3,直接用php写个死循环还提供触发,这时需要用缓存或者数据库来协助推出循环,还有必须用sleep或者usleep控制触发频率
4,crontab+php
5,web触发方式,这也有区别,一种是定时触发,一种是定周期触发,DZ和PHPWind都是定时触发,我最后采用的是定周期触发
具体的实现思路 很容易想,就不多说了
自己有主机肯定用crontab来执行命令行PHP
没有只能写在代码中了
用crontab会比较好, 如果用循环的话, 最好也要把循环和具体处理程序分开, 不然内存会一直增加.

今天一不小心在php手册上发现了这个函数-ignore_user_abort,这个函数可以帮助我们实现像linux中的cron一样实现计划任务,下面一起来看下该如何来实现。
首先看下php手册对这个函数的解释
Description

int ignore_user_abort ([ bool $setting ] )
Sets whether a client disconnect should cause a script to be aborted.

也就是说无论客户端是否关闭浏览器,下面的程序都会执行.
再看下其参数
Parameters

setting
If not set, the function will only return the current setting.

这个函数接受一个参数,来决定是否启用ignore_user_abort的功能。
再看其返回值:

Return Values
Returns the previous setting, as a boolean.

这里说返回前一次的设置,并且是bool值得,经过我的测试,这个说法是不对的,返回的明明是int型的,不相信的话大家可以写一个php文件来测试下。
说了这么多了,到底该如何用php的这个函数实现计划任务呢?还跌借助另外一个函数,这个函数是set_time_limit,通过set_time_limit0)可以设置程序的运行时间为无限制,php默认的运行时间是30秒,通过set_time_limit(0)可以让程序无限制的执行下去。在程序执行之前加上ignore_user_abort(1)和set_time_limit(0)即可以了,最终程序该如何写呢?给大家一个例子。

1.  <?php

2.  ignore_user_abort(); // run script in background

3.  set_time_limit(0); // run script forever

4.  $interval=30; // do every 15 minutes…

5.  do{

6.  $fp = fopen(‘text3.txt’,'a’);

7.  fwrite($fp,’test’);

8.  fclose($fp);

9.  sleep($interval); // wait 15 minutes

10. }while(true);

11. ?>

 

原创粉丝点击