| 1 |
<?php |
| 2 |
/* |
| 3 |
Name: 系统信息 |
| 4 |
URI: https://mp.weixin.qq.com/s/kqlag2-RWn_n481R0QCJHw |
| 5 |
Description: 系统信息让你在后台一个页面就能够快速实时查看当前的系统状态。 |
| 6 |
Version: 2.0 |
| 7 |
Admin: true |
| 8 |
*/ |
| 9 |
class WPJAM_Server_Status{ |
| 10 |
public static function callback(...$args){ |
| 11 |
$id = $args[1]['id']; |
| 12 |
$items = [self::class, $GLOBALS['current_tab']]($id); |
| 13 |
|
| 14 |
if($id == 'usage'){ |
| 15 |
foreach($items as $item){ |
| 16 |
echo '<hr />'; |
| 17 |
|
| 18 |
$unit = wpjam_pull($item[1], 'unit') ?: 1; |
| 19 |
$data = wpjam_map(wpjam_pull($item[1], 'labels'), fn($v, $k) => ['label'=>$v, 'count'=>round($item[0][$k]/$unit, 2)]); |
| 20 |
|
| 21 |
echo wpjam_chart('donut', $data, $item[1]+['total'=>true, 'chart_width'=>150, 'table_width'=>320]); |
| 22 |
} |
| 23 |
}else{ |
| 24 |
?> |
| 25 |
<table class="widefat striped" style="border:none;"> |
| 26 |
<tbody><?php foreach($items as $item){ ?> |
| 27 |
<tr><?php foreach($item as $i){ ?> |
| 28 |
<td><?php echo $i; ?></td> |
| 29 |
<?php } ?></tr> |
| 30 |
<?php } ?></tbody> |
| 31 |
</table> |
| 32 |
<?php |
| 33 |
} |
| 34 |
} |
| 35 |
|
| 36 |
public static function server($id){ |
| 37 |
if($id == 'server'){ |
| 38 |
$items[] = ['服务器', gethostname().'('.$_SERVER['HTTP_HOST'].')']; |
| 39 |
$items[] = ['服务器IP', '� |
| 40 |
网:'.gethostbyname(gethostname())]; |
| 41 |
$items[] = ['系统', php_uname('s')]; |
| 42 |
|
| 43 |
if(strpos(ini_get('open_basedir'), ':/proc') !== false){ |
| 44 |
if(@is_readable('/proc/cpuinfo')){ |
| 45 |
$cpus = wpjam_lines(file_get_contents('/proc/cpuinfo'), "\n\n"); |
| 46 |
$base[] = count($cpus).'核'; |
| 47 |
} |
| 48 |
|
| 49 |
if(@is_readable('/proc/meminfo')){ |
| 50 |
$mems = wpjam_lines(file_get_contents('/proc/meminfo')); |
| 51 |
$mem = (int)substr(array_find($mems, fn($m) => str_starts_with($m, 'MemTotal:')), 9); |
| 52 |
$base[] = round($mem/1024/1024).'G'; |
| 53 |
} |
| 54 |
|
| 55 |
if(!empty($base)){ |
| 56 |
$items[] = ['� |
| 57 |
�置', '<strong>'.implode(' / ', $base).'</strong>']; |
| 58 |
} |
| 59 |
|
| 60 |
if(@is_readable('/proc/meminfo')){ |
| 61 |
$uptime = wpjam_lines(file_get_contents('/proc/uptime'), ' '); |
| 62 |
$items[] = ['运行时间', human_time_diff(time()-$uptime[0])]; |
| 63 |
} |
| 64 |
|
| 65 |
|
| 66 |
$items[] = ['空闲率', round($uptime[1]*100/($uptime[0]*count($cpus)), 2).'%']; |
| 67 |
$items[] = ['系统负载', '<strong>'.implode(' ',sys_getloadavg()).'</strong>']; |
| 68 |
} |
| 69 |
|
| 70 |
$items[] = ['文档根目录', $_SERVER['DOCUMENT_ROOT']]; |
| 71 |
|
| 72 |
return $items; |
| 73 |
}elseif($id == 'version'){ |
| 74 |
return [ |
| 75 |
[wpjam_lines($_SERVER['SERVER_SOFTWARE'], '/')[0], $_SERVER['SERVER_SOFTWARE']], |
| 76 |
['MySQL', $GLOBALS['wpdb']->db_version().'(最低要求:'.$GLOBALS['required_mysql_version'].')'], |
| 77 |
['PHP', phpversion().'(最低要求:'.$GLOBALS['required_php_version'].')'], |
| 78 |
['Zend', Zend_Version()], |
| 79 |
['WordPress', $GLOBALS['wp_version'].'('.$GLOBALS['wp_db_version'].')'], |
| 80 |
['TinyMCE', $GLOBALS['tinymce_version']] |
| 81 |
]; |
| 82 |
}elseif($id == 'php'){ |
| 83 |
return [[implode(' ', get_loaded_extensions())]]; |
| 84 |
}elseif($id == 'apache'){ |
| 85 |
return [[implode(' ', apache_get_modules())]]; |
| 86 |
} |
| 87 |
} |
| 88 |
|
| 89 |
public static function opcache($id){ |
| 90 |
if($id == 'usage'){ |
| 91 |
echo '<p>'.wpjam_get_page_button('reset_opcache').'</p>'; |
| 92 |
|
| 93 |
$status = opcache_get_status(); |
| 94 |
$rest = $status['opcache_statistics']['max_cached_keys']-$status['opcache_statistics']['num_cached_keys']; |
| 95 |
|
| 96 |
return [ |
| 97 |
[$status['memory_usage'], [ |
| 98 |
'title' => '� |
| 99 |
存使用', |
| 100 |
'labels' => ['used_memory'=>'已用� |
| 101 |
存', 'free_memory'=>'剩余� |
| 102 |
存', 'wasted_memory'=>'浪费� |
| 103 |
存'], |
| 104 |
'unit' => 1024*1024 |
| 105 |
]], |
| 106 |
[$status['opcache_statistics'], [ |
| 107 |
'title' => '命中率', |
| 108 |
'labels' => ['hits'=>'命中', 'misses'=>'未命中'] |
| 109 |
]], |
| 110 |
[$status['opcache_statistics']+['rest_cached_keys'=>$rest], [ |
| 111 |
'title' => '存储Keys', |
| 112 |
'labels' => ['num_cached_keys'=>'已用Keys', 'rest_cached_keys'=>'剩余Keys'] |
| 113 |
]] |
| 114 |
]; |
| 115 |
}elseif($id == 'status'){ |
| 116 |
return wpjam_entries(opcache_get_status()['opcache_statistics']); |
| 117 |
}elseif($id == 'configuration'){ |
| 118 |
$config = opcache_get_configuration(); |
| 119 |
|
| 120 |
return array_reduce([$config['version'], wpjam_array($config['directives'], fn($k)=> str_replace('opcache.', '', $k))], fn($c, $v)=> array_merge($c, wpjam_entries($v)), []); |
| 121 |
} |
| 122 |
} |
| 123 |
|
| 124 |
public static function memcached($id){ |
| 125 |
foreach($GLOBALS['wp_object_cache']->get_stats() as $key => $stats){ |
| 126 |
if($id == 'usage'){ |
| 127 |
echo '<p>'.wpjam_get_page_button('flush_mc').'</p>'; |
| 128 |
|
| 129 |
return [ |
| 130 |
[$stats, [ |
| 131 |
'title' => '命中率', |
| 132 |
'labels' => ['get_hits'=>'命中次数', 'get_misses'=>'未命中次数'], |
| 133 |
]], |
| 134 |
[$stats+['rest'=>$stats['limit_maxbytes']-$stats['bytes']], [ |
| 135 |
'title' => '� |
| 136 |
存使用', |
| 137 |
'labels' => ['bytes'=>'已用� |
| 138 |
存', 'rest'=>'剩余� |
| 139 |
存'], |
| 140 |
'unit' => 1024*1024 |
| 141 |
]] |
| 142 |
]; |
| 143 |
}elseif($id == 'status'){ |
| 144 |
return [ |
| 145 |
['Memcached地址', $key], |
| 146 |
['Memcached版本', $stats['version']], |
| 147 |
['进程ID', $stats['pid']], |
| 148 |
['启动时间', wpjam_date('Y-m-d H:i:s',($stats['time']-$stats['uptime']))], |
| 149 |
['运行时间', human_time_diff(0,$stats['uptime'])], |
| 150 |
['已用/分� |
| 151 |
�的� |
| 152 |
存', size_format($stats['bytes']).' / '.size_format($stats['limit_maxbytes'])], |
| 153 |
['当前/启动后总数量', $stats['curr_items'].' / '.$stats['total_items']], |
| 154 |
['为获取� |
| 155 |
存踢除数量', $stats['evictions']], |
| 156 |
['当前/总打开连接数', $stats['curr_connections'].' / '.$stats['total_connections']], |
| 157 |
['总命中次数', $stats['get_hits']], |
| 158 |
['总未命中次数', $stats['get_misses']], |
| 159 |
['总获求次数', $stats['cmd_get']], |
| 160 |
['总请求次数', $stats['cmd_set']], |
| 161 |
['Item平均大小', size_format($stats['bytes']/$stats['curr_items'])], |
| 162 |
]; |
| 163 |
}elseif($id == 'efficiency'){ |
| 164 |
return wpjam_map(['get_hits'=>'命中', 'get_misses'=>'未命中', 'cmd_get'=>'获取', 'cmd_set'=>'设置'], fn($v, $k)=> ['每秒'.$v.'次数', round($stats[$k]/$stats['uptime'])]); |
| 165 |
}elseif($id == 'options'){ |
| 166 |
return wpjam_array(wpjam_get_reflection('class', 'Memcached', 'Constants'), fn($k, $v)=> str_starts_with($k, 'OPT_') ? [$k, [$k, $GLOBALS['wp_object_cache']->get_mc()->getOption($v)]] : null); |
| 167 |
} |
| 168 |
} |
| 169 |
} |
| 170 |
|
| 171 |
public static function get_tabs(){ |
| 172 |
return wpjam_map(['server'=>[ |
| 173 |
'title' => '服务器', |
| 174 |
'function' => 'dashboard', |
| 175 |
'widgets' => (strtoupper(substr(PHP_OS,0,3)) === 'WIN' ? [] : [ |
| 176 |
'server' => ['title'=>'信息'], |
| 177 |
])+[ |
| 178 |
'php' => ['title'=>'PHP扩展'], |
| 179 |
'version' => ['title'=>'版本', 'context'=>'side'] |
| 180 |
]+((!$GLOBALS['is_apache'] || !function_exists('apache_get_modules')) ? [] : [ |
| 181 |
'apache' => ['title'=>'Apache模块', 'context'=>'side'] |
| 182 |
]) |
| 183 |
]]+(function_exists('opcache_get_status') ? ['opcache'=>[ |
| 184 |
'title' => 'Opcache', |
| 185 |
'function' => 'dashboard', |
| 186 |
'widgets' => [ |
| 187 |
'usage' => ['title'=>'使用率'], |
| 188 |
'status' => ['title'=>'状态'], |
| 189 |
'configuration' => ['title'=>'� |
| 190 |
�置信息', 'context'=>'side'] |
| 191 |
], |
| 192 |
'actions' => ['reset_opcache'=>[ |
| 193 |
'title' => '重置缓存', |
| 194 |
'button_text' => '重置缓存', |
| 195 |
'direct' => true, |
| 196 |
'confirm' => true, |
| 197 |
'callback' => fn()=> opcache_reset() ? ['notice'=>'缓存重置成功'] : wp_die('缓存重置失败') |
| 198 |
]] |
| 199 |
]] : [])+(method_exists('WP_Object_Cache', 'get_mc') ? ['memcached'=>[ |
| 200 |
'title' => 'Memcached', |
| 201 |
'function' => 'dashboard', |
| 202 |
'widgets' => [ |
| 203 |
'usage' => ['title'=>'使用率'], |
| 204 |
'efficiency' => ['title'=>'效率'], |
| 205 |
'options' => ['title'=>'选项', 'context'=>'side'], |
| 206 |
'status' => ['title'=>'状态'] |
| 207 |
], |
| 208 |
'actions' => ['flush_mc'=>[ |
| 209 |
'title' => '刷新缓存', |
| 210 |
'button_text' => '刷新缓存', |
| 211 |
'direct' => true, |
| 212 |
'confirm' => true, |
| 213 |
'callback' => fn() => wp_cache_flush() ? ['notice'=>'缓存刷新成功'] : wp_die('缓存刷新失败') |
| 214 |
]] |
| 215 |
]] : []), fn($tab)=> ['widgets'=> array_map(fn($v)=> $v+['callback'=>[self::class, 'callback']], $tab['widgets'])]+$tab); |
| 216 |
} |
| 217 |
} |
| 218 |
|
| 219 |
wpjam_add_menu_page('server-status', [ |
| 220 |
'parent' => 'wpjam-basic', |
| 221 |
'menu_title' => '系统信息', |
| 222 |
'summary' => __FILE__, |
| 223 |
'chart' => true, |
| 224 |
'order' => 9, |
| 225 |
'function' => 'tab', |
| 226 |
'model' => 'WPJAM_Server_Status', |
| 227 |
'capability' => is_multisite() ? 'manage_site' : 'manage_options', |
| 228 |
]); |