簡體   English   中英

php正在鎖定已刪除的會話文件

[英]php is locking a deleted session file

我們的php應用程序在apache下運行,偶爾會嘗試鎖定已刪除的會話文件,這會掛起apache進程並最終耗盡進程。

證據 :

strace : flock(89, LOCK_EX                   -----stuck in flock for File Descriptor 89

然后 :

lsof,對於同樣的過程:

httpd 22161 apache 89u ... /var/lib/php/session/sess_mf7svvirg7rbu9l0m5999pm6h4 (deleted)

有關為什么會發生這種情況的任何想法? 我們可以做些什么來阻止它呢?

我遇到了與你的症狀相同的問題,除了會話文件是否被刪除是無關緊要的(也可能適合你 - 你有證據表明刪除會話文件與flock嗎?)。

就我而言,在兩個腳本之間訪問同一會話文件是一種競爭條件:

  1. /page1.php在加載時執行正常。 它包括對/background.php執行XMLHttpRequest的javascript。
  2. 當訪問/background.php ,它運行readfile(http://remote.url) ,這是一個不存在的URL。
  3. 導航到/page2.php ,腳本停止運行。 strace顯示flock(89, LOCK_EX和lsof表示它正在等待會話文件的讀/寫訪問。

在這種情況下,/ /page2.php/background.php都在同一會話文件上等待,但后者無法這樣做,因為它等待readfile()超時。 我在php_error_log得到了這個:

PHP Warning:  readfile(http://remote.url): failed to open stream: Connection timed out in […]/background.php on line […]

所以問題在於與完全不同的腳本而不是感知到的罪魁禍首。

您可以通過瀏覽php會話文件的所有打開文件來快速檢查此問題,以查看哪個httpd進程正在使用它:

$ sudo lsof | grep sess_it9q6kkvf83gcj72vu05p9fcad7
httpd     31325    apache   74u      REG                8,5       410   11634061 /var/lib/php/session/sess_it9q6kkvf83gcj72vu05pfa543
httpd     31632    apache   74uW     REG                8,5       410   11634061 /var/lib/php/session/sess_it9q6kkvf83gcj72vu05pfa543

如果兩個httpd進程正在訪問同一個會話文件,那么這可能是您的問題。 現在您可以使用strace檢查這些進程正在執行的操作,或者在我的情況下,使用apachectl fullstatus就足夠了:

$ sudo apachectl fullstatus | grep 31632
5-7  31632 0/1/1169  _ 0.05 6     30692 0.0  0.02  3.45 111.222.333.444 www.example.com.com     /background.php

是否有任何巨大的(客戶端)需要刪除會話文件? 你不應該這樣做。 PHP本身實現了一個垃圾收集機制來刪除已解散的會話文件。 它將比使用PHP自己編寫的任何其他內容更有效

您可以使用:

  1. session_destroy - 銷毀注冊到會話的所有數據
  2. session_unset - 釋放所有會話變量

並再次執行session_start()。

在這里查看更多。

更新:

PHP是一個非常干凈的腳本引擎,它不會在您的系統上留下垃圾! 達到會話超時后會自動刪除會話文件。 session-timeout可能是您的系統的情況我認為如此。 因此,如果超時設置為20分鍾,則文件將在上次訪問后20分鍾刪除。 對於cookie也是如此。 每次請求頁面時,cookie-ttl設置為現在+ 20分鍾。

查看一些配置指令 可能性是您已將gc_maxlifetime設置為非常高的值,並且它們根本沒有達到“到期”限制以自動收集。 您應該檢查您的應用程序,以確保它們沒有在運行時為會話設置設置奇怪的值(使用ini_set() )。

PHP有一個內部算法,在session_start()上運行,決定它是否應該執行垃圾清理運行並刪除舊的會話文件。 出於性能原因,我認為每次運行的默認機會是1%,因此平均每100個session_start()調用將啟動一次垃圾收集例程。 如果您發現這還不夠,可以將gc_divisor設置提高到高於1的值。

不知道為什么你的情況。

這個問題得到了一些好的建議......

您是否嘗試重新安裝環境或遷移到其他服務器? 如果你否決了默認會話處理程序並使用fopen($ file,'w')而不是fopen($ file,'x'),它會工作嗎?

此外,基於數據庫實現會話處理程序的解決方法,例如,有一百萬左右的指南來設置“php和mysql會話處理程序”。

對於您的情況,這可能更像是一種解決方法,但為什么不將會話從文件系統遷移到數據庫呢?

你可以在這里獲得更多信息http://php.net/manual/en/function.session-set-save-handler.php

你有沒有嘗試過閱讀這兩個漏洞?

https://bugs.php.net/bug.php?id=47640 https://bugs.php.net/bug.php?id=32092

嘗試調用session_write_close()(丑陋的解決方法)作為最后一行或升級PHP。

暫無
暫無

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

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