初始化本地仓库
This commit is contained in:
@@ -0,0 +1,388 @@
|
||||
<?php
|
||||
/**
|
||||
*+------------------
|
||||
* madong
|
||||
*+------------------
|
||||
* Copyright (c) https://gitee.com/motion-code All rights reserved.
|
||||
*+------------------
|
||||
* Author: Mr. April (405784684@qq.com)
|
||||
*+------------------
|
||||
* Official Website: http://www.madong.tech
|
||||
*/
|
||||
|
||||
namespace core\monitor;
|
||||
|
||||
/**
|
||||
* 系统监控服务类
|
||||
*
|
||||
* @author Mr.April
|
||||
* @since 1.0
|
||||
*/
|
||||
class ServerMonitor
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取磁盘信息
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDiskInfo(): array
|
||||
{
|
||||
$disk = [];
|
||||
if (stristr(PHP_OS, 'WIN')) {
|
||||
// Windows 系统
|
||||
$drives = shell_exec('wmic logicaldisk get size,freespace,caption');
|
||||
$lines = explode("\n", trim($drives ?? ''));
|
||||
foreach ($lines as $line) {
|
||||
if (preg_match('/^([A-Z]:)/', $line, $matches)) {
|
||||
$parts = preg_split('/\s+/', trim($line));
|
||||
if (count($parts) >= 3) {
|
||||
$disk[] = [
|
||||
'filesystem' => $matches[1],
|
||||
'size' => $this->formatBytes(intval($parts[1])),
|
||||
'available' => $this->formatBytes(intval($parts[2])),
|
||||
'used' => $this->formatBytes(intval($parts[1]) - intval($parts[2])),
|
||||
'use_percentage' => sprintf('%.2f', (intval($parts[1]) - intval($parts[2])) / intval($parts[1]) * 100) . '%',
|
||||
'mounted_on' => $matches[1],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Linux 系统
|
||||
$diskInfo = shell_exec('df -h');
|
||||
$lines = explode("\n", trim($diskInfo ?? ''));
|
||||
foreach ($lines as $line) {
|
||||
if (preg_match('/^\/dev\/\w+/', $line)) {
|
||||
$parts = preg_split('/\s+/', $line);
|
||||
$disk[] = [
|
||||
'filesystem' => $parts[0],
|
||||
'size' => $parts[1],
|
||||
'used' => $parts[2],
|
||||
'available' => $parts[3],
|
||||
'use_percentage' => $parts[4],
|
||||
'mounted_on' => $parts[5],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $disk;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取cpu信息
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCpuInfo(): array
|
||||
{
|
||||
try {
|
||||
if (PHP_OS == 'Linux') {
|
||||
$cpu = $this->getCpuUsage();
|
||||
preg_match('/(\d+)/', shell_exec('cat /proc/cpuinfo | grep "cache size"') ?? '', $cache);
|
||||
if (count($cache) == 0) {
|
||||
// aarch64 有可能是arm架构
|
||||
$cache = trim(shell_exec("lscpu | grep L3 | awk '{print \$NF}'") ?? '');
|
||||
if ($cache == '') {
|
||||
$cache = trim(shell_exec("lscpu | grep L2 | awk '{print \$NF}'") ?? '');
|
||||
}
|
||||
if ($cache != '') {
|
||||
$cache = [0, intval(str_replace(['K', 'B'], '', strtoupper($cache)))];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$cpu = shell_exec('wmic cpu get LoadPercentage | findstr /V "LoadPercentage"');
|
||||
$cpu = intval(trim($cpu ?? '0'));
|
||||
$cache = shell_exec('wmic cpu get L3CacheSize | findstr /V "L3CacheSize"');
|
||||
$cache = trim($cache ?? '');
|
||||
if ($cache == '') {
|
||||
$cache = shell_exec('wmic cpu get L2CacheSize | findstr /V "L2CacheSize"');
|
||||
$cache = trim($cache ?? '');
|
||||
}
|
||||
if ($cache != '') {
|
||||
$cache = [0, intval($cache) * 1024];
|
||||
}
|
||||
}
|
||||
return [
|
||||
'cpu_name' => $this->getCpuName(), // CPU 名称
|
||||
'physical_cores' => $this->getCpuPhysicsCores(), // 物理核心数
|
||||
'logical_cores' => $this->getCpuLogicCores(), // 逻辑核心数
|
||||
'cache_size_mb' => $cache[1] ? $cache[1] / 1024 : 0, // 缓存大小(MB)
|
||||
'cpu_usage_percentage' => $cpu, // CPU 使用率(%)
|
||||
'free_cpu_percentage' => round(100 - $cpu, 2), // 可用 CPU 百分比(%)
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
return [
|
||||
'cpu_name' => '获取失败',
|
||||
'physical_cores' => '获取失败',
|
||||
'logical_cores' => '获取失败',
|
||||
'cache_size_mb' => '获取失败',
|
||||
'cpu_usage_percentage' => '获取失败',
|
||||
'free_cpu_percentage' => '获取失败',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取内存信息
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMemoryInfo(): array
|
||||
{
|
||||
$result = [];
|
||||
if (stristr(PHP_OS, 'WIN')) {
|
||||
// Windows 系统
|
||||
$cap = shell_exec('wmic Path Win32_PhysicalMemory Get Capacity | findstr /V "Capacity"');
|
||||
$caps = array_filter(array_map('trim', explode("\n", $cap)));
|
||||
$result['total_memory'] = round(array_sum(array_map('intval', $caps)) / 1024 / 1024 / 1024, 2); // 总内存(GB)
|
||||
$free = shell_exec('wmic OS get FreePhysicalMemory | findstr /V "FreePhysicalMemory"');
|
||||
$result['available_memory'] = round(intval(trim($free)) / 1024, 2); // 可用内存(MB)
|
||||
$result['used_memory'] = round($result['total_memory'] - $result['available_memory'], 2); // 使用内存(GB)
|
||||
$result['php_memory_usage'] = round(memory_get_usage(true) / 1024 / 1024, 2); // PHP 使用内存(MB)
|
||||
} else {
|
||||
// Linux 系统
|
||||
$memInfo = shell_exec('cat /proc/meminfo');
|
||||
$memInfoArray = array_filter(array_map('trim', explode("\n", $memInfo)));
|
||||
|
||||
$total = $available = 0;
|
||||
|
||||
foreach ($memInfoArray as $line) {
|
||||
if (str_starts_with($line, 'MemTotal:')) {
|
||||
preg_match('/(\d+)/', $line, $matches);
|
||||
$total = intval($matches[1]);
|
||||
}
|
||||
if (str_starts_with($line, 'MemAvailable:')) {
|
||||
preg_match('/(\d+)/', $line, $matches);
|
||||
$available = intval($matches[1]);
|
||||
}
|
||||
}
|
||||
$result['total_memory'] = sprintf('%.2f', $total / 1024 / 1024); // 总内存(GB)
|
||||
$result['available_memory'] = sprintf('%.2f', $available / 1024 / 1024); // 可用内存(GB)
|
||||
$result['used_memory'] = sprintf('%.2f', ($total - $available) / 1024 / 1024); // 使用内存(GB)
|
||||
$result['php_memory_usage'] = round(memory_get_usage(true) / 1024 / 1024, 2); // PHP 使用内存(MB)
|
||||
}
|
||||
// 计算内存使用率
|
||||
$result['memory_usage_rate'] = sprintf('%.2f', ($result['used_memory'] / $result['total_memory']) * 100);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Redis详情
|
||||
*
|
||||
* @return array
|
||||
* @throws \RedisException
|
||||
*/
|
||||
public function getRedisInfo(): array
|
||||
{
|
||||
$config = config('redis.default');
|
||||
$redis = new \Redis();
|
||||
$redis->connect($config['host'], $config['port']);
|
||||
if (!empty($config['password'])) {
|
||||
$redis->auth($config['password']);
|
||||
}
|
||||
$info = $redis->info(); // 获取 Redis 监控信息
|
||||
|
||||
return [
|
||||
'uptime_in_seconds' => $info['uptime_in_seconds'], // 运行时间(秒)
|
||||
'connected_clients' => $info['connected_clients'], // 连接的客户端数量
|
||||
'used_memory' => $this->formatBytes($info['used_memory']), // 使用的内存
|
||||
'memory_fragmentation_ratio' => $info['mem_fragmentation_ratio'], // 内存碎片比率
|
||||
'total_commands_processed' => $info['total_commands_processed'], // 处理的命令总数
|
||||
'total_connections_received' => $info['total_connections_received'], // 接收的连接总数
|
||||
'keyspace_hits' => $info['keyspace_hits'], // 键空间命中次数
|
||||
'keyspace_misses' => $info['keyspace_misses'], // 键空间未命中次数
|
||||
'hit_rate' => $this->calculateHitRate($info), // 命中率
|
||||
'variable' => $info ?? [],
|
||||
'data' => $this->getRedisKeysAndValues($redis),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取PHP环境信息
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPhpInfo(): array
|
||||
{
|
||||
return [
|
||||
'php_version' => PHP_VERSION,
|
||||
'os' => PHP_OS,
|
||||
'project_path' => BASE_PATH,
|
||||
'memory_limit' => ini_get('memory_limit'),
|
||||
'max_execution_time' => ini_get('max_execution_time'),
|
||||
'error_reporting' => ini_get('error_reporting'),
|
||||
'display_errors' => ini_get('display_errors'),
|
||||
'upload_max_filesize' => ini_get('upload_max_filesize'),
|
||||
'post_max_size' => ini_get('post_max_size'),
|
||||
'extension_dir' => ini_get('extension_dir'),
|
||||
'loaded_extensions' => implode(', ', get_loaded_extensions()),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描redis数据
|
||||
*
|
||||
* @param $redis
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getRedisKeysAndValues($redis): array
|
||||
{
|
||||
|
||||
$keyValues = [];
|
||||
$iterator = null;
|
||||
do {
|
||||
$keys = $redis->scan($iterator);
|
||||
foreach ($keys as $key) {
|
||||
$keyValues[$key] = $redis->get($key);
|
||||
}
|
||||
} while ($iterator > 0);
|
||||
return $keyValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取CPU名称
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getCpuName(): string
|
||||
{
|
||||
if (PHP_OS == 'Linux') {
|
||||
preg_match('/^\s+\d\s+(.+)/', shell_exec('cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c') ?? '', $matches);
|
||||
if (count($matches) == 0) {
|
||||
// aarch64 有可能是arm架构
|
||||
$name = trim(shell_exec("lscpu| grep Architecture | awk '{print $2}'") ?? '');
|
||||
if ($name != '') {
|
||||
$mfMhz = trim(shell_exec("lscpu| grep 'MHz' | awk '{print \$NF}' | head -n1") ?? '');
|
||||
$mfGhz = trim(shell_exec("lscpu| grep 'GHz' | awk '{print \$NF}' | head -n1") ?? '');
|
||||
if ($mfMhz == '' && $mfGhz == '') {
|
||||
return $name;
|
||||
} else if ($mfGhz != '') {
|
||||
return $name . ' @ ' . $mfGhz . 'GHz';
|
||||
} else if ($mfMhz != '') {
|
||||
return $name . ' @ ' . round(intval($mfMhz) / 1000, 2) . 'GHz';
|
||||
}
|
||||
} else {
|
||||
return '未知';
|
||||
}
|
||||
}
|
||||
return $matches[1] ?? "未知";
|
||||
} else {
|
||||
$name = shell_exec('wmic cpu get Name | findstr /V "Name"');
|
||||
return trim($name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取cpu物理核心数
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getCpuPhysicsCores(): string
|
||||
{
|
||||
if (PHP_OS == 'Linux') {
|
||||
$num = str_replace("\n", '', shell_exec('cat /proc/cpuinfo |grep "physical id"|sort |uniq|wc -l'));
|
||||
return intval($num) == 0 ? '1' : $num;
|
||||
} else {
|
||||
$num = shell_exec('wmic cpu get NumberOfCores | findstr /V "NumberOfCores"');
|
||||
$num = trim($num ?? '1');
|
||||
$nums = explode("\n", $num);
|
||||
$num = 0;
|
||||
foreach ($nums as $n) {
|
||||
$num += intval(trim($n));
|
||||
}
|
||||
return strval($num);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取cpu逻辑核心数
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getCpuLogicCores(): string
|
||||
{
|
||||
if (PHP_OS == 'Linux') {
|
||||
return str_replace("\n", '', shell_exec('cat /proc/cpuinfo |grep "processor"|wc -l'));
|
||||
} else {
|
||||
$num = shell_exec('wmic cpu get NumberOfLogicalProcessors | findstr /V "NumberOfLogicalProcessors"');
|
||||
$num = trim($num ?? '1');
|
||||
$nums = explode("\n", $num);
|
||||
$num = 0;
|
||||
foreach ($nums as $n) {
|
||||
$num += intval(trim($n));
|
||||
}
|
||||
return strval($num);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取CPU使用率
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getCpuUsage(): string
|
||||
{
|
||||
$start = $this->calculationCpu();
|
||||
sleep(1);
|
||||
$end = $this->calculationCpu();
|
||||
|
||||
$totalStart = $start['total'];
|
||||
$totalEnd = $end['total'];
|
||||
|
||||
$timeStart = $start['time'];
|
||||
$timeEnd = $end['time'];
|
||||
|
||||
return sprintf('%.2f', ($timeEnd - $timeStart) / ($totalEnd - $totalStart) * 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算CPU
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function calculationCpu(): array
|
||||
{
|
||||
$mode = '/(cpu)[\s]+([0-9]+)[\s]+([0-9]+)[\s]+([0-9]+)[\s]+([0-9]+)[\s]+([0-9]+)[\s]+([0-9]+)[\s]+([0-9]+)[\s]+([0-9]+)/';
|
||||
$string = shell_exec('cat /proc/stat | grep cpu');
|
||||
preg_match_all($mode, $string, $matches);
|
||||
|
||||
$total = $matches[2][0] + $matches[3][0] + $matches[4][0] + $matches[5][0] + $matches[6][0] + $matches[7][0] + $matches[8][0] + $matches[9][0];
|
||||
$time = $matches[2][0] + $matches[3][0] + $matches[4][0] + $matches[6][0] + $matches[7][0] + $matches[8][0] + $matches[9][0];
|
||||
|
||||
return ['total' => $total, 'time' => $time];
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化字节可读格式
|
||||
*
|
||||
* @param $bytes
|
||||
* @param $decimals
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function formatBytes($bytes, $decimals = 2): string
|
||||
{
|
||||
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
$factor = floor((strlen($bytes) - 1) / 3);
|
||||
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . ' ' . @$units[$factor];
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算Redis命中率
|
||||
*
|
||||
* @param array $info
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
private function calculateHitRate(array $info): float
|
||||
{
|
||||
if ($info['keyspace_hits'] + $info['keyspace_misses'] == 0) {
|
||||
return 0; // 避免除以零
|
||||
}
|
||||
return sprintf('%.2f', ($info['keyspace_hits'] / ($info['keyspace_hits'] + $info['keyspace_misses'])) * 100); // 命中率(%)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user