背景
通常,在cli下運行的常駐後臺PHP進程,可能異常退出,比如php執行過程中出現的致命錯誤,或被 kill 命令手動殺死等。如下面的php代碼:
1 2 3 4 5 6 7 8 9 |
|
查錯
我們使用register_shutdown_function可以跟蹤到底是什麼錯誤導致的進程退出。(想更多瞭解register_shutdown_function,請查看博文 妙用php中的register_shutdown_function和fastcgi_finish_request)加入了錯誤捕捉代碼。如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
可是,php當進程再次退出時,在日誌中並沒有記錄任何信息。說明register_shutdown_function方法根本沒有執行。是什麼導致register_shutdown_function方法沒有運行呢?在php的官方文檔中又這樣一個註釋:
Shutdown functions will not be executed if the process is killed with a SIGTERM or SIGKILL signal. While you cannot intercept a SIGKILL, you can use pcntl_signal() to install a handler for a SIGTERM which uses exit() to end cleanly.
註釋的意思是當php進程獲得SIGTERM和SIGKILL信號而退出時,是不執行register_shutdown_function方法的。可以使用pcntl_signal()方法來捕獲信息,並調用相應的處理方法。
好,如何檢測是信號導致我們的php進程退出的呢?我們加入如下代碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
過一段時間,發現php進程退出了,日誌中出現瞭如下日誌信息:
2014-11-23 18:30:06 exit signo[14]
2014-11-23 18:30:06 [error]is_end[no]
看來是sigalarm信號導致php進程退出了。這個信號是可以捕獲和處理的。kill 命令會發出sigalarm信號。最終的代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
|
這時再kill 進程,在日誌中就發現了alarm相關的日誌,但是php進程依然在。
PS:以上代碼如果用kill -9命令殺死(SIGKILL信號),還是會退出的。也就是說SIGKILL信號是無法捕獲的。
參考
http://blogread.cn/it/article/7256?f=wb_blogread
PS:
error_get_last() 函數獲得最後發生的錯誤。
該函數以數組的形式返回最後發生的錯誤。如果沒有錯誤發生則返回 NULL。
返回的錯誤數組包含 4 個鍵名和鍵值:
- [type] - 錯誤類型
- [message] - 錯誤消息
- [file] - 發生錯誤所在的文件
- [line] - 發生錯誤所在的行