纯PHP实现系统与PHP进程监控:深入探索/proc文件系统


纯PHP实现系统与PHP进程监控:深入探索/proc文件系统

本文将深入探讨如何利用纯php语言,在不依赖外部shell命令的情况下,监控linux系统资源和php进程的详细信息。我们将重点介绍如何通过php的文件系统函数直接读取和解析`/proc`虚拟文件系统,从而获取系统负载、内存使用、活跃php进程数量及其资源消耗等全局数据,为系统管理员提供强大的php内建监控能力。

引言:纯PHP监控的挑战与机遇

在系统管理和性能优化中,实时了解服务器的运行状态和应用程序的资源消耗至关重要。对于PHP应用程序而言,除了单个脚本自身的内存使用(如通过memory_get_usage()获取)和系统整体负载(如通过sys_getload*g()获取)外,我们常常需要获取更全面的信息,例如当前所有活跃的PHP进程总数、它们占用的全局内存总量、由哪些用户运行、以及是否存在长时间运行的PHP进程等。

传统的做法可能涉及执行Shell命令(如ps aux | grep php、free -h等),但这在某些安全受限或追求纯PHP解决方案的环境中并不理想。幸运的是,在Linux系统上,PHP可以通过其标准的文件系统函数,直接访问一个名为/proc的特殊虚拟文件系统,从而获取这些详尽的系统和进程信息。

/proc文件系统:Linux上的信息宝库

/proc文件系统是一个独特且强大的虚拟文件系统,它不存储在磁盘上,而是由Linux内核在内存中动态生成。它提供了对内核数据结构、系统配置和当前运行进程的实时视图。每个正在运行的进程都会在/proc目录下创建一个以其PID(进程ID)命名的子目录,例如/proc/1234。这些进程目录中包含了大量关于该进程的信息文件,如进程状态、命令行参数、内存映射等。

PHP与/proc文件系统的交互方式与读取普通文件无异。我们可以使用file_get_contents()读取文件内容,使用scandir()遍历目录,从而以纯PHP代码的方式获取这些系统级和进程级的数据。

立即学习“PHP免费学习笔记(深入)”;

获取系统级信息

通过/proc文件系统,我们可以轻松获取系统整体的资源使用情况。

1. 系统负载

PHP内置的sys_getload*g()函数实际上就是对/proc/load*g文件的封装。该文件包含三个浮点数,分别表示过去1分钟、5分钟和15分钟的平均系统负载。

BlessAI BlessAI

Bless AI 提供五个独特的功能:每日问候、庆祝问候、祝福、祷告和名言的文本生成和图片生成。

BlessAI 135 查看详情 BlessAI

示例:直接读取/proc/load*g

<?php
function getSystemLoadAvg() {
    if (file_exists('/proc/load*g')) {
        $load*g_content = file_get_contents('/proc/load*g');
        $parts = explode(' ', $load*g_content);
        return [
            '1_min' => (float)$parts[0],
            '5_min' => (float)$parts[1],
            '15_min' => (float)$parts[2]
        ];
    }
    return null;
}

// $load = getSystemLoadAvg();
// if ($load) {
//     echo "System Load (1/5/15 min): {$load['1_min']} / {$load['5_min']} / {$load['15_min']}\n";
// }
?>

2. 全局内存使用

/proc/meminfo文件提供了系统内存的详细统计信息,包括总内存、可用内存、空闲内存、缓存、缓冲区等。

示例:读取/proc/meminfo

<?php
function getSystemMemoryInfo() {
    $memoryInfo = [];
    if (file_exists('/proc/meminfo')) {
        $meminfo_content = file_get_contents('/proc/meminfo');
        $lines = explode("\n", $meminfo_content);
        foreach ($lines as $line) {
            if (preg_match('/^(\w+):\s*(\d+)\s*kB$/', $line, $matches)) {
                $key = strtolower($matches[1]);
                $memoryInfo[$key] = (int)$matches[2]; // Value in KB
            }
        }
    }
    return $memoryInfo;
}

// $mem = getSystemMemoryInfo();
// if ($mem) {
//     echo "Total Memory: " . round($mem['memtotal'] / 1024 / 1024, 2) . " GB\n";
//     echo "Available Memory: " . round($mem['mem*ailable'] / 1024 / 1024, 2) . " GB\n";
// }
?>

监控PHP进程详情

获取单个PHP进程的详细信息是实现全局PHP环境监控的关键。

1. 进程目录结构与关键文件

每个进程在/proc下都有一个以其PID命名的目录,例如/proc/1234。在这个目录中,有几个文件对我们特别有用:

  • /proc/[PID]/status:包含进程的名称、状态、UID、GID以及各种内存使用统计(如VmRSS物理内存、VmSize虚拟内存等)。
  • /proc/[PID]/cmdline:包含进程启动时使用的完整命令行参数。这是识别PHP进程最直接的方式。
  • /proc/[PID]/stat:包含更底层的进程统计信息,包括进程的启动时间(以Jiffies为单位)。

2. 实现步骤

  1. 遍历PID目录: 使用scandir('/proc')获取所有目录和文件,然后过滤出纯数字命名的目录,这些就是进程PID。
  2. 识别PHP进程: 对于每个PID,读取/proc/[PID]/cmdline文件的内容。通过检查命令行参数是否包含“php”、“php-fpm”或“php-cgi”等关键字来判断它是否为一个PHP进程。
  3. 提取进程信息: 如果是PHP进程,读取/proc/[PID]/status文件,解析出进程名称、实际物理内存占用(VmRSS)、用户ID(Uid)等。
  4. 计算运行时长: 读取/proc/[PID]/stat文件,获取进程的启动时间(starttime字段),结合系统启动时间(从/proc/stat的btime字段获取)和系统时钟频率(通常为100 Jiffies/秒),可以计算出进程已运行的秒数。
  5. 汇总数据: 统计PHP进程总数、不同用户运行的进程数、总内存占用以及长时间运行的进程数。

示例代码:获取PHP进程概览

以下是一个完整的PHP函数,用于收集并汇总当前系统上所有PHP进程的关键信息:

<?php
/**
 * 获取当前系统上所有PHP进程的概览信息。
 * 仅适用于Linux系统,依赖于/proc文件系统。
 *
 * @return array 包含PHP进程总数、用户数、长时间运行进程数、总内存占用等信息的数组,
 *               或在出错时返回包含'error'键的数组。
 */
function getPhpProcessOverview() {
    $phpProcesses = [];
    $totalPhpMemoryKb = 0; // 所有PHP进程的VmRSS总和,单位KB
    $usersRunningPhp = []; // 存储运行PHP进程的用户UID
    $longRunningProcessesCount = 0; // 运行时间超过5分钟的PHP进程数量

    // 检查/proc文件系统是否存在,此功能为Linux特有
    if (!is_dir('/proc')) {
        return ['error' => '`/proc` filesystem not found. This feature is Linux-specific.'];
    }

    // 获取所有PID目录
    $pids = array_filter(scandir('/proc'), 'is_numeric');

    // 获取系统启动时间 (btime) 和时钟频率 (_SC_CLK_TCK)
    $systemBootTime = 0;
    $clockTicks = 100; // 常见的_SC_CLK_TCK值,通常为100 jiffies/秒
    if (file_exists('/proc/stat')) {
        $statFileContent = file_get_contents('/proc/stat');
        if (preg_match('/^btime\s*(\d+)/m', $statFileContent, $btimeMatches)) {
            $systemBootTime = (int)$btimeMatches[1];
        }
    }

    foreach ($pids as $pid) {
        $cmdlinePath = "/proc/{$pid}/cmdline";
        $statusPath = "/proc/{$pid}/status";
        $statPath = "/proc/{$pid}/stat";

        // 确保文件存在且可读
        if (file_exists($cmdlinePath) && file_exists($statusPath) && file_exists($statPath)) {
            $cmdline = file_get_contents($cmdlinePath);
            // cmdline内容通常以null字节分隔,替换为空格以便解析
            $cmdline = str_replace("\0", " ", $cmdline);

            // 通过命令行判断是否为PHP进程 (php, php-fpm, php-cgi等)
            if (preg_match('/php(?:-fpm|-cgi)?/i', $cmdline)) {
                $statusContent = file_get_contents($statusPath);
                $statContent = file_get_contents($statPath);

                $processInfo = [
                    'pid' => (int)$pid,
                    'name' => '',
                    'memory_rss_kb' => 0, // Resident Set Size (物理内存占用)
                    'uid' => '',
                    'uptime_seconds' => 0,
                    'cmdline' => trim($cmdline)
                ];

                // 解析status文件获取进程名、VmRSS和UID
                if (preg_match('/^Name:\s*(.*)$/m', $statusContent, $matches)) {
                    $processInfo['name'] = trim($matches[1]);
                }
                if (preg_match('/^VmRSS:\s*(\d+)\s*kB$/m', $statusContent, $matches)) {
                    $processInfo['memory_rss_kb'] = (int)$matches[1];
                    $totalPhpMemoryKb += (int)$matches[1];
                }
                if (preg_match('/^Uid:\s*(\d+)/m', $statusContent, $matches)) {
                    $processInfo['uid'] = $matches[1];
                    $usersRunningPhp[$matches[1]] = true; // 记录运行进程的用户
                }

                // 解析stat文件获取进程启动时间并计算运行时长
                // /proc/[PID]/stat 的第22个字段 (0-indexed 21) 是进程启动时间 (starttime)
                $statFields = explode(' ', $statContent);
                if (isset($statFields[21]) && $systemBootTime > 0) {
                    $startTimeJiffies = (int)$statFields[21];
                    // 进程启动时间(秒) = 系统启动时间(秒) + 进程启动时钟节拍 / 每秒时钟节拍
                    $processStartTimeSeconds = $systemBootTime + ($startTimeJiffies / $clockTicks);
                    $processUptimeSeconds = time() - $processStartTimeSeconds;
                    $processInfo['uptime_seconds'] = max(0, round($processUptimeSeconds));

                    // 判断是否为长时间运行进程 (例如,超过5分钟)
                    if ($processInfo['uptime_seconds'] > (5 * 60)) {
                        $longRunningProcessesCount++;
                    }
                }

                $phpProcesses[] = $processInfo;
            }
        }
    }

    return [
        'total_scripts_running' => count($phpProcesses),
        'users_running_process' => count($usersRunningPhp),
        'process_with_more_than_5_minutes' => $longRunningProcessesCount,
        'memory_global_assigned_to_all_php_kb' => $totalPhpMemoryKb,
        'details' => $phpProcesses // 包含每个PHP进程的详细信息
    ];
}

// 示例用法:
$overview = getPhpProcessOverview();

