8

php平滑重启nginx,彻底清除WordPress的静态缓存

 3 years ago
source link: https://zhang.ge/4730.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Jager · 12月6日 · 2014年web · wp super cache · 静态缓存 4831次已读

每一次分享技术文章,都是基于自己的痛点,基于自己的需求。这次也一样,所以分享具体方法之前,我先说一下我这次的需求与痛点:

一、需求痛点

在博客集成了代码版缓存功能之后,为了方便在前台清理页面缓存,我特意写了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执行指定命令的权限,在这个需求中,我们可以这样做:

#编辑/etc/sudoers文件:
vim /etc/sudoers
#找到 Defaults    requiretty,并注释掉:
#Defaults    requiretty
#接着在文件最后加上一行允许www帐号以root身份无密码执行reload nginx的命令:
www ALL=(root) NOPASSWD:/usr/local/nginx/sbin/nginx -s reload
#最后按下ESC退出编辑模式,键入 :x! 或 :wp! 强行保存并退出vim即可。

Ps:操作vim需要一定的Linux基础知识,不会的童鞋先脑补一下吧!

三、部署代码

①、新增平滑重启nginx的脚本

#在Linux的opt目录新增reload_nginx.sh脚本:
[root@Mars_Server ~]# vim /opt/reload_nginx.sh
#脚本内容(注意nginx的实际路径):
#!/bin/bash
/usr/bin/sudo /usr/local/nginx/sbin/nginx -s reload
#保存脚本后,赋读取和执行权限:
chmod +xr /opt/reload_nginx.sh

②、PHP代码

php执行这个脚本的代码很简单:

<?php exec(EscapeShellCmd("/opt/reload_nginx.sh")); ?>

Ps:实际上,使用 exec(/opt/reload_nginx.sh"") ; 也是完全可以的。多套了一层EscapeShellCmd是为了安全考虑(其实这里貌似没啥必要,算是掩耳盗铃吧!)。

既然知道php代码了,那么只要修改上次分享的缓存清理代码,如下新增26行和33行即可:

<?php
//缓存清理代码(实际使用,请自行修改缓存路径!)
if(isset($_POST['action'])){
if($_POST['action'] == 'delcache'){
if($_POST['page_type'] == 'single'){
$post = $_POST['post_id'];
$cachefile = "/home/wwwroot/zhang.ge/cache/zhang.ge/".$post.".html/index.html";
$cachedir = "/home/wwwroot/zhang.ge/cache/zhang.ge/".$post.".html";
} else if($_POST['page_type'] == 'page') {
$post = $_POST['slug'];
$cachefile = "/home/wwwroot/zhang.ge/cache/zhang.ge/".$post."/index.html";
$cachedir = "/home/wwwroot/zhang.ge/cache/zhang.ge/".$post;
} else if($_POST['page_type'] == 'category') {
$post = $_POST['slug'];
$cachefile = "/home/wwwroot/zhang.ge/cache/zhang.ge/".$post."/index.html";
$cachedir = "/home/wwwroot/zhang.ge/cache/zhang.ge/".$post;
} else if($_POST['page_type'] == 'home') {
$cachefile = "/home/wwwroot/zhang.ge/cache/zhang.ge/index.html";
} else {
exit();
if($_POST['page_type'] == 'home'){
if (file_exists($cachefile)) {
unlink($cachefile);
//删除缓存后平滑重启nginx:
exec(EscapeShellCmd("/opt/reload_nginx.sh"));
} else if($_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系统面板差不多,希望能给有需要的人提供一些参考,有任何相关问题记得给我留言。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK