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 执行指定命令的权限,在这个需求中,我们可以这样做:

#编辑/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/zhangge.net/cache/zhangge.net/".$post.".html/index.html";
            $cachedir = "/home/wwwroot/zhangge.net/cache/zhangge.net/".$post.".html";
        } else if($_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;
        } else if($_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;
        } else if($_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"));
            }
        } 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 系统面板差不多,希望能给有需要的人提供一些参考,有任何相关问题记得给我留言。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java帮帮-微信公众号-技术文章全总结

Web-第二十七天 SVN使用【悟空教程】

为保障团队开发过程中人员沟通各方面成本的降低,必须使用一种有效的方式减少沟通环节,提高开发效率,对资源的共享进行管理。

1781
来自专栏ChaMd5安全团队

文件上传漏洞的一些总结

0x00 前言 在跟p猫的py交易后,写下了这篇文章,根据之前写文章后表哥给予的一些改进建议,尽量在这篇文章中写得更加详细。因为本人技术水平有限菜的要死,所以...

8566
来自专栏邹立巍的专栏

Linux 的进程间通信:管道

管道,英文为 pipe 。这是一个我们在学习 Linux 命令行的时候就会引入的一个很重要的概念。管道是UNIX 环境中历史最悠久的进程间通信方式。本文主要说明...

9422
来自专栏IT大咖说

MongoDB技术分享:WiredTiger存储引擎

内容来源:2018 年 10 月 27 日,MongoDB中文社区联席主席郭远威在“2018年MongoDB中文社区 广州大会”进行《WiredTiger存储引...

1902
来自专栏源哥的专栏

基于linux的嵌入IPv4协议栈的内容过滤防火墙系统(4)-包过滤模块和内容过滤模块

Netfilter是linux2.4内核实现数据包过滤/数据包处理/NAT等的功能框架。它在网络上设置了五个钩(hook),我们可以在我们所需要的一个钩对数据...

902
来自专栏F-Stack的专栏

F-Stack Q&A 第一期

Q1:F-Stack有中断模式吗,有计划支持吗?在计算密集型的应用中,轮询模式会占用更多的CPU资源? A1:F-Stack暂时只支持轮询模式,后续会支持中断+...

7335
来自专栏架构师之路

mysql-proxy数据库中间件架构 | 架构师之路

一、mysql-proxy简介 mysql-proxy是mysql官方提供的mysql中间件服务,上游可接入若干个mysql-client,后端可连接若干个my...

4976
来自专栏PHP实战技术

一个查看框架源码,一个查找错误的小工具,你用了吗?

日常开发中还在一直var_dump?exit()?,是不是很不便捷,很不方便?今天小梦就给大家讲讲在PHP开发中(划重点:PHP开发,当然其他语言开发也是有类似...

1504
来自专栏耕耘实录

DNS主从服务器中域(zone)文件类型不一致问题的解决方法

版权声明:本文为耕耘实录原创文章,各大自媒体平台同步更新。欢迎转载,转载请注明出处,谢谢

1234
来自专栏从零开始学自动化测试

git+jenkins在windows机器上新建一个slave节点

前言 我们在跑自动化项目的时候,希望有单独的测试机能跑自动化项目,并且能集成到jenkins上构建任务。如果公司已经有jenkins环境了,那无需重新搭建。 只...

4386

扫码关注云+社区

领取腾讯云代金券