这些日子,我们公司的论坛时有不正常之处,典型问题就是:无征兆的,「最近访问论坛"列表,突然丢失,不少人大呼不方便。如果去后台更新一下子缓存,又正常了。
反复查对,发现:/forumdata/cache/cache_forumdisplay.php 这个文件,其中缓存了论坛列表信息。出现问题时,其中本来应该正常缓存的信息,丢失了。
而缓存更新,在/include/cache.inc.php 的 updatecache() 函数之中,cache_forumdisplay.php 通过统一的流程制造,实在是想不通,什么地方产生了特殊状况。
因为这个丢失,当时看起来,是没有任何征兆,无法重现的。
无奈之下,在/include/cache.inc.php 的 writetocache 函数中,埋了一段代码:
function writetocache($script, $cachenames, $cachedata ='', $prefix ='cache_'){ global $authkey, $timestamp; if(is_array($cachenames)&&!$cachedata){ foreach($cachenames as $name){ $cachedata .= getcachearray($name, $script); } } $dir= DISCUZ_ROOT.'./forumdata/cache/'; if(!is_dir($dir)){ @mkdir($dir, 0777); } if($fp =@fopen("$dir$prefix$script.php",'wb')){ fwrite($fp,"<?phpn//Discuz! cache file, DO NOT modify me!". "n//Created: ".date("M j, Y, G:i"). "n//Identify: ".md5($prefix.$script.'.php'.$cachedata.$authkey)."nn$cachedata?>"); fclose($fp); //
埋的代码 |
一天以后,在/forumdata/logs/里面,*****_notfound.php 里面,逮到了一次丢失的过程,基本流程是:
/admincp.php->/admin/prune.inc.php->updatecache()->/include/cache.func.php->writetocache()
对应的实际操作,就是在网站的后台,执行批量删除帖子的操作,其中有一个更新:updatecache(『globalstick』);
最后,定位到了 getcachevars() 这个函数里面,找到了问题所在。
先卖个关子,0818 的时候,Discuz 发了一个补丁,详见 http://www.discuz.net/thread-1388523-1-1.html 。
恰好更新了/include/cache.func.php 这个文件,在 getcachevars() 里面加了一段代码:
if(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $key)){ continue; } |
其作用在于过滤非法变量。
殊不知,就是这段代码,变成了罪魁祸首,导致新的问题产生。
程序实际运行过程中,会有_DCACHE[『forums』] 等类似的变量名,需要通过这个关卡,结果就是挂掉,直接导致对应的信息为空,从而是的缓存文件丢失信息。有兴趣的朋友,可以自己跟踪测试一下子。
修正的代码如下:
if(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $key)&&!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_ x7f-xff]*['[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*']$/", $key)){ continue; } |
让_DCACHE[『forums』] 等类似的变量名通过,至此问题解决。
经查代码发现,Discuz4.1.0 到 Discuz7.0.0,均存在该问题,所以请使用 Discuz 的同学们,从速修改,以免出现莫名其妙的问题。
---------- 在文件中查找 ---------- "/dp20090818/4.1.0/admin/styles.inc.php"(316,28): } elseif(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $newcvar)) { "/dp20090818/4.1.0/include/cache.func.php"(664,21): if(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $key)) { "/dp20090818/5.0.0/admin/styles.inc.php"(320,28): } elseif(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $newcvar)) { "/dp20090818/5.0.0/include/cache.func.php"(776,21): if(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $key)) { "/dp20090818/5.5.0/admin/styles.inc.php"(328,28): } elseif(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $newcvar)) { "/dp20090818/5.5.0/include/cache.func.php"(1087,21): if(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $key)) { "/dp20090818/6.0.0/admin/styles.inc.php"(314,28): } elseif(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $newcvar)) { "/dp20090818/6.0.0/include/cache.func.php"(1425,21): if(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $key)) { "/dp20090818/6.1.0/admin/styles.inc.php"(332,28): } elseif(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $newcvar)) { "/dp20090818/6.1.0/include/cache.func.php"(1378,21): if(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $key)) { "/dp20090818/6.1.0F/admin/styles.inc.php"(332,28): } elseif(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $newcvar)) { "/dp20090818/6.1.0F/include/cache.func.php"(1359,21): if(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $key)) { "/dp20090818/7.0.0/admin/styles.inc.php"(736,28): } elseif(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $newcvar)) { "/dp20090818/7.0.0/include/cache.func.php"(1503,21): if(!preg_match("/^[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*$/", $key)) { 找到 14 个事件 (在 14 个文件中) 。 输出完成 (耗时 0 秒) |
没有打 0818 补丁的,请从速从 http://www.discuz.net/thread-1388523-1-1.html 打最新补丁,然后与打过补丁的同学,一起把 getcachevars() 的这个问题修正。