最新的memcache pecl中,新增了一个memcache.php,这个php文件可以用来方便的查看memcache的状况,界面上与apc自带的apc.php风格一致。
如图:
应该算是最方便的监测memcache的办法了。
/* +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2004 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.0 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_0.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | [email protected] so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: stoneson Rejected!
Wrong Username or Password!
EOB;
exit; } */ ///MEMCACHE FUNCTIONS / function sendMemcacheCommands($command){ global $MEMCACHE_SERVERS;
$result = array();
foreach($MEMCACHE_SERVERS as $server){
$strs = explode(':',$server);
$host = $strs[0];
$port = $strs[1];
$result[$server] = sendMemcacheCommand($host,$port,$command);
}
return $result; } function sendMemcacheCommand($server,$port,$command){
$s = @fsockopen($server,$port);
if (!$s){
die("Cant connect to:".$server.':'.$port);
}
fwrite($s, $command."\r\n");
$buf='';
while ((!feof($s))) {
$buf .= fgets($s, 256);
if (strpos($buf,"END\r\n")!==false){ // stat says end
break;
}
if (strpos($buf,"DELETED\r\n")!==false || strpos($buf,"NOT_FOUND\r\n")!==false){ // delete says these
break;
}
if (strpos($buf,"OK\r\n")!==false){ // flush_all says ok
break;
}
} fclose($s); return parseMemcacheResults($buf); } function parseMemcacheResults($str){
$res = array();
$lines = explode("\r\n",$str);
$cnt = count($lines);
for($i=0; $i< $cnt; $i++){
$line = $lines[$i];
$l = explode(' ',$line,3);
if (count($l)==3){
$res[$l[0]][$l[1]]=$l[2];
if ($l[0]=='VALUE'){ // next line is the value
$res[$l[0]][$l[1]] = array();
list ($flag,$size)=explode(' ',$l[2]);
$res[$l[0]][$l[1]]['stat']=array('flag'=>$flag,'size'=>$size);
$res[$l[0]][$l[1]]['value']=$lines[++$i];
}
}elseif($line=='DELETED' || $line=='NOT_FOUND' || $line=='OK'){
return $line;
}
}
return $res; } function dumpCacheSlab($server,$slabId,$limit){ list($host,$port) = explode(':',$server); $resp = sendMemcacheCommand($host,$port,'stats cachedump '.$slabId.' '.$limit); return $resp; } function flushServer($server){ list($host,$port) = explode(':',$server); $resp = sendMemcacheCommand($host,$port,'flush_all'); return $resp; } function getCacheItems(){ $items = sendMemcacheCommands('stats items'); $serverItems = array(); $totalItems = array(); foreach ($items as $server=>$itemlist){ $serverItems[$server] = array(); $totalItems[$server]=0; if (!isset($itemlist['STAT'])){ continue; } $iteminfo = $itemlist['STAT']; foreach($iteminfo as $keyinfo=>$value){ if (preg_match('/items\:(\d+?)\:(.+?)$/',$keyinfo,$matches)){ $serverItems[$server][$matches[1]][$matches[2]] = $value; if ($matches[2]=='number'){ $totalItems[$server] +=$value; } } } } return array('items'=>$serverItems,'counts'=>$totalItems); } function getMemcacheStats($total=true){
$resp = sendMemcacheCommands('stats');
if ($total){
$res = array();
foreach($resp as $server=>$r){
foreach($r['STAT'] as $key=>$row){
if (!isset($res[$key])){
$res[$key]=null;
}
switch ($key){
case 'pid':
$res['pid'][$server]=$row;
break;
case 'uptime':
$res['uptime'][$server]=$row;
break;
case 'time':
$res['time'][$server]=$row;
break;
case 'version':
$res['version'][$server]=$row;
break;
case 'pointer_size':
$res['pointer_size'][$server]=$row;
break;
case 'rusage_user':
$res['rusage_user'][$server]=$row;
break;
case 'rusage_system':
$res['rusage_system'][$server]=$row;
break;
case 'curr_items':
$res['curr_items']+=$row;
break;
case 'total_items':
$res['total_items']+=$row;
break;
case 'bytes':
$res['bytes']+=$row;
break;
case 'curr_connections':
$res['curr_connections']+=$row;
break;
case 'total_connections':
$res['total_connections']+=$row;
break;
case 'connection_structures':
$res['connection_structures']+=$row;
break;
case 'cmd_get':
$res['cmd_get']+=$row;
break;
case 'cmd_set':
$res['cmd_set']+=$row;
break;
case 'get_hits':
$res['get_hits']+=$row;
break;
case 'get_misses':
$res['get_misses']+=$row;
break;
case 'evictions':
$res['evictions']+=$row;
break;
case 'bytes_read':
$res['bytes_read']+=$row;
break;
case 'bytes_written':
$res['bytes_written']+=$row;
break;
case 'limit_maxbytes':
$res['limit_maxbytes']+=$row;
break;
case 'threads':
$res['rusage_system'][$server]=$row;
break;
}
}
}
return $res;
}
return $resp; } // // // don't cache this page // header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1 header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); // HTTP/1.0 function duration($ts) { global $time; $years = (int)((($time - $ts)/(7*86400))/52.177457); $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400)); $weeks = (int)(($rem)/(7*86400)); $days = (int)(($rem)/86400) - $weeks*7; $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24; $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60; $str = ''; if($years==1) $str .= "$years year, "; if($years>1) $str .= "$years years, "; if($weeks==1) $str .= "$weeks week, "; if($weeks>1) $str .= "$weeks weeks, "; if($days==1) $str .= "$days day,"; if($days>1) $str .= "$days days,"; if($hours == 1) $str .= " $hours hour and"; if($hours>1) $str .= " $hours hours and"; if($mins == 1) $str .= " 1 minute"; else $str .= " $mins minutes"; return $str; } // create graphics // function graphics_avail() {
return extension_loaded('gd'); } function bsize($s) {
foreach (array('','K','M','G') as $i => $k) {
if ($s < 1024) break;
$s/=1024;
}
return sprintf("%5.1f %sBytes",$s,$k); } // create menu entry function menu_entry($ob,$title) {
global $PHP_SELF;
if ($ob==$_GET['op']){
return "
EOB; } // TODO, AUTH $_GET['op'] = !isset($_GET['op'])? '1':$_GET['op']; $PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],'')) : ''; $PHP_SELF=$PHP_SELF.'?'; $time = time(); // sanitize _GET foreach($_GET as $key=>$g){ $_GET[$key]=htmlentities($g); } // singleout // when singleout is set, it only gives details for that server. if (isset($_GET['singleout']) && $_GET['singleout']>=0 && $_GET['singleout'] General Cache Information
EOB;
echo "PHP Version $phpversion \n";
echo "Memcached Host". ((count($MEMCACHE_SERVERS)>1) ? 's':'')." ";
$i=0;
if (!isset($_GET['singleout']) && count($MEMCACHE_SERVERS)>1){
foreach($MEMCACHE_SERVERS as $server){
echo ($i+1).'. '.$server.'
';
}
}
else{
echo '1.'.$MEMCACHE_SERVERS[0];
}
if (isset($_GET['singleout'])){
echo '(all servers)
';
}
echo " \n";
echo <<Total Memcache Cache ".bsize($memcacheStats['limit_maxbytes'])." Memcache Server Information
EOB; foreach($MEMCACHE_SERVERS as $server){ echo ''; echo '
';
} echo << ';
echo ''.$server.' [Flush this server] ';
echo 'Start Time ',date(DATE_FORMAT,$memcacheStatsSingle[$server]['STAT']['time']-$memcacheStatsSingle[$server]['STAT']['uptime']),' ';
echo 'Uptime ',duration($memcacheStatsSingle[$server]['STAT']['time']-$memcacheStatsSingle[$server]['STAT']['uptime']),' ';
echo 'Memcached Server Version '.$memcacheStatsSingle[$server]['STAT']['version'].' ';
echo 'Used Cache Size ',bsize($memcacheStatsSingle[$server]['STAT']['bytes']),' ';
echo 'Total Cache Size ',bsize($memcacheStatsSingle[$server]['STAT']['limit_maxbytes']),' Host Status Diagrams
EOB;
$size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
echo <<
EOB;
echo
graphics_avail() ?
'Cache Usage
Hits & Misses
'.
" \n"
: "",
'".
" ',
' ',
' Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size)," \n",
' Hits: ',$hits.sprintf(" (%.1f%%)",$hits*100/($hits+$misses))," \n",
'',
'
Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size)," \n",
' Misses: ',$misses.sprintf(" (%.1f%%)",$misses*100/($hits+$misses))," \n";
echo <<< EOB
Cache Information
Current Items(total) $curr_items ($total_items) Hits {$hits} Misses {$misses} Request Rate (hits, misses) $req_rate cache requests/second Hit Rate $hit_rate cache requests/second Miss Rate $miss_rate cache requests/second Set Rate $set_rate cache requests/second
$server EOB;
foreach($entries as $slabId => $slab) {
$dumpUrl = $PHP_SELF.'&op=2&server='.(array_search($server,$MEMCACHE_SERVERS)).'&dumpslab='.$slabId;
echo
"Slab Id Info ",
" ";
$m=1-$m;
}
echo << ",
"Item count: ",$slab['number'],'
Age:',duration($time-$slab['age']),'
Evicted:',((isset($slab['evicted']) && $slab['evicted']==1)? 'Yes':'No');
if ((isset($_GET['dumpslab']) && $_GET['dumpslab']==$slabId) && (isset($_GET['server']) && $_GET['server']==array_search($server,$MEMCACHE_SERVERS))){
echo "
Items: item
";
$items = dumpCacheSlab($server,$slabId,$slab['number']); // maybe someone likes to do a pagination here :)
$i=1; foreach($items['ITEM'] as $itemKey=>$itemInfo){ $itemInfo = trim($itemInfo,'[ ]'); echo '',$itemKey,''; if ($i++ % 10 == 0) { echo '
'; } elseif ($i!=$slab['number']+1){ echo ','; } }
}
echo "
EOB; }
break; break; case 4: //item dump if (!isset($_GET['key']) || !isset($_GET['server'])){ echo "No key set!"; break; } // I'm not doing anything to check the validity of the key string. // probably an exploit can be written to delete all the files in key=base64_encode("\n\r delete all"). // somebody has to do a fix to this. $theKey = htmlentities(base64_decode($_GET['key'])); $theserver = $MEMCACHE_SERVERS[(int)$_GET['server']]; list($h,$p) = explode(':',$theserver); $r = sendMemcacheCommand($h,$p,'get '.$theKey); echo <<
EOB; echo "Server Key Value Delete "; echo <<",$theserver," ",$theKey, "
flag:",$r['VALUE'][$theKey]['stat']['flag'], "
Size:",bsize($r['VALUE'][$theKey]['stat']['size']), "",chunk_split($r['VALUE'][$theKey]['value'],40)," ", 'Delete ","
EOB; break; case 5: // item delete
if (!isset($_GET['key']) || !isset($_GET['server'])){
echo "No key set!";
break; } $theKey = htmlentities(base64_decode($_GET['key']));
$theserver = $MEMCACHE_SERVERS[(int)$_GET['server']];
list($h,$p) = explode(':',$theserver); $r = sendMemcacheCommand($h,$p,'delete '.$theKey); echo 'Deleting '.$theKey.':'.$r;
break; case 6: // flush server $theserver = $MEMCACHE_SERVERS[(int)$_GET['server']]; $r = flushServer($theserver); echo 'Flush '.$theserver.":".$r; break; } echo getFooter(); ?>