if (isset($overview['error'])) {
    echo "Error: " . $overview['error'] . "\n";
} else {
    echo "--- PHP 进程概览 ---\n";
    echo "总计运行中的PHP进程数: " . $overview['total_scripts_running'] . "\n";
    echo "运行PHP进程的用户数: " . $overview['users_running_process'] . "\n";
    echo "运行时间超过5分钟的PHP进程数: " . $overview['process_with_more_than_5_minutes'] . "\n";
    echo "所有PHP进程占用的总物理内存 (RSS): " . round($overview['memory_global_assigned_to_all_php_kb'] / 1024, 2) . " MB\n";
    echo "\n--- 

以上就是纯PHP实现系统与PHP进程监控:深入探索/proc文件系统的详细内容,更多请关注php中文网其它相关文章!


# linux  # php  # 长时间  # 遍历  # 命令行  # 文件系统  # 内存占用  # linux系统  # ai  # 虚拟内存  # 字节  # php函数  # 上海网络营销推广策划  # 内蒙古seo关键词排名价格  # seo咖啡加盟  # 刘连康seo视频  # 青岛网站建设入门必练  # 营销网站建设推广策略  # 太原抖音seo厂家  # 太仓品牌网站建设  # seo sem 工作  # 衡水教育网站推广方案  # 并与  # 以其  # 系统启动  # 是一个  # 数据结构 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894 】


相关推荐: 《顺丰同城骑士》查看我的技能方法  b站如何剪辑视频_b站必剪app使用教程  Windows自带的便笺数据如何备份_防止数据丢失的便利贴迁移教程【干货】  解决异步Python机器人中同步操作的阻塞问题  c++如何实现观察者设计模式_c++行为型设计模式实战  VS Code的时间线(Timeline)视图:您的代码时光机  鲁班大师乓乓皮肤获取方法  使用逻辑应用(Logic Apps)自动处理邮件附件中的XML到Excel  Scipy Sparse CSR 矩阵非零元素行级遍历的最佳实践  rabbitmq 持久化有什么缺点?  PHP实现等比数列:构建数组元素基于前一个值递增的方法  高德地图怎么查看未来行程规划_高德地图未来行程规划查看方法  《淘宝联盟》推广自己的店铺方法  Excel宏怎么删除_Excel中删除宏的详细操作流程  《绝区零》2.3前瞻|直播|内容介绍  《真我》申请退款方法  食品生产用水只要符合国家规定的生活饮用水卫生标准就可以吗  厨房地面防滑垫的油污怎么洗? 机洗和手洗防滑垫的注意事项  AO3中文入口稳定分享_AO3官网HTTPS看文详解  TikTok笔记文字无法编辑如何解决 TikTok笔记文字编辑优化方法  抖音号怎么解除企业认证改成个人?改成个人有影响吗?  使用AI在VS Code中将代码从一种语言翻译成另一种  有道AI翻译入口 智能写作官方网站入口  获取WooCommerce产品在后台编辑页面的分类ID  快递查询,一键速查  谷歌学术论文搜索引擎 谷歌学术官网入口论坛永久链接  SQL聚合查询、联接与筛选:GROUP BY 子句的正确使用与常见陷阱  顺丰快递收费标准查询_如何查看顺丰最新收费价格  鸣潮历史学家灯塔位置一览  windows10怎么开启wsl_windows10安装linux子系统教程  word文档行距怎么调?word文档调行距的操作步骤  手机远程连接电脑方法  iPhone 13 Pro Max如何设置桌面小组件_iPhone 13 Pro Max小组件添加指南  抖音小程序怎么开通?小程序开通条件是什么?  Mac怎么关闭按键声音_Mac键盘打字音效设置  《糖豆》添加舞曲方法  J*a中的值传递到底指什么_值传递模型在参数传递中的真正含义说明  如何在Golang中处理表单文件上传_Golang 表单文件上传示例  vivo浏览器怎么离线保存网页 vivo浏览器下载完整页面以便无网络时阅读  如何在mysql中设计餐饮点餐系统_mysql点餐系统项目实战  猫眼电影app如何设置电影上映提醒_猫眼电影上映提醒设置教程  三星M34录音变声问题_Samsung M34麦克风调整  优化CSS动画与J*aScript定时器协同:构建稳定Toast提示  Pandas中基于动态偏移量实现DataFrame列值位移的策略  POKI小游戏在线免费入口链接 POKI小游戏无下载秒玩玩  Go Goroutine调度与并发执行深度解析  TikTok视频播放中断怎么办 TikTok播放异常修复方法  msn官方入口2025登录 msn官网2025直达首页入口  我居然低估了 DeepSeek,这次更新它做到了这些!  《杖剑传说》食谱大全 

 2025-12-09

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.