目錄
1、Linux伺服器上使用CronTab定時執行php
2、Windows伺服器上使用bat定時執行php
3、非自有伺服器(虛擬主機)上實作php定時任務
4、使用ignore_user_abort(true)和sleep死循環
5、借用用户的访问行为来执行某些延迟任务
6、借用第三方定时任务跳板
7、循环利用include包含文件(待验证)
首頁 後端開發 php教程 PHP執行定時任務的幾種方法思路

PHP執行定時任務的幾種方法思路

Mar 14, 2018 pm 02:07 PM
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(&#39;PRC&#39;); // 切换到中国的时间$run_time = strtotime(&#39;+1 day&#39;); // 定时任务第一次执行的时间是明天的这个时候$interval = 3600*12; // 每12个小时执行一次if(!file_exists(dirname(__FILE__).&#39;/cron-run&#39;)) exit(); // 在目录下存放一个cron-run文件,如果这个文件不存在,说明已经在执行过程中了,该任务就不能再激活,执行第二次,否则这个文件被多次访问的话,服务器就要崩溃掉了do {  if(!file_exists(dirname(__FILE__).&#39;/cron-switch&#39;)) 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__).&#39;/cron-run&#39;); // 这里就是通过删除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 .= &#39;?&#39;.$query;  if($scheme == &#39;https&#39;) {
    $host = &#39;ssl://&#39;.$host;
  }

  $fp = fsockopen($host,$port,$error_code,$error_msg,1);  if(!$fp) {    return array(&#39;error_code&#39; => $error_code,&#39;error_msg&#39; => $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(&#39;error_code&#39; => 0);
  }
}

_sock(&#39;www.yourdomain.com/script.php&#39;);// ...// 继续执行其他动作// ..
登入後複製

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

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(&#39;do.php&#39;);之前赋值

include(dirname(__FILE__).&#39;/do.php&#39;);
登入後複製

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

PHP定時任務是一個很有趣的東西,雖然說實話,用系統的php.exe去直接執行php檔案的效率更高,但是對於很多普通站長而言,虛擬主機是無法做到直接php執行原生程序的。本文僅提供一些解決的思路,我也只是在學習中,有很多問題或表述都不正確,希望你指出來;你可以透過本文的思路,發展出自己的一種解決方案,希望你能將方案發布,並與我一起探討。

相關推薦:

詳解PHP實作執行定時任務

詳解PHP實作執行定時任務_PHP

####################################################### ######詳解PHP執行定時任務的實作思路_php技巧######

以上是PHP執行定時任務的幾種方法思路的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

See all articles