草庐IT

php sleep 功能奇怪的行为

coder 2024-04-19 原文

我们继承了一个平台,该平台有一个 crobjob,每分钟使用不同的参数将本地 php 脚本 curl 三次 (curl -s -o --url https://localhost/myscript.php?option= XYZ -k).该脚本运行大约 1 分钟,并且其可能具有相同选项的多个实例会重叠一段时间。脚本根据给定的选项记录在不同的文件中,并且每个日志都以脚本启动时的时间戳开头,因此它充当实例标识符。

脚本有这个骨架:

<?php

$option=XYZ;
$scriptId = time();
$file = "log_$option.txt";

file_put_contents($file,"\n$scriptId: Start\n",FILE_APPEND);
session_start();

$expires = time()+60;
file_put_contents($file,"\n$scriptId: Expires at $expires\n",FILE_APPEND);

while(time()<$expires){

    file_put_contents($file,"\n$scriptId: Not expired at ".time()."\n",FILE_APPEND);

    switch($option){
        case X:
            do_db_stuff();
            break;
        ...
    }

    file_put_contents($file,"\n$scriptId: Will sleep at ".time()."\n",FILE_APPEND);
    sleep(13);
    file_put_contents($file,"\n$scriptId: Woke up at ".time()."\n",FILE_APPEND);
}

file_put_contents($file,"\n$scriptId: Finished at ".time()."\n",FILE_APPEND);

通常这个脚本运行良好(即使它们在实例 A 最后一次休眠和实例 B 启动时重叠)但有时我们有两个问题可以通过日志确认:

  • 有时它会休眠不到 13 秒(a 时间长短不一,始终少于 13 分钟);
  • 有时脚本会停止(在“Will sleep”之后不再记录,我们可以验证没有正在执行数据库操作)。 [在编辑 2 中对此进行更新]

我们已经调查了可能的原因,但找不到任何原因:

  • php max_execution_time 设置为 240 秒并且脚本从不 需要超过一分半钟;
  • sleep 文档说它是针对每个 session 的,但是 curl 没有使用 cookie,所以它在每个实例中应该是不同的 session (而且如果它使用相同的 session ,它总是会阻塞,因为我们总是执行三个脚本实例,它没有);
  • 托管技术团队表示服务器中都没有错误 错误日志也不在 php 错误日志中的时间戳中,这些问题所在 发生。

我无法随意重现这些问题,但它们至少每天发生一次。 我想知道什么会干扰 sleep 行为?如何检测或修复它?

附加信息:

  • linux系统
  • MySQL 5.5
  • Apache
  • php 5.3
  • php max_execution_time 设置为 240

编辑 1: 澄清一下:实际上我们有 3 个选项,因此它写入 3 个日志文件,每个选项一个。在任何给定时间,每个选项最多可以运行两个实例(同一选项的每个实例重叠少量时间)。

Edit2:根据@Jan 的建议,我在 sleep 函数结果中添加了日志。该脚本已经停止了该日志:

[2016-01-05, 13:11:01] Will sleep at 2016-01-05, 13:11:29
[2016-01-05, 13:11:01] Woke up at 2016-01-05, 13:11:37 with sleep return 5
[2016-01-05, 13:11:01] Not expired at 2016-01-05, 13:11:37
[2016-01-05, 13:11:01] Will sleep at 2016-01-05, 13:11:37
[2016-01-05, 13:11:01] Woke up at 2016-01-05, 13:11:38 with sleep return 13
... no more log from instance [2016-01-05, 13:11:01] ...
[2016-01-05, 13:12:01] Start

根据 sleep 文档:

If the call was interrupted by a signal, sleep() returns a non-zero value. On Windows, this value will always be 192 (the value of the WAIT_IO_COMPLETION constant within the Windows API). On other platforms, the return value will be the number of seconds left to sleep.

因此根据文档和日志,sleep 似乎由于中断而被缩短。

我怎么知道是什么中断导致了这个(pcntl_signal?),它是从哪里来的,有什么办法可以避免吗?

Edit3:我添加了代码来处理带有 pcntl_signal 的信号(尝试从信号 1 到 255 注册)并记录它们,问题仍然存在,但日志仍然是空的。

最佳答案

您可以使用 pcntl_signal 定义信号处理程序。

使用这些处理程序,您可以在发生中断时进行记录。但是据我所知,您无法检测到它的来源。

您还可以使用 pcntl_alarm 来处理延迟的作业。 Check PHP Manual - PCNTL Alarm

关于php sleep 功能奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34610807/

有关php sleep 功能奇怪的行为的更多相关文章

  1. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  2. ruby-on-rails - Cucumber 是否只是 rspec 的包装器以帮助将测试组织成功能? - 2

    只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您

  3. ruby - Ruby gsub 替换中的行为不一致? - 2

    两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio

  4. ruby-on-rails - Ruby 中意外的大小写行为 - 2

    我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。

  5. ruby - 使对象的行为类似于 ruby​​ 中并行分配的数组 - 2

    假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje

  6. ruby - 了解在 Ruby 中与 lambda 一起使用的 inject 行为 - 2

    我经常将预配置的lambda插入可枚举的方法中,例如“map”、“select”等。但是“注入(inject)”的行为似乎有所不同。例如与mult4=lambda{|item|item*4}然后(5..10).map&mult4给我[20,24,28,32,36,40]但是,如果我制作一个2参数lambda用于像这样的注入(inject),multL=lambda{|product,n|product*n}我想说(5..10).inject(2)&multL因为“inject”有一个可选的单个初始值参数,但这给了我......irb(main):027:0>(5..10).inject

  7. ruby-on-rails - rails 功能测试 - 2

    在Rails自动生成的功能测试(test/functional/products_controller_test.rb)中,我看到以下代码:classProductsControllerTest我的问题是:方法调用products()在哪里/如何定义?products(:one)到底是什么意思?看代码,大概意思是“创建一个产品”,但是它是如何工作的呢?注意我是Ruby/Rails的新手,如果这些是微不足道的问题,我深表歉意。 最佳答案 如果您查看test/fixtures文件夹,您会看到一个products.yml文件。这是在您创建

  8. ruby-on-rails - 浮点乘法的 Ruby 奇怪问题 - 2

    有没有人用ruby​​解决这个问题:假设我们有:a=8.1999999我们想将它四舍五入为2位小数,即8.20,然后乘以1,000,000得到8,200,000我们是这样做的;(a.round(2)*1000000).to_i但是我们得到的是8199999,为什么?奇怪的是,如果我们乘以1000、100000或10000000而不是1000000,我们会得到正确的结果。有人知道为什么吗?我们正在使用ruby​​1.9.2并尝试使用1.9.3。谢谢! 最佳答案 每当你在计算中得到时髦的数字时使用bigdecimalrequire'bi

  9. ruby-on-rails - 功能测试 Authlogic? - 2

    在我的一些Controller中,我有一个before_filter检查用户是否登录?用于CRUD操作。application.rbdeflogged_in?unlesscurrent_userredirect_toroot_pathendendprivatedefcurrent_user_sessionreturn@current_user_sessionifdefined?(@current_user_session)@current_user_session=UserSession.findenddefcurrent_userreturn@current_userifdefine

  10. ruby - 奇怪的 ruby​​ for 循环行为(为什么这样做有效) - 2

    defreverse(ary)result=[]forresult[0,0]inaryendresultendassert_equal["baz","bar","foo"],reverse(["foo","bar","baz"])这行得通,我想了解原因。有什么解释吗? 最佳答案 如果我使用each而不是for/in重写它,它看起来像这样:defreverse(ary)result=[]#forresult[0,0]inaryary.eachdo|item|result[0,0]=itemendresultendforainb基本上就

随机推荐