[英]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開始時重疊)但有時我們可以通過日志確認兩個問題:
我們已經研究了可能的原因但找不到任何原因:
max_execution_time
設置為240秒,腳本永遠不會超過一分半鍾; sleep
文檔說它是每個會話但curl不使用cookie所以它應該是每個實例中的不同會話(並且如果它使用相同的它總是會阻止,因為我們總是執行三個腳本實例,它不會) ; 我不能隨意重現這些問題,但它們每天至少發生一次。 我想知道的是什么可以干擾睡眠行為? 我該如何檢測或修復它?
附加信息:
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.