PVE安装后初始是不带CPU频率和各温度监控器显示的,本篇教程将带大家修改pve的文件,以实现自定义频率和温度显示!

一、安装sensors温度检测工具

1.1.安装

首先我们需要SSH连接PVE后,安装sensors温度检测工具

apt update -y && apt install sensors -y

1.2.初始化设置

安装好后,使用sensors-detect进行初始化设置

sensors-detect

这里通常情况全部ENTER回车键确认即可(即直接使用默认值)

image-20240124173238727

1.3.测试温度传感器

这里我们使用命令 sensors 查看一下温度传感器是否正常获取到温度值了

image-20240124173448211

可以看到温度获取正常,但是为了方便处理数据,我们后续使用的命令是:sensors -j

-j 表示用 JSON 格式输出传感器数据

image-20240124173615330

1.4.安装ups控制工具

此处跳过,可以去看我写的另一篇教程PVE与TG-BOX600 UPS系统联动断电自动关机(linux通用)

二、修改PVE文件,添加修改代码

2.1 编辑api文件代码

文件路径:/usr/share/perl5/PVE/API2/Nodes.pm

可以使用sftp等工具copy到自己电脑上方便修改,或者使用vi和nano直接打开,我这里直接copy后使用notepad++打开修改

定位编辑位置,查找内容:$res->{ksm} = {

....
$res->{ksm} = {
        shared => $meminfo->{memshared},
    };
$res->{cpure} = cat /proc/cpuinfo | grep -i  "cpu mhz"; #cpu频率
$res->{sensinfo} = sensors -j; #JSON格式输出传感器数据
$res->{hddtemp} = hddtemp /dev/sd?;    #硬盘温度
$res->{apcaccess} = apcaccess; #ups信息
...

参考上面示例,添加代码:

$res->{cpure} = cat /proc/cpuinfo | grep -i "cpu mhz"; #cpu频率

$res->{sensinfo} = sensors -j; #JSON格式输出传感器数据

$res->{hddtemp} = hddtemp /dev/sd?; #硬盘温度

image-20240124174635346

2.2 编辑界面js文件代码

文件路径:/usr/share/pve-manager/js/pvemanagerlib.js

定位编辑位置,查找内容:Proxmox.Utils.render_cpu_model,

{
        itemId: 'cpus',
        colspan: 2,
        printBar: false,
        title: gettext('CPU(s)'),
        textField: 'cpuinfo',
        renderer: Proxmox.Utils.render_cpu_model,
        value: '',
    },
//在这后面添加以下内容
    {
      itemId: 'cpumhz',
      colspan: 2,
      printBar: false,
      title: gettext('CPU频率'),
      textField: 'cpure',
      renderer:function(value){
            const m = value.match(/(?<=:\s+)(\d+)/g);
            return CPUMHZ: ${m[0]} | ${m[1]} | ${m[2]} | ${m[3]};
        }
    },
    {
        itemId: 'sensinfo',

        colspan: 2,

        printBar: false,

        title:gettext('温度传感器'),  // WEB显示内容

        textField:'sensinfo',

        renderer:function(value){

        value = JSON.parse(value.replaceAll('Â', ''));

        const z1 = value['acpitz-acpi-0']['temp1']['temp1_input'].toFixed(1);

        const z2 = value['acpitz-acpi-0']['temp2']['temp2_input'].toFixed(1);

        const cp = value['coretemp-isa-0000']['Package id 0']['temp1_input'].toFixed(1);
        const c0 = value['coretemp-isa-0000']['Core 0']['temp2_input'].toFixed(1);
        const c1 = value['coretemp-isa-0000']['Core 1']['temp3_input'].toFixed(1);

        //const c2 = value['coretemp-isa-0000']['Core 2']['temp4_input'].toFixed(1);

        //const c3 = value['coretemp-isa-0000']['Core 3']['temp5_input'].toFixed(1);

        //const f1 = value['it8786-isa-0a40']['fan1']['fan1_input'].toFixed(1);
        const n0 =value['nvme-pci-0d00']['Composite']['temp1_input'].toFixed(1);
        return CPU温度: ${cp}℃ (${c0}℃,${c1}℃) <br> 主板温度:${z1}℃ | ${z2}℃ <br> 固态硬盘温度:${n0}℃;  // 输出格式

            }

    },
    {
            itemId: 'hddtemp',
            colspan: 2,
            printBar: false,
            title: gettext('HDD温度'),
            textField: 'hddtemp',
            renderer: function(value) {
                value = value.replace(/Â/g, '');
                return value.replace(/\n/g, '<br>')
            }
    },
    {    
        itemId: 'apcaccess',    
        colspan: 2,    
        printBar: false,    
        title: gettext('UPS信息'),    
        textField: 'apcaccess',    
        renderer: function(value) {    
            let result = {};  
            const lines = value.split(/\r?\n/); // 根据换行符分割字符串  

             lines.forEach(line => {  
                const parts = line.trim().split(/:\s*/); // 尝试按冒号和空格分割  
                if (parts.length > 1) {  
                    const key = parts[0].trim();  
                    let value = parts.slice(1).join(': ').trim(); // 默认情况下,将剩余部分作为值  

                    // 特殊处理 DATE 字段,假设它可能包含空格分隔的年、月、日、时、分、秒和时区  
                    if (key === 'DATE') {  
                        // 使用正则表达式来匹配并提取完整的日期时间字符串  
                        const dateMatch = value.match(/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2}) ([+-]\d{4})$/);  
                        if (dateMatch) {  
                            // 重新组合日期时间字符串(如果需要的话,这里可以根据实际格式进行调整)  
                            value = ${dateMatch[1]}-${dateMatch[2]}-${dateMatch[3]} ${dateMatch[4]}:${dateMatch[5]}:${dateMatch[6]} ${dateMatch[7]};  
                        }  
                    }  

                    // 存储到对象中  
                    result[key] = value;  
                }  
            });  

            return `UPS名称:${result.UPSNAME || '未知'} 
更新时间:${result.DATE || '未知'}
状态:${result.STATUS || '未知'}
输出电压:${result.OUTPUTV || '未知'}
负载:${result.LOADPCT.replace(' Percent', '') || '未知'} %
电池电量:${result.BCHARGE.replace(' Percent', '') || '未知'} %
电池可供电时间:${result.TIMELEFT || '未知'}`; } },

