Maison  >  Article  >  développement back-end  >  Plusieurs méthodes et idées pour exécuter des tâches planifiées en PHP

Plusieurs méthodes et idées pour exécuter des tâches planifiées en PHP

小云云
小云云original
2018-03-14 14:07:183846parcourir

PHP lui-même n'a pas de fonction de synchronisation et PHP ne peut pas être multithread. La fonction de tâche planifiée de PHP doit être combinée avec d'autres outils pour y parvenir. Par exemple, WordPress a une fonction wp-cron intégrée, qui est très puissante. Dans cet article, nous analyserons en profondeur les idées de plusieurs tâches planifiées PHP courantes.

1. Utilisez CronTab pour exécuter régulièrement php sur le serveur Linux

Commençons par l'exécution relativement complexe de php sur le serveur. Une fois PHP installé sur le serveur, les fichiers PHP peuvent être exécutés, que le logiciel d'environnement serveur tel que nginx ou Apache soit installé ou non. Sous Linux, utiliser la ligne de commande et CronTab pour planifier des tâches est un excellent choix, et c'est également le choix le plus efficace.

Tout d’abord, entrez en mode ligne de commande. En tant que serveur, Linux passe généralement par défaut en mode ligne de commande. Bien entendu, notre serveur de gestion se connecte également généralement au serveur à distance via des outils tels que putty. Pour plus de commodité, nous nous connectons en tant qu'utilisateur root. Après avoir tapé :

crontab -e

dans la ligne de commande, un fichier sera ouvert, et il est dans un état de non-édition. C'est l'interface d'édition de vi. En appuyant sur i sur le clavier, entrez le. mode d'édition, vous pouvez modifier le contenu. Chaque ligne de ce fichier est une tâche planifiée. Lorsque nous créons une nouvelle ligne, nous créons une nouvelle tâche planifiée (bien sûr, cela signifie écrire dans un certain format dans cette ligne). Prenons maintenant un exemple et ajoutons une ligne avec le contenu suivant :

00 * * * * lynx -dump https://www.yourdomain.com/script.php

Qu'est-ce que cela signifie ? En fait, la ligne ci-dessus se compose de deux parties, la première partie est l'heure et la dernière partie est le contenu de l'opération. Par exemple, dans l'exemple ci-dessus,

00 * * * *

signifie que lorsque la minute de l'heure actuelle est 00, la tâche planifiée sera exécutée. La partie temporelle se compose de 5 paramètres temporels, qui sont :

分 时 日 月 周
第1列表示分钟1~59 每分钟用或者 */1表示,/n表示每n分钟,例如*/8就是每8分钟的意思,下面也是类推
第2列表示小时1~23(0表示0点)
第3列表示日期1~31第4列表示月份1~12第5列标识号星期0~6(0表示星期天)

La dernière partie de la phrase entière est le contenu spécifique de l'opération.

lynx -dump https://www.yourdomain.com/script.php

signifie accéder à cette URL via lynx. Nous utilisons principalement lynx, curl et wget pour obtenir un accès à distance aux URL. Si nous voulons améliorer l'efficacité, utiliser directement PHP pour exécuter des fichiers PHP locaux est le meilleur choix, par exemple :

00 */2 * * * /usr/local/bin/php /home/www/script.php

Cette déclaration. peut exécuter script.php via l'environnement PHP interne de Linux à 0 minute toutes les 2 heures. Notez que cela n'est pas accessible via l'URL et exécuté via l'environnement du serveur, mais directement exécuté car l'environnement du serveur est contourné, donc l'efficacité est bien sûr. beaucoup plus élevé.

D'accord, quelques tâches planifiées obligatoires ont été ajoutées. Cliquez sur la touche Échap du clavier, entrez ":wq" et appuyez sur Entrée. Cela enregistre la tâche planifiée définie et vous pouvez également voir une invite à l'écran indiquant qu'une nouvelle tâche planifiée a été créée. L'étape suivante consiste à écrire correctement votre script.php.

Je ne présenterai pas ici davantage d'utilisation de CronTab. Si vous souhaitez utiliser cette fonction de tâche planifiée de manière plus flexible, vous devriez en apprendre davantage sur crontab vous-même.

2. Utilisez bat pour exécuter régulièrement php sur les serveurs Windows

Il existe un fichier cmd et bat similaire sur Windows et Linux. Le fichier bat est similaire à un fichier shell. équivaut à Puisque les commandes à l'intérieur sont exécutées dans l'ordre (bien sûr, la programmation peut également être implémentée via la logique), nous pouvons utiliser le fichier de commandes bat pour implémenter les tâches planifiées PHP sur le serveur Windows. En fait, le principe des tâches planifiées sous Windows est le même que celui sous Linux, mais les méthodes et approches sont différentes. Bon, commençons.

Tout d'abord, créez un fichier cron.bat dans un emplacement que vous jugez plus approprié, puis ouvrez-le avec un éditeur de texte (le Bloc-notes fonctionnera) et écrivez-y le contenu suivant :

D:\php\php.exe -q D:\website\test.php

Ce que cette phrase signifie, c'est que l'utilisation de php.exe pour exécuter le fichier php test.php, comme le contab ci-dessus, contourne l'environnement du serveur et l'efficacité d'exécution est relativement élevée. Après avoir écrit, cliquez sur Enregistrer et fermez l'éditeur.

L'étape suivante consiste à configurer une tâche planifiée pour exécuter cron.bat. Ouvrez dans l'ordre : "Démarrer -> Panneau de configuration -> Planification des tâches -> Ajouter une planification des tâches", définissez l'heure et le mot de passe de la tâche planifiée dans l'interface ouverte et montez cron.bat en le sélectionnant. OK, une telle tâche planifiée a été créée. Cliquez avec le bouton droit sur la tâche planifiée et exécutez-la, et la tâche planifiée commencera à être exécutée lorsque le temps sera écoulé, cron.bat sera exécuté pour le traitement, et cron.bat le sera. exécutez php.

3. Implémenter des tâches planifiées PHP sur des serveurs non possédés (hôtes virtuels)

Si le webmaster ne possède pas son propre serveur mais loue un hôte virtuel, il ne pourra pas accéder au système serveur pour effectuer les opérations ci-dessus. Comment devrions-nous effectuer les tâches planifiées PHP à ce moment-là ? En fait, il existe plusieurs méthodes.

4. Utilisez ignore_user_abort(true) et sleep infinite loop

Dites directement une phrase au début d'un document php :

ignore_user_abort(true);

À ce moment, accédez à ceci php via l'url, même si l'utilisateur ferme le navigateur (se déconnecte), php continuera à s'exécuter sur le serveur. En utilisant cette fonctionnalité, nous pouvons réaliser une fonction très puissante, c'est-à-dire qu'elle peut être utilisée pour activer des tâches planifiées. Après activation, elle peut faire ce qu'elle veut. En fait, elle est un peu similaire aux tâches en arrière-plan.

Et sleep(n) signifie que lorsque le programme s'exécutera ici, il ne poursuivra pas son exécution temporairement, mais se reposera pendant n secondes. Si vous accédez à ce php, vous constaterez que la page prend au moins n secondes à charger. En fait, ce comportement d’attente à long terme consomme des ressources et ne peut être utilisé en grande quantité.

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

<?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,效率低。

Les tâches planifiées PHP sont une chose très intéressante. Bien que pour être honnête, il soit plus efficace d'utiliser le php.exe du système pour exécuter directement les fichiers PHP, mais pour de nombreux webmasters ordinaires, les hôtes virtuels ne peuvent pas exécuter directement les fichiers PHP natifs. programmes. Cet article ne fournit que quelques idées de solutions. Je suis en train d'étudier. Il y a beaucoup de questions ou d'expressions incorrectes. Vous pourrez développer votre propre solution grâce aux idées de cet article. discutez-en avec moi.

Recommandations associées :

Explication détaillée de l'implémentation PHP des tâches planifiées

Explication détaillée de l'implémentation PHP des tâches planifiées_PHP

Explication détaillée de la façon d'implémenter des tâches planifiées dans les compétences PHP_php

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn