1. 程式人生 > >php平滑重啟nginx,徹底清除WordPress的靜態快取

php平滑重啟nginx,徹底清除WordPress的靜態快取

每一次分享技術文章,都是基於自己的痛點,基於自己的需求。這次也一樣,所以分享具體方法之前,我先說一下我這次的需求與痛點:

一、需求痛點

在部落格集成了程式碼版快取功能之後,為了方便在前臺清理頁面快取,我特意寫了ajax 清理快取的功能相關文章)。這個功能寫好之後確實可以正常工作。

但是,為了讓網站載入速度提升到極致,我還在 nginx 裡面加了類似於 WP Super Cache 的 mod_rewrite 機制:當存在頁面快取時,會繞過 PHP 解析,而直接調取快取在前臺展示。

這樣就發現了一個問題:當我在前臺點選快取清理後,後臺的頁面快取檔案確實是刪除了,但是 nginx 卻在記憶體裡面快取了一份!!從而導致一段時間內怎麼重新整理頁面,展示的依然是快取內容!這樣一來,不管是我還是使用者,點選前臺這個清理按鈕根本就不能實時看到效果,明顯就雞肋了!

我發現這個問題的做法是,點選按鈕刪除快取,然後進入 Linux 系統去 reload 一下 nginx,才能徹底重新整理快取!我勒個去,每次我除錯程式碼的時候,真心能把人累死(雖然我可以關閉快取功能,但是我就是要享受一下自己寫的清理功能嘛!)。

需求都有了,怎能讓技術成為瓶頸?

所以,根據以上需求,很容易得出一個解決方案:當點選前臺清理按鈕時,php 先刪除快取檔案,然後 reload 平滑重啟 nginx 就可以實現徹底清除快取了!

測試了半天,發現難點是 php 如何才能執行 Linux 命令。經過不斷測試,終於搞定這個問題,下面開始分享!

二、執行許可權

php 執行 Linux 命令有幾個前提條件:

①、php 必須開放一些執行外部命令的函式,比如 exec()、system()等;

②、必須賦予 WEB 啟動帳號(比如 www 帳號)執行特殊命令(比如 .../nginx -s reload)的許可權。

對於問題 ①:

i. 修改 php 配置檔案 php.ini,先找到 safe_mode 配置,確認 safe_mode=off,即關閉 php 安全模式(lnmp 一鍵安裝包預設已經是關閉的了);

ii. 繼續找到 disable_functions 配置,將其中的 exec 刪除,即允許執行 exec()函式;

ii. 最後過載 php-fpm 或 php 即可生效,比如 lnmp 環境可以執行 service php-fpm reload 命令。

Ps:開啟 exec 函式存在被惡意注入的風險,不過我這種小部落格就沒什麼好懼怕的,況且我的備份及防護都很完善!

對於問題②:

我們需要在 Linux 中賦予 WEB 帳號使用 sudo 執行指定命令的許可權,在這個需求中,我們可以這樣做:

Shell
12345678910 #編輯/etc/sudoers檔案:vim/etc/sudoers#找到 Defaults    requiretty,並註釋掉:#Defaults    requiretty#接著在檔案最後加上一行允許www帳號以root身份無密碼執行reload nginx的命令:www ALL=(root)NOPASSWD:/usr/local/nginx/sbin/nginx-sreload#最後按下ESC退出編輯模式,鍵入 :x! 或 :wp! 強行儲存並退出vim即可。

Ps:操作 vim 需要一定的 Linux 基礎知識,不會的童鞋先腦補一下吧!

三、部署程式碼

①、新增平滑重啟 nginx 的指令碼

Shell
123456789 #在Linux的opt目錄新增reload_nginx.sh指令碼:[root@Mars_Server~]# vim /opt/reload_nginx.sh #指令碼內容(注意nginx的實際路徑):#!/bin/bash/usr/bin/sudo/usr/local/nginx/sbin/nginx-sreload#儲存指令碼後,賦讀取和執行許可權:chmod+xr/opt/reload_nginx.sh

②、PHP 程式碼

php 執行這個指令碼的程式碼很簡單:

PHP
1 <?phpexec(EscapeShellCmd("/opt/reload_nginx.sh"));?>

Ps:實際上,使用 exec(/opt/reload_nginx.sh"") ; 也是完全可以的。多套了一層 EscapeShellCmd 是為了安全考慮(其實這裡貌似沒啥必要,算是掩耳盜鈴吧!)。

既然知道 php 程式碼了,那麼只要修改上次分享的快取清理程式碼,如下新增 26 行和 33 行即可:

PHP
1234567891011121314151617181920212223242526272829303132333435363738394041 <?php//快取清理程式碼(實際使用,請自行修改快取路徑!)if(isset($_POST['action'])){if($_POST['action']=='delcache'){if($_POST['page_type']=='single'){$post=$_POST['post_id'];$cachefile="/home/wwwroot/zhangge.net/cache/zhangge.net/".$post.".html/index.html";$cachedir="/home/wwwroot/zhangge.net/cache/zhangge.net/".$post.".html";}elseif($_POST['page_type']=='page'){$post=$_POST['slug'];$cachefile="/home/wwwroot/zhangge.net/cache/zhangge.net/".$post."/index.html";$cachedir="/home/wwwroot/zhangge.net/cache/zhangge.net/".$post;}elseif($_POST['page_type']=='category'){$post=$_POST['slug'];$cachefile="/home/wwwroot/zhangge.net/cache/zhangge.net/".$post."/index.html";$cachedir="/home/wwwroot/zhangge.net/cache/zhangge.net/".$post;}elseif($_POST['page_type']=='home'){$cachefile="/home/wwwroot/zhangge.net/cache/zhangge.net/index.html";}else{exit();}if($_POST['page_type']=='home'){if(file_exists($cachefile)){unlink($cachefile);//刪除快取後平滑重啟nginx:exec(EscapeShellCmd("/opt/reload_nginx.sh"));}}elseif($_POST['page_type']!='null'){if(file_exists($cachefile)){unlink($cachefile);rmdir($cachedir);//刪除快取後平滑重啟nginx:exec(EscapeShellCmd("/opt/reload_nginx.sh"));}}else{exit();}}exit();}?>

Ps:若對以上程式碼有任何疑問,請務必參考上一篇相關文章

全部完成之後,現在在前臺使用快取清理功能,將會先刪除快取檔案,然後平滑重啟 nginx,從而真正實現在純靜態的前臺實時清理快取,顯示最新內容!

四、寫在最後

這篇教程算是我這種強迫症&發騷友學習實驗之作,而且整個教程並未過多考慮安全問題。所以,如果不是和我這種既不在意被人攻擊,又清楚箇中原理的人,還是不建議做這種強迫症設定(實際上也就是解禁了 exec 函式存在隱患而已)!

總之,這篇文章分享的方案,還是有一定的參考價值的,根據本文思路,就可以實現在 WEB 介面任意操作伺服器了,其實也就和大部分站長用的 Linux 系統面板差不多,希望能給有需要的人提供一些參考,有任何相關問題記得給我留言。