代码解释:

回到文章前用 sensors -j 输出传感器参数那段

image-20240124175402062

"coretemp-isa-0000" 是 CPU 传感器,其中 "Core 0" 是核心编号,"temp2_input": 56.000 是核心温度

"Package id 0" 是封装传感器,对应的 "temp1_input": xx.000 是封装温度,具体看代码

"acpitz-acpi-0" 是主板传感器,对应的参数大伙看自己的代码

PS:由于我的主板是技嘉z270n主板,直接biso接管机箱风扇控制,故风扇代码使用“//”注释了;cpu为双核4线程的G5500,注释了剩下两个核心温度

转速在 "it8786-isa-0a40" 模块中的 "fan1" 或者 "fan2",看具体插在 CPU 或者 SYS 针脚上

return 输出显示详解:

获取数据格式为【const xxxx = value['xxxx']['xxxx']['xxxx_input'].toFixed(1)】

【result】输出字符串的格式根据实际情况或者个人需求进行修改

2.3 修改布局显示

还是这个js文件:/usr/share/pve-manager/js/pvemanagerlib.js

定位编辑位置。

查找内容:Ext.create('Ext.window.Window', {

image-20240124180608781

继续查找内容跳转:widget.pveNodeStatus

image-20240124180629501

两处 height 的值需按情况修改,每多一行数据增加 20。根据实际情况修改,比如不想看到订阅,可适当调整

三、重启 PVE WEB 服务

输入代码:systemctl restart pveproxy

等待几秒钟后,刷新PVE管理网页或者重新打开PVE管理页面


参考资料:

是一名喜欢每天折腾的咸鱼!
也是一名半退役的算竞摸鱼选手,参与过icpc,天梯赛,蓝桥等比赛.
---------------------------------------------------
百度 飞桨领航团-团长
Datawhale -鲸英助教团成员
上海人工智能实验室 书生·浦语实战营- 助教
---------------------------------------------------
认证类:
华为 Harmony OS应用开发者高级认证,
NISP 一级认证,
H3C NE-RS网络工程师认证
---------------------------------------------------
荣获奖项荣誉:
第十八届“挑战杯”全国大学生课外学术科技作品竞赛 “揭榜挂帅”专项赛-全国特等奖、
“美亚杯”第八届中国电子取证大赛 三等奖、
“蓝桥杯”国优、
中国高校计算机大赛-团体程序天梯赛 省高校一等奖、
“蓝桥杯”省一等奖、
H3C新华三杯 省三等奖、
中国移动“梧桐杯”大数据创新大赛 省三等奖、
百度 飞桨领航团 金牌团长
最后更新于 2024-07-05