禁用了傳說中的PHP危險函數之后,Laravel的定時任務不能執行了?

雖然已是 2018 年,但網上依然流傳著一些「高危 PHP 函數,請一定要禁用!」的標題黨文章(搜索關鍵字:一些需要禁用的PHP危險函數)。

這些文章的內容簡單直接,給出 php.inidisable_functions 的配置(包含一大堆函數),說這些函數十分危險,一定要禁用,有的內容甚至和7、8年前一模一樣,被開發者們奉為秘籍,薪火相傳。

禁用危險函數在理論上是可以加強安全性,但這種做法就好比做飯時害怕用菜刀切菜傷到自己而改用手撕。搞安全一定要重視對入口的控制,而不是自廢武功,因為禁用某些函數會導致某些需求很難、甚至不能實現。

謝遜后來自廢武功…

舉個例子。

比如 Laravel 中定時任務功能的底層使用了 Symfony/Process,其中就依賴 proc_open 函數來執行命令(及其一系列函數),如果被禁用,定時任務就沒法用了。

這里還有個小坑。

朋友本來有一個穩定運行的 Laravel 項目,但某天為了加強安全性,就在 php.ini 里禁用了一堆函數(網上找來的),其中就包含 proc_open 這些。后來他突然發現所有的定時任務都沒有跑了,Laravel 日志和 PHP 錯誤日志也沒有任何異常。后來他猜測應該和函數禁用行為有關,于是還原了配置,可是此時定時任務還是沒有運行。

這里的坑就在于他的所有定時任務都設置了 withoutOverlapping。當開啟這個設置之后,Laravel 在運行任務時會設置排他鎖:開始的時候檢查有沒有上鎖,有鎖則忽略執行,否則就上鎖,執行命令,執行結束之后解鎖。上鎖當然沒問題,可是執行掛了(這里應該是靜默失敗,普通異常是會被捕捉然后解鎖的),后面就自然沒有解鎖,所以配置恢復之后,開始執行時發現鎖依然存在,是不會實際執行的。

怎么解決呢?Laravel 的鎖使用的系統默認 Cache,所以只需要去對應 Cache 的 driver 中刪掉鎖的緩存文件就好了,或者等待鎖過期之后也行(5.5 默認是 24 小時)。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容