[英]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
嗎?)。
就我而言,在兩個腳本之間訪問同一會話文件是一種競爭條件:
/page1.php
在加載時執行正常。 它包括對/background.php
執行XMLHttpRequest的javascript。 /background.php
,它運行readfile(http://remote.url)
,這是一個不存在的URL。 /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自己編寫的任何其他內容更有效 。
您可以使用:
並再次執行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.