簡體   English   中英

php睡眠功能奇怪的行為

[英]php sleep function odd behaviour

我們繼承了一個平台,它有一個crobjob,每分鍾用不同的參數卷曲一個本地php腳本三次( 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秒(可變的時間長度,總是小於13);
  • 有時腳本會停止(在“Will sleep”之后不再記錄,我們可以驗證沒有db內容正在完成)。 [編輯2中的更新]

我們已經研究了可能的原因但找不到任何原因:

  • php max_execution_time設置為240秒,腳本永遠不會超過一分半鍾;
  • sleep文檔說它是每個會話但curl不使用cookie所以它應該是每個實例中的不同會話(並且如果它使用相同的它總是會阻止,因為我們總是執行三個腳本實例,它不會) ;
  • 托管技術團隊表示,在發生這些問題的時間戳中,服務器錯誤日志和php錯誤日志中都沒有錯誤。

我不能隨意重現這些問題,但它們每天至少發生一次。 我想知道的是什么可以干擾睡眠行為? 我該如何檢測或修復它?

附加信息:

  • linux系統
  • mysql 5.5
  • 阿帕奇
  • php 5.3
  • php max_execution_time設置為240

編輯1:只是為了澄清:實際上我們有3個選項,因此它寫入3個日志文件,每個選項一個。 在任何給定時間,每個選項最多可以運行兩個實例(相同選項的每個實例重疊一小段時間)。

Edit2:根據@Jan建議,我將日志添加到睡眠功能結果中。 腳本已經停止了一次該日志:

[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文檔:

如果呼叫被信號中斷,則sleep()返回非零值。 在Windows上,此值始終為192(Windows API中WAIT_IO_COMPLETION常量的值)。 在其他平台上,返回值將是剩余的休眠秒數。

因此,根據文檔和日志,似乎由於中斷導致sleep被縮短。

我怎么知道是什么中斷導致這個( pcntl_signal ?),它來自哪里,有什么方法可以避免它?

編輯3:我添加了用pcntl_signal處理信號的代碼(嘗試從信號1到255注冊)並記錄它們,問題仍然發生但日志仍為空。

您可以使用pcntl_signal定義信號處理程序。

使用這些處理程序,您可以在發生中斷時進行記錄。 但AFAIK你無法察覺它來自哪里。

您也可以使用pcntl_alarm來處理延遲的工作。 檢查PHP手冊 - PCNTL警報

鑒於你的堆棧,中斷信號可能來自apache。 根據Apache在堆棧上與PHP通信的方式,Apache配置中有幾個超時選項可以通過腳本執行進行推斷。

如果你的cron在localhost上調用curl,也許它可以直接調用PHP文件,所以避免使用apache進程來保持請求活着? 您必須使用max_execution_time值編輯專用的CLI php.ini文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM