php任务分配思路_PHP执行定时任务的几种方法思路

PHP本身是没有定时功能的,PHP也不能多线程。PHP的定时任务功能必须通过和其他工具结合才能实现,例如WordPress内置了wp-cron的功能,很厉害。本文,我们就来深入的解析几种常见的php定时任务的思路。

1、Linux服务器上使用CronTab定时执行php

我们先从相对比较复杂的服务器执行php谈起。服务器上安装了php,就可以执行php文件,无论是否安装了nginx或Apache这样的服务器环境软件。而Linux中,使用命令行,用CronTab来定时任务,又是绝佳的选择,而且也是效率最高的选择。

首先,进入命令行模式。作为服务器的linux一般都默认进入命令行模式的,当然,我们管理服务器也一般通过putty等工具远程连接到服务器,为了方便,我们用root用户登录。在命令行中键入:crontab -e

之后就会打开一个文件,并且是非编辑状态,则是vi的编辑界面,通过敲键盘上的i,进入编辑模式,就可以编辑内容。这个文件中的每一行就是一个定时任务,我们新建一行,就是新建一条定时任务(当然是指这一行内按照一定的格式进行书写)。我们现在来举个例子,增加一行,内容如下:00 * * * * lynx -dump https://www.yourdomain.com/script.php

这是什么意思呢?实际上上面这一行由两部分组成,前面一部分是时间,后面一部分是操作内容。例如上面这个,00 * * * *

就是指当当前时间的分钟数为00时,执行该定时任务。时间部分由5个时间参数组成,分别是:分 时 日 月 周

第1列表示分钟1~59 每分钟用或者 */1表示,/n表示每n分钟,例如*/8就是每8分钟的意思,下面也是类推

第2列表示小时1~23(0表示0点)

第3列表示日期1~31第4列表示月份1~12第5列标识号星期0~6(0表示星期天)

整个句子的后面部分就是操作的具体内容。lynx -dump https://www.yourdomain.com/script.php

意思就是说通过lynx访问这个url。我们在使用中主要用到lynx、curl、wget来实现对url的远程访问,而如果要提高效率,直接用php去执行本地php文件是最佳选择,例如:00 */2 * * * /usr/local/bin/php /home/www/script.php

这条语句就可以在每2小时的0分钟,通过linux内部php环境执行script.php,注意,这里可不是通过url访问,通过服务器环境来执行哦,而是直接执行,因为绕过了服务器环境,所以效率当然要高很多。

好了,已经添加了几条需要的定时任务了吧。点击键盘上的Esc键,输入“:wq”回车,这样就保存了设置的定时任务,屏幕上也能看到提示创建了新的定时任务。接下来就是好好写你的script.php了。

关于CronTab的更多用法这里就不介绍了,如果你想更灵活的使用这个定时任务功能,应该自己再去深入学习一下crontab。

2、Windows服务器上使用bat定时执行php

windows上和linux上有一个类似的cmd和bat文件,bat文件类似于shell文件,执行这个bat文件,就相当于依次执行里面的命令(当然,还可以通过逻辑来实现编程),所以,我们可以利用bat命令文件在windows服务器上面实现PHP定时任务。实际上在windows上定时任务,和linux上道理是一样的,只不过方法和途径不同。好了下面开始。

首先,在一个你觉得比较适当的位置创建一个cron.bat文件,然后用文本编辑器打开它(记事本都可以),在里面写上这样的内容:D:\php\php.exe -q D:\website\test.php

这句话的意思就是,使用php.exe去执行test.php这个php文件,和上面的contab一样,绕过了服务器环境,执行效率也比较高。写好之后,点击保存,关闭编辑器。

接下来就是设置定时任务来运行cron.bat。依次打开:“开始–>控制面板–>任务计划–>添加任务计划”,在打开的界面中设置定时任务的时间、密码,通过选择,把cron.bat挂载进去。确定,这样一个定时任务就建立好了,在这个定时任务上右键,运行,这个定时任务就开始执行了,到点时,就会运行cron.bat处理,cron.bat再去执行php。

3、非自有服务器(虚拟主机)上实现php定时任务

如果站长没有自己的服务器,而是租用虚拟主机,就无法进入服务器系统进行上述操作。这个时候应该如何进行php定时任务呢?其实方法又有多个。

4、使用ignore_user_abort(true)和sleep死循环

在一个php文档的开头直接来一句:ignore_user_abort(true);

这时,通过url访问这个php的时候,即使用户把浏览器关掉(断开连接),php也会在服务器上继续执行。利用这个特性,我们可以实现非常牛的功能,也就是通过它来实现定时任务的激活,激活之后就随便它自己怎么办了,实际上就有点类似于后台任务。

而sleep(n)则是指当程序执行到这里时,暂时不往下执行,而是休息n秒钟。如果你访问这个php,就会发现页面起码要加载n秒钟。实际上,这种长时间等待的行为是比较消耗资源的,不能大量使用。

那么定时任务到底怎么实现呢?使用下面的代码即可实现:<?php

ignore_user_abort(true);

set_time_limit(0);

date_default_timezone_set('PRC'); // 切换到中国的时间$run_time = strtotime('+1 day'); // 定时任务第一次执行的时间是明天的这个时候$interval = 3600*12; // 每12个小时执行一次if(!file_exists(dirname(__FILE__).'/cron-run')) exit(); // 在目录下存放一个cron-run文件,如果这个文件不存在,说明已经在执行过程中了,该任务就不能再激活,执行第二次,否则这个文件被多次访问的话,服务器就要崩溃掉了do { if(!file_exists(dirname(__FILE__).'/cron-switch')) break; // 如果不存在cron-switch这个文件,就停止执行,这是一个开关的作用 $gmt_time = microtime(true); // 当前的运行时间,精确到0.0001秒 $loop = isset($loop) && $loop ? $loop : $run_time - $gmt_time; // 这里处理是为了确定还要等多久才开始第一次执行任务,$loop就是要等多久才执行的时间间隔 $loop = $loop > 0 ? $loop : 0; if(!$loop) break; // 如果循环的间隔为零,则停止

sleep($loop);

// ... // 执行某些代码 // ...

@unlink(dirname(__FILE__).'/cron-run'); // 这里就是通过删除cron-run来告诉程序,这个定时任务已经在执行过程中,不能再执行一个新的同样的任务 $loop = $interval;

} while(true);

通过执行上面这段php代码,即可实现定时任务,直到你删除cron-switch文件,这个任务才会停止。

但是有一个问题,也就是如果用户直接访问这个php,实际上没有任何作用,页面也会停在这个地方,一直处于加载状态,有没有一种办法可以消除这种影响呢?fsockopen帮我们解决了这个问题。

fsockopen可以实现在请求访问某个文件时,不必获得返回结果就继续往下执行程序,这是和curl通常用法不一样的地方,我们在使用curl访问网页时,一定要等curl加载完网页后,才会执行curl后面的代码,虽然实际上curl也可以实现“非阻塞式”的请求,但是比fsockopen复杂的多,所以我们优先选择fsockopen,fsockopen可以在规定的时间内,比如1秒钟以内,完成对访问路径发出请求,完成之后就不管这个路径是否返回内容了,它的任务就到这里结束,可以继续往下执行程序了。利用这个特性,我们在正常的程序流中加入fsockopen,对上面我们创建的这个定时任务php的地址发出请求,即可让定时任务在后台执行。如果上面这个php的url地址是www.yourdomain.com/script.php,那么我们在编程中,可以这样:// ...// 正常的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.1\r\n";

$header.="Host: $host\r\n";

$header.="Connection: close\r\n\r\n";//长连接关闭

fwrite($fp, $header);

usleep(1000); // 这一句也是关键,如果没有这延时,可能在nginx服务器上就无法执行成功

fclose($fp); return array('error_code' => 0);

}

}

_sock('www.yourdomain.com/script.php');// ...// 继续执行其他动作// ..

把这段代码加入到某个定时任务提交结果程序中,在设置好时间后,提交,然后执行上面这个代码,就可以激活该定时任务,而且对于提交的这个用户而言,没有任何页面上的堵塞感。

5、借用用户的访问行为来执行某些延迟任务

但是上面使用sleep来实现定时任务,是效率很低的一种方案。我们希望不要使用这种方式来执行,这样的话就可以解决效率问题。我们借用用户访问行为来执行任务。用户对网站的访问其实是一个非常丰富的行为资源,包括搜索引擎蜘蛛对网站的访问,都可以算作这个类型。在用户访问网站时,内部加一个动作,去检查任务列表中是否存在没有被执行的任务,如果存在,就将这个任务执行。对于用户而言,利用上面所说的fsockopen,根本感觉不到自己的访问竟然还做出了这样的贡献。但是这种访问的缺点就是访问很不规律,比如你希望在凌晨2点执行某项任务,但是这个时间段非常倒霉,没有用户或任何行为到达你的网站,直到早上6点才有一个新访问。这就导致你原本打算2点执行的任务,到6点才被执行。

这里涉及到一个定时任务列表,也就是说你需要有一个列表来记录所有任务的时间、执行什么内容。一般来说,很多系统会采用数据库来记录这些任务列表,比如wordpress就是这样做的。我则利用文件读写特性,提供了托管在github上的开源项目php-cron,你可以去看看。总之,如果你想要管理多个定时任务,靠上面的单个php是无法合理布局的,必须想办法构建一个schedules列表。由于这里面的逻辑比较复杂,就不再详细阐述,我们仅停留在思路层面上。

6、借用第三方定时任务跳板

很好玩的是,一些服务商提供了各种类型的定时任务,例如阿里云的ACE提供了单独的定时任务,你可以填写自己应用下的某个uri。百度云BCE提供了服务器监测功能,每天会按照一定的时间规律访问应用下的固定uri。类似的第三方平台上还有很多定时任务可以用。你完全可以用这些第三方定时任务作为跳板,为你的网站定时任务服务。比如说,你可以在阿里云ACE上建立一个每天凌晨2点的定时任务,执行的uri是/cron.php。然后你创建一个cron.php,里面则采用fsockopen去访问你真正要执行某些任务的网站的url,例如上面的www.yourdomain.com/script.php,而且在cron.php中还可以访问多个url。然后把cron.php上传到你的ACE上面去,让ACE的定时任务去访问/cron.php,然后让cron.php去远程请求目标网站的定时任务脚本。

7、循环利用include包含文件(待验证)

php面向过程的特性使得其程序是从上往下执行的,利用这个特性,在我们使用include某个文件时,就会执行被引入的文件,知道include的文件内程序执行完之后,再往下执行。如果我们创建一个循环,再利用sleep,不断的include某个文件,使循环执行某段程序,则可以达到定时执行的目的。我们再进一步,并不是利用while(true)来实现循环,而是利用被include文件本身再include自身来实现循环,比如我们创建一个do.php,它的内容如下:if(...) exit(); // 通过某个开关来关闭执行// ...

// 执行某些程序// ...

sleep($loop); // 这个$loop在include('do.php');之前赋值

include(dirname(__FILE__).'/do.php');

其实通过这种方法执行和while的思路也像。而且同样用到sleep,效率低。

PHP定时任务是一个非常有意思的东西,虽然说实话,用系统的php.exe去直接执行php文件的效率更高,但是对于很多普通站长而言,虚拟主机是无法做到直接php执行原生程序的。本文仅提供一些解决的思路,我也仅仅是在学习中,有很多问题或表述都不正确,希望你指出来;你可以通过本文的思路,开发出自己的一种解决方案,希望你能将方案发布,并与我一起探讨。

相关推荐:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/562504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JDBC练习二

JDBC练习二 import java.sql.*; /*JDBC完成Delete */public class JDBCTest02 {public static void main(String[] args) {// 1、注册驱动// 2、获取连接// 3、获取数据库操作对象// 4、执行sql语句// 5、获取查询结果集// 6、释放资源Connection conn null;Statement stmt …

dhrystone测试结果_Linux性能测试工具-UnixBench--安装以及结果分析-阿里云开发者社区...

UnixBenchunixbench是一个用于测试unix系统性能的工具&#xff0c;也是一个比较通用的benchmark&#xff0c; 此测试的目的是对类Unix 系统提供一个基本的性能指示&#xff0c;很多测试用于系统性能的不同方面&#xff0c;这些测试的结果是一个指数值(index value&#xff0c;如…

JDBC练习三

JDBC练习三 import java.sql.*; /*注册驱动的另一种方式 */public class JDBCTest03 {public static void main(String[] args) {try{// 注册驱动Class.forName("com.mysql.jdbc.Driver");// 获取连接Connection conn DriverManager.getConnection("jdbc:mysq…

mailbox 编程_MailboxProcessor从C#

虽然可以使用MailboxProcessor< T>直接从C#(使用C#异步扩展),如我的另一个答案中所指出的,这不是一件好事 – 我主要是为了好奇而写的.邮箱处理器< T>类型被设计为从F#使用,所以它不适合C#编程模型.你可能可以为C#实现类似的API,但它不会那么好(当然不是C#4.0). TP…

JDBC练习四

JDBC练习四 import java.sql.*; import java.util.*; /*使用资源绑定器 */ public class JDBCTest04 {public static void main(String[] args) {ResourceBundle bundle ResourceBundle.getBundle("jdbc");String driver bundle.getString("driver");St…

JDBC练习五

JDBC练习五 /*执行DQL语句 */import java.sql.*; import java.util.*;public class JDBCTest05 {public static void main(String[] args) {// 1、注册驱动// 2、建立连接// 3、获取数据库操作对象// 4、执行sql语句// 5、获取查询结果集// 6、释放资源Connection conn null;…

gradle 查看依赖类库版本_如何查找第三方库(Gradle引用)的依赖?

原标题&#xff1a;如何查找第三方库(Gradle引用)的依赖?如何查找第三方库(Gradle引用)的依赖?每日一问-Tools-20181105答: 三方法可查找.1. 执行 Gradle Task : androidDependencies可以直接执行gradleandroidDependencies执行结果将在控制台直接输出.可以在控制台直接查看,…

JDBC小记

JDBC小记 前言 昨天刚冲完了jdbc,今天来总结 一.JDBC介绍 JDBC (百度百科): Java数据库连接&#xff0c;&#xff08;Java Database Connectivity&#xff0c;简称JDBC&#xff09;是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口&#xff0c;提供了诸如查询…

云联惠认证时间_云联惠强制关闭真正原因是什么?

展开全部云联惠强制关闭的原因是云联惠为特大网络传销犯罪62616964757a686964616fe78988e69d8331333433616232团伙。广东云联惠网络科技有限公司成立于2014年1月6日&#xff0c;法定代表人是黄观勇。2018年5月8日&#xff0c;广东省公安厅部署广州警方开展收网行动&#xff0c;…

MySQL数据库基本操作命令

MySQL数据库学习 登陆&#xff1a;shell > mysql - uroot - p 修改&#xff1a; ①shell >的MySQL - uroot - ppassward -提示提示符 ②mysql >提示消费 【参数】\D完整的日期&#xff1b;\d当前数据库&#xff1b;\h服务器名称&#xff1b;\u当前用户&#xff1b; 修…

iview this.$modal 关闭所有的弹窗_一看会用TOB弹窗应用场景

全文阅读约10分钟&#xff0c;无高深理论&#xff0c;直述弹窗在tob产品中的应用场景。弹窗在B端设计中应用非常高频了&#xff0c;根据应用场景我把它分为三类&#xff0c;一类为模态弹窗(有黑色不透明度的背景遮罩)&#xff0c;一类为非模态弹窗(无遮罩)&#xff0c;一类归为…

In aggregated query without GROUP BY, expression #2 of SELECT list contains nonaggregated column...

ERROR 1140 (42000): In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column ‘mydb.student.sname’; this is incompatible with sql_modeonly_full_group_by maven项目报错error: expression #2 of SELECT list contains non…

又学MySQL

又学MySQL 一、数据库的基本操作 1.1、启动 net start mysql -- 启动1.2、断开 net stop mysql -- 断开1.3、连接 mysql -uroot -p -- 连接数据库 Enter password:******1.4、退出 exit -- 退出1.5、创建数据库 create database 数据库名;-- 例如&#xff0c;创建一个叫…

人工智能芯片龙头之一gti概念股_AI芯片相关股票有哪些?AI芯片概念股票龙头一览...

12月18日消息&#xff0c;AI芯片概念开盘报涨&#xff0c;华西股份(9.17&#xff0c;2.573%)领涨&#xff0c; 富瀚微(148&#xff0c;1.914%)、汇顶科技(155.43&#xff0c;1.06%)、华天科技(14.03&#xff0c;0.718%)、紫光股份(21&#xff0c;0.095%)等跟涨。那么&#xff0…

数据库错误 ERROR 1366 (HY000): Incorrect string value: ‘\xD4\xF8\xBB\xAA‘ for column ‘Sname‘ at row 1解决

数据库错误 ERROR 1366 (HY000): Incorrect string value: ‘\xD4\xF8\xBB\xAA’ for column ‘Sname’ at row 1解决 一.原因: 插入数据时有中文字符出现 二.解决方案 1.查看当前服务器状态 : status或者\s 2.修改数据库的默认编码方式 使用命令: alter database mydb ch…

python requests 状态码_requests获取所有状态码

requests获取所有状态码 requests默认是不会获取301/302的状态码的。可以设置allow_redirects=False,这样就可以获取所有的状态码了 import requests # url # url = http://www.freebuf.com/news/157100.html # 请求200,返回200 url = http://www.freebuf.com/fevents/133225…

【SpringBoot篇】解决缓存击穿问题② — 基于逻辑过期方式

&#x1f38a;专栏【SpringBoot】 &#x1f354;喜欢的诗句&#xff1a;天行健&#xff0c;君子以自强不息。 &#x1f386;音乐分享【如愿】 &#x1f384;欢迎并且感谢大家指出小吉的问题&#x1f970; 文章目录 &#x1f38d;什么是逻辑过期方式⭐思路&#x1f339;代码 &am…

Git使用手册--超级详细,自己都看哭了

Git 一.git简介 Git是目前世界上最先进的分布式版本控制系统&#xff08;没有之一&#xff09;。 关于版本控制系统: 版本控制是一种记录一个或若干文件内容变化&#xff0c;以便将来查阅特定版本修订情况的系统.有了它你就可以将选定的文件回溯到之前的状态&#xff0c;甚…

nodejs核心模块fs删除文件_用 NodeJS 重命名系统文件

作者&#xff1a;Nick Major翻译&#xff1a;疯狂的技术宅原文&#xff1a;https://coderrocketfuel.com/article/how-to-rename-a-system-file-using-node-js未经允许严禁转载介绍你是在 Node.js 中操作系统文件&#xff0c;并且需要一种简单的方法来以编程方式重命名文件&…

Java io流---拷贝目录

Java io流—拷贝目录 代码: package demo01;import java.io.File;public class CopyAll {public static void main(String[] args) {//拷贝源File srcFile new File("E:\\学习\\a");//拷贝目标File destFile new File("C:\\Users\\22721\\Desktop");//…