Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 确保作业已执行的最佳方法_Php_Amazon Web Services_Ubuntu_Redis_Cron - Fatal编程技术网

Php 确保作业已执行的最佳方法

Php 确保作业已执行的最佳方法,php,amazon-web-services,ubuntu,redis,cron,Php,Amazon Web Services,Ubuntu,Redis,Cron,我有一个在服务器中连续运行的脚本,在本例中是一个PHP脚本,如: php路径/to/my/index.php 它被执行了,当它完成时,它被执行了一次又一次,永远 我正在寻找最好的方式来通知,如果该事件停止运行(已执行) 它停止被调用的原因有很多,比如服务器内存、新部署、人为错误。。。等等 我只想得到通知(电子邮件,短信,slack…)如果脚本在一定时间内没有执行(比如1小时,1天等等) 我的服务器是住在AWS的Ubuntu 一个想法: 我在考虑在REDIS/MEMCACHED/ETC中使用带有T

我有一个在服务器中连续运行的脚本,在本例中是一个PHP脚本,如:

php路径/to/my/index.php

它被执行了,当它完成时,它被执行了一次又一次,永远

我正在寻找最好的方式来通知,如果该事件停止运行(已执行)

它停止被调用的原因有很多,比如服务器内存、新部署、人为错误。。。等等

我只想得到通知(电子邮件,短信,slack…)如果脚本在一定时间内没有执行(比如1小时,1天等等)

我的服务器是住在AWS的Ubuntu

一个想法: 我在考虑在REDIS/MEMCACHED/ETC中使用带有TTL的索引。每次脚本运行时,更新该索引的TTL


如果脚本在该TTL时间内停止工作,则此索引将过期。我只需要一种在到期时触发通知的方法,但看起来REDIS/MEMCACHED并没有为此做好准备

register\u shutdown\u函数可能会有所帮助,但可能不会


我不能说我见过需要在PHP中无限期运行的脚本。也许有另一种方法可以解决您所追求的问题?

更新-根据您的redis想法,我将查看键空间通知

我没有测试过这个想法,因为我实际上不是redis用户。但也可以订阅以捕获过期事件(可能来自另一台服务器?)并生成通知


没有“最好”的方法可以做到这一点。最终,最有效的方法将归结为您支持的特定工作流

tl;dr版本:找到成功的要素并记录最近发生的时间。在另一个脚本中将其用于通知触发器

长版本:

也就是说,使用单独的观察者进行持久存储可能是最直接的方法。记录上次成功运行,然后每隔一段时间用cron作业检查一次

对于这样的脚本,我通常会监视所讨论的脚本生成的退出代码或日志。这将错误通知过程与脚本本身隔离开来,因此脚本中的缺陷(希望)不会妨碍通知

例如,假设我们有一个脚本来调用实际的脚本。。。(这是非常未经测试的伪代码)

注意:上面显示的特定方法有一些注意事项。脚本可能以非致命的方式失败,如果您不检查脚本,本例可能会将其记录为成功运行。例如,权限错误会导致警告,但脚本仍会运行整个过程,并正常退出,而不会使用特定的返回代码调用
exit
。我们这里的示例调用程序会将其记录为成功运行,即使它不是


另一个选项是记录脚本的成功,只检查调用程序是否存在错误。

如果在register\u shutdown\u函数中重新启动脚本,则在内存或超时问题或大多数情况下会触发错误。但我仍然会将一些数据存储在持久性存储中的某个位置,比如说,可能是脚本最后一次启动和结束的时候,或者它是否当前正在运行,然后可能依赖另一个脚本(可能是cron作业,甚至是每个页面加载)来检查脚本是否可能当前正在运行,如果不是,就发送一封电子邮件。这是cron作业吗?不,不是,这是有原因的。谢谢,但我不想依靠另一个“cron作业”来监视初始作业,因为它可能会由于与原始作业相同的原因而无法执行。抱歉,我在PHP进程本身中将内存不足解释为内存不足,不是整个服务器。(假设单独的进程隔离了观察者/通知者,但不是整个系统)嗯。。。在这种情况下,您可以在成功运行时向外部服务报告。除此之外,这个过程大致相当。对不起,在尝试回答之前,我可能应该询问有关您的设置和具体限制的更多详细信息。如果您有一个“最佳”案例解决方案的具体列表,您可能希望将其添加到您的问题中。无论如何,更新了您的redis方法,但我不确定它是否可行,因为我对redis有点不熟悉。在询问之前我已经看到了,但正如您所看到的,在这一阶段它不可靠:(我也在查看DynamoDB streams,它具有类似的触发器删除功能(用于TLL过期)…啊,这太不幸了。我仍然认为对您的问题进行一点扩展是有意义的。其他细节的一些示例:您希望您的通知方法保留哪种类型的失败?整个主机关闭,或者只是脚本没有正确完成,等等。您愿意使用第三方监控解决方案吗?(例如,带有自定义指标的AWS CloudWatch)有任何特殊注意事项吗?没有
cron
绝对是一个特殊注意事项,尤其是对于基于时间的通知。
<?php
//Run and record.
exec("php path/to/my/index.php", $output, $return_code);
//$return_code will be 255 on fatal errors. You can use other return codes
//with exit in your called script to report other fail states.
if($return_code == 0) {
  file_put_contents('/path/to/folder/last_success.txt', time());
} else {
  file_put_contents('/path/to/folder/error_report.json', json_encode([
    'return_code' => $return_code,
    'time' => time(),
    'output' => implode("\n", $output), 
      //assuming here that error output isn't silently logged somewhere already.
  ], JSON_PRETTY_PRINT));
}
<?php
//Notify us immediately on failure maybe?
//If you have a lot of transient failures it may make more sense to
//aggregate and them in a single report at a specific time instead.
if(is_file('/path/to/folder/error_report.json')) {
  //Mail details stored in JSON here.

  //rename file so it's recorded, but we don't receive it again.
  rename('/path/to/folder/error_report.json', '/path/to/folder/error_report.json'.'-sent-'.date('Y-m-d-H-i-s'));
} else {
  if(is_file('/path/to/folder/last_success.txt')) {
    $last_success = intval(file_get_contents('/path/to/folder/last_success.txt'));
    if(strtotime('-24 hours') > $last_success) {
      //Our script hasn't run in 24 hours, let someone know.
    }
  } else {
    //No successful run recorded. Might want to put code here if that's unexpected.
  }
}