Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4175546
  • 博文数量: 291
  • 博客积分: 8003
  • 博客等级: 大校
  • 技术积分: 4275
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-30 18:28
文章分类

全部博文(291)

文章存档

2017年(1)

2013年(47)

2012年(115)

2011年(121)

2010年(7)

分类: 系统运维

2012-07-21 14:34:53

我公司的一个客户在国外访问测试网站比较麻烦,因此我在一台机器上安装了一个nginx,并且使用nginx的proxy_cache模块做缓存服务器,由于由于修改比较多,每次使用ngx_cache_purge清除cache只能清除几个url,没有很好的办法去清除某个目录的缓存。我研究了nginx的缓存文件格式,发现可以从中提取出url出来,如下图所示,url是以"KEY:"开头以0x0A结尾
我写了一个程序能够实现
1.提交一批url进行清除对应的cache
2.提交一批url目录可以清除包含这些目录的url,若是提交域名可以清除整站
3.查看某个目录下的缓存文件是否缓存上
4.可以添加多个站点
需要县安装ngx_cache_purge
代码如下

点击(此处)折叠或打开

  1. <?php
  2. /*
  3.  * 作者:yifangyou
  4.    日期:2012-07-21 14:43:00
  5.    功能:按照多个目录或者多个URL的方式,清除nginx的cache,或者查看nginx cache 缓存
  6.    要求:nginx + ngx_cache_purge
  7.  */
  8.    //代理服务器的ip
  9.   $proxyIp="127.0.0.1";
  10.   //代理服务器端口
  11.     $proxyPort=80;
  12.     //代理服务器的缓存目录
  13.     $cacheDir="/opt/proxy_cache_dir/";
  14.     $proxySites=array(
  15.     //用户访问的域名 => 被代理的实际网站的域名,若是都是80的话就是一样即可
  16.      ""=>""
  17.     );
  18. //输出文件
  19. $output="";    
  20. $result=array();
  21. $filedirs = array();
  22. //只查看缓存文件,不清除
  23. if($_POST["view"]){
  24.          $accessSite=$_POST["accessSite"];
  25.      $proxySite=$proxySites[$accessSite];
  26.          $clearUrls=array();
  27.          $clearUrls=explode ("\n",$_POST["dirs"]);
  28.          if($$proxySite){
  29.                  foreach($ds as $d){
  30.                          $d=str_replace($accessSite, $proxySite,$d);
  31.                          $clearUrls[]=$d;
  32.                  }
  33.          }
  34.          scan_dir($cacheDir);
  35.          $cacheurls = array();
  36.          foreach($filedirs as $filename){
  37.                 if(!is_file($filename)){
  38.                         continue;
  39.                 }
  40.                 $cacheUrl=getUrlFromCacheFile($filename);
  41.                                 if(count($clearUrls)){
  42.                                     $cacheurls[]=$cacheUrl;
  43.                                     continue;
  44.                                 }
  45.                 foreach($clearUrls as $clearUrl){
  46.                   $clearUrl=str_replace($accessSite, $proxySite,$clearUrl);
  47.                   $pos=strpos($cacheUrl,$clearUrl);
  48.                   // echo "$cacheUrl,$clearUrl,$pos
    ";

  49.                   //比较和
  50.                   if($pos===0){
  51.                      $cacheurls[]=$cacheUrl;
  52.                      break;
  53.                    }
  54.                 }
  55.         }

  56. }else //清除一批URL
  57. if($_POST["urls"]){
  58.     $accessSite=$_POST["accessSite"];
  59.     $proxySite=$proxySites[$accessSite];
  60.     $output.="
    执行结果
\n
\n";
  •     $urls=explode ("\n",$_POST["urls"]);
  •     foreach($urls as $url2){
  •         $url=trim($url2);
  •         $output.="------------------------$url start-----------------------------\n";
  •         $pos = strpos($url, $accessSite);
  •         if ($pos !== false && $pos==0) {
  •             $url=str_replace($accessSite, $proxySite,$url);
  •             if(purge($proxyIp,$proxyPort,$url)==0){
  •                 $result[$url2]=0;
  •             }else{
  •                 $result[$url2]=1;
  •             }
  •         }else{
  •             $output.="skip $url\n";
  •             $result[$url2]=-1;
  •         }
  •         $output.="------------------------$url end -----------------------------\n";
  •     }
  •     $output.="
  • \n";
  • }else//清除某个目录下的所有文件
  • if($_POST["dirs"]){
  •     $accessSite=$_POST["accessSite"];
  •     $proxySite=$proxySites[$accessSite];
  •     $clearUrls=array();
  •     $clearUrls=explode ("\n",$_POST["dirs"]);
  •     if($$proxySite){
  •         foreach($ds as $d){
  •             $d=str_replace($accessSite, $proxySite,$d);
  •             $clearUrls[]=$d;
  •         }
  •     }
  •     scan_dir($cacheDir);
  •     $cacheurls = array();
  •     foreach($filedirs as $filename){
  •         if(!is_file($filename)){
  •             continue;
  •         }
  •         $cacheUrl=getUrlFromCacheFile($filename);

  •         foreach($clearUrls as $clearUrl){
  •          $clearUrl=str_replace($accessSite, $proxySite,$clearUrl);
  •             $pos=strpos($cacheUrl,$clearUrl);
  •             // echo "$cacheUrl,$clearUrl,$pos
    ";

  •             //比较和
  •             if($pos===0){
  •                     $cacheurls[]=$cacheUrl;
  •                     break;
  •             }
  •         }
  •     }
  •     if(count($cacheurls) > 0){
  •         $accessSite=$_POST["accessSite"];
  •         $proxySite=$proxySites[$accessSite];
  •         $output.="
    执行结果
  • \n
    \n";
  •         foreach($cacheurls as $url2){

  •             $url=trim($url2);
  •             $output.="------------------------$url start-----------------------------\n";
  •             $pos = strpos($url, $accessSite);
  •             if(purge($proxyIp,$proxyPort,$url)==0){
  •                     $result[$url2]=0;
  •             }else{
  •                     $result[$url2]=1;
  •             }
  •             $output.="------------------------$url end -----------------------------\n";
  •         }
  •         $output.="
  • \n";
  •     }else{
  •         foreach($clearUrls as $u){
  •             $result[$u]=-1;
  •         }
  •     }
  • }
  • ?>

  • <!DOCTYPE html>
  • <html xmlns="">
  • <head>
  • <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  • <title>刷新squid</title>
  • <body>
  • <?php
  •     if($result){
  •         echo "\n";
  •         foreach($result as $url=>$isOk){
  •             switch($isOk){
  •                 case 0://成功
  •                 $r="成功";
  •                 break;
  •                 case 1://成功
  •                 $r="失败";
  •                 break;
  •                 case -1://跳过
  •                 $r="跳过";
  •                 break;
  •             }
  •             if($$proxySite){
  •                 $url=str_replace($proxySite, $accessSite, $url);
  •             }
  •             echo "
  • \n";
  •         }
  •         echo "
  • URL结果
    $url$r
    \n"
    ;
  •     }
  • ?>

  • <form action="" method="post">
  • <table >
  • <tr><td>选择站点:</td></tr>
  • <tr><td>
  • <select name="accessSite" id="accessSite">
  •     <?php
  •         foreach($proxySites as $accessSite => $proxySite){
  •         $isSelected=$_POST["accessSite"]==$accessSite?"selected":"";
  •             echo "\n";
  •         }
  •     ?>
  • </select>
  • <script>
  •     function view(){
  •         location="?accessSite="+document.getElementById("accessSite").value+"&view=1";    
  •     }    
  • </script>
  • <input type="checkbox" name="view" value="1" <?php echo $_POST["view"]?"checked":"";?>/><label for="view">只查看</label>
  • </td></tr>
  • <tr><td>输入一组URL(一个一行)</td></tr>
  • <tr><td><textarea name="urls" style="width:1000px;height:200px;"><?php if($_POST["view"])foreach($cacheurls as $cacheurl){echo "$cacheurl\n";}?></textarea></td></tr>
  • <tr><td>刷新目录(一个一行)</td></tr>
  • <tr><td><textarea name="dirs" style="width:1000px;height:200px;"></textarea></td></tr>
  • <tr><td><input type="submit" value="提交" /></td></tr>
  • </table>
  • </form>
  • <?php
  •     echo $output;
  • ?>
  • </body></html>
  • <?php
  • //清除某个url
  • function purge($proxyIp,$proxyPort,$url)
  • {
  •     global $output;
  •     $host = parse_url($url);
  •     $host = $host['host'];
  •     $purge_url=str_replace("http://".$host,"/purge",$url);
  •     if (empty($proxyIp)) {
  •         $proxyIp = gethostbyname($host);
  •     }
  •     if (empty($proxyPort)) {
  •         $proxyPort = "80";
  •     }
  •     $output.="正在从服务器".$proxyIp."更新".$url."\n";
  •     $errstr = '';
  •     $errno = '';
  •     $fp = fsockopen ($proxyIp, $proxyPort, $errno, $errstr, 2);
  •     if (!$fp)
  •     {
  •          $output.="连接失败!";
  •          return -1;
  •     }
  •     else
  •     {
  •         $out = "GET ".$purge_url." HTTP/1.1\r\n";
  •         $out .= "Host:".$host."\r\n";
  •         $out .= "Connection: close\r\n\r\n";
  •         $output.="***********request start**************\n";
  •         $output.=$out;
  •         $output.="***********request end **************\n";
  •         fputs ($fp, $out);
  •         $output.="***********response start**************\n";
  •         //是否更新成功
  •         $isOk=false;
  •         while($out = fgets($fp , 4096)){
  •             if(strpos($out,"200 OK\r\n")!==FALSE){
  •                 //更新成功
  •                 $isOk=true;
  •             }
  •             $output.=$out;
  •             if($out=="\r\n"){
  •                 break;
  •             }
  •         }
  •         fclose ($fp);
  •         $output.="***********response end **************\n";        
  •         flush();
  •         if($isOk){
  •             return 0;
  •         }else{
  •             return 1;
  •         }
  •     }
  • }

  • //递归扫描cache目录下所有文件路径
  • function scan_dir($dir) {
  •         global $filedirs;
  •         if (!is_dir($dir)) return false;
  •         if ($dh = opendir($dir)) {
  •             while (($file = readdir($dh)) !== false) {
  •                 if ($file[0] == '.') continue;
  •                 if($file=='swap.state')continue;
  •                 $fullpath = "$dir/$file";
  •                 $filedirs[] = $fullpath;
  •                 if (is_dir($fullpath))
  •                     scan_dir($fullpath);
  •             }
  •             closedir($dh);
  •         }
  •         return $filedirs;
  • }
  • //从cache文件中提取真实的URL
  • function getUrlFromCacheFile($filename){
  •         //cache文件头长度
  •         $headerLen=0x1E;
  •         $handle = fopen($filename, "rb");
  •         if(!$handle){
  •             return -1;
  •         }
  •         //读取文件的前1k字节
  •         $contents = fread($handle, 1024);
  •         fclose($handle);
  •         if(strlen($contents)<=$headerLen){
  •             return -2;
  •         }
  •         //截掉文件头
  •         $contents=substr($contents,$headerLen);
  •         
  •         //cache文件的分隔符为\A
  •         $pos=strpos($contents, chr(0x0A));
  •         if($pos===FALSE){
  •             return -3;
  •         }
  •         //获取分隔符前的字符串
  •         $contents="http://".substr($contents,0,$pos);
  •         return $contents;
  • }
  • ?>


  • 测试结果:

    阅读(17956) | 评论(5) | 转发(1) |
    给主人留下些什么吧!~~

    kimfly2014-11-11 15:39:45

    楼主,能否把文件共享下,谢谢。

    xdsnet2012-08-23 17:34:54

    yifangyou: 不是我的排版乱了,是代码编辑器有点问题.....
    但还是可以继续调整以完成更好的排版啊

    0881555552012-07-25 14:43:55

    学习了

    yifangyou2012-07-23 21:21:50

    xieyunge: 学习了,正好用上,可惜排版乱了.....
    不是我的排版乱了,是代码编辑器有点问题

    xieyunge2012-07-23 21:18:53

    学习了,正好用上,可惜排版乱了