pve安全温控
这里的pve版本为7.x
一、安装sensors
apt-get install lm-sensors
#探测下温度,执行:(一路yes,回车)
sensors-detect
#获取温度信息,执行:
sensors
ACPI interface那里是主板温度:temp1和temp2 (有些主板不一样,建议不管主板温度)
ISA adapter那里是CPU温度:Core0和Core1 (几个核心就是显示几个,演示机只有双核,所以只有2个)
#如果是全新安装,需要安装工具并重启 pveproxy 服务
apt-get install lm-sensors && apt-get install nvme-cli && apt-get install hddtemp && chmod +s /usr/sbin/nvme && chmod +s /usr/sbin/hddtemp && chmod +s /usr/sbin/smartctl && systemctl restart pveproxy
a) 如果是全新安装或者首次更新并使用 PVE 7.2+,需要安装工具并重启 pveproxy 服务:
apt-get install -y lm-sensors && chmod +s /usr/sbin/smartctl && systemctl restart pveproxy
b) 如果需要显示磁盘 I/O 信息,需要安装工具并重启 pveproxy 服务:
apt-get install -y sysstat && systemctl restart pveproxy
c) 如果是更新脚本,只需要重启 pveproxy 服务:
systemctl restart pveproxy1.1 修改web文件
在修改之前最好备份一下,防止出问题回退,下述的为。
1.2 修改/usr/share/perl5/PVE/API2/Nodes.pm
搜索
$res->{pveversion} = PVE::pvecfg::package()在下方插入
$res->{thermalstate} = `sensors`;如果是服务器12核的主板(E5-2678 v3)类似的:
my $cpufreqs = `lscpu | grep MHz`;
my $corefreqs = `cat /proc/cpuinfo | grep -i "cpu MHz"`;
$res->{cpu_frequency} = $cpufreqs . $corefreqs;
$res->{cpu_temperatures} = `sensors`;
my $nvme_ssd1_temperatures = `smartctl -a /dev/nvme0|grep -E "Model Number|Total NVM Capacity|Temperature:|Percentage|Data Unit|Power Cycles|Power On Hours|Unsafe Shutdowns"`;
my $nvme_ssd1_io = `iostat -d -x -k 1 1 | grep -E 'nvme0'`;
$res->{nvme_ssd1_status} = $nvme_ssd1_temperatures . $nvme_ssd1_io;
my $nvme_ssd2_temperatures = `smartctl -a /dev/nvme1|grep -E "Model Number|Total NVM Capacity|Temperature:|Percentage|Data Unit|Power Cycles|Power On Hours|Unsafe Shutdowns"`;
my $nvme_ssd2_io = `iostat -d -x -k 1 1 | grep -E 'nvme1'`;
$res->{nvme_ssd2_status} = $nvme_ssd2_temperatures . $nvme_ssd2_io;
my $hdd1_temperatures = `smartctl -a /dev/sda|grep -E "Model|Capacity|Power_On_Hours|Power_Cycle_Count|Unexpected_Power_Loss|Unexpect_Power_Loss_Ct|Temperature"`;
my $hdd1_io = `iostat -d -x -k 1 1 | grep -E 'sda'`;
$res->{hdd1_status} = $hdd1_temperatures . $hdd1_io;
my $hdd2_temperatures = `smartctl -a /dev/sdb|grep -E "Model|Capacity|Power_On_Hours|Power_Cycle_Count|Unexpected_Power_Loss|Unexpect_Power_Loss_Ct|Temperature"`;
my $hdd2_io = `iostat -d -x -k 1 1 | grep -E 'sdb'`;
$res->{hdd2_status} = $hdd2_temperatures . $hdd2_io;
my $hdd3_temperatures = `smartctl -a /dev/sdc|grep -E "Model|Capacity|Power_On_Hours|Power_Cycle_Count|Unexpected_Power_Loss|Unexpect_Power_Loss_Ct|Temperature"`;
my $hdd3_io = `iostat -d -x -k 1 1 | grep -E 'sdc'`;
$res->{hdd3_status} = $hdd3_temperatures . $hdd3_io;
my $hdd4_temperatures = `smartctl -a /dev/sdd|grep -E "Model|Capacity|Power_On_Hours|Power_Cycle_Count|Unexpected_Power_Loss|Unexpect_Power_Loss_Ct|Temperature"`;
my $hdd4_io = `iostat -d -x -k 1 1 | grep -E 'sdd'`;
$res->{hdd4_status} = $hdd4_temperatures . $hdd4_io;
my $hdd5_temperatures = `smartctl -a /dev/sde|grep -E "Model|Capacity|Power_On_Hours|Power_Cycle_Count|Unexpected_Power_Loss|Unexpect_Power_Loss_Ct|Temperature"`;
my $hdd5_io = `iostat -d -x -k 1 1 | grep -E 'sde'`;
$res->{hdd5_status} = $hdd5_temperatures . $hdd5_io;
1.3 修改/usr/share/pve-manager/js/pvemanagerlib.js
搜索
PVE Manager Version在这个json文件的节点后面添加:
这里是双核心:
{
itemId: 'thermal',
colspan: 2,
printBar: false,
title: gettext('CPU温度'),
textField: 'thermalstate',
renderer:function(value){
const p0 = value.match(/Package id 0.*?\+([\d\.]+)Â/)[1];
const c0 = value.match(/Core 0.*?\+([\d\.]+)Â/)[1];
const c1 = value.match(/Core 1.*?\+([\d\.]+)Â/)[1];
const b0 = value.match(/temp1.*?\+([\d\.]+)?/)[1];
const b1 = value.match(/temp2.*?\+([\d\.]+)?/)[1];
return `Package: ${p0} ℃ || 核心1: ${c0} ℃ | 核心2: ${c1} ℃ || 主板: ${b0} ℃ | ${b1} ℃ `
}
},这是四核心的:
{
itemId: 'thermal',
colspan: 2,
printBar: false,
title: gettext('CPU温度'),
textField: 'thermalstate',
renderer:function(value){
const p0 = value.match(/Package id 0.*?\+([\d\.]+)Â/)[1];
const c0 = value.match(/Core 0.*?\+([\d\.]+)Â/)[1];
const c1 = value.match(/Core 1.*?\+([\d\.]+)Â/)[1];
const c2 = value.match(/Core 2.*?\+([\d\.]+)Â/)[1];
const c3 = value.match(/Core 3.*?\+([\d\.]+)Â/)[1];
return `Package: ${p0} ℃ || 核心1: ${c0} ℃ | 核心2: ${c1} ℃ | 核心3: ${c2} ℃ | 核心4: ${c3} ℃ `
}
},12核心的
{
itemId: 'cpu-frequency',
colspan: 2,
printBar: false,
title: gettext('CPU主频'),
textField: 'cpu_frequency',
renderer:function(value){
let output = '';
let cpufreqs = value.matchAll(/^CPU MHz.*?(\d+\.\d+)\n^CPU max MHz.*?(\d+)\.\d+\n^CPU min MHz.*?(\d+)\.\d+\n/gm);
for (const cpufreq of cpufreqs) {
output += `实时: ${cpufreq[1]} MHz | 最低: ${cpufreq[3]} MHz | 最高: ${cpufreq[2]} MHz\n`;
}
let corefreqs = value.match(/^cpu MHz.*?(\d+\.\d+)/gm);
if (corefreqs.length > 0) {
for (i = 1;i < corefreqs.length;) {
for (const corefreq of corefreqs) {
output += `线程 ${i++}: ${corefreq.match(/(?<=:\s+)(\d+\.\d+)/g)} MHz`;
output += ' | ';
if ((i-1) % 4 == 0){
output = output.slice(0, -2);
output += '\n';
}
}
}
} else {
output += '(';
output += `${corefreqs}`;
output += ')';
}
return output.replace(/\n/g, '<br>');
}
},
{
itemId: 'cpu-temperatures',
colspan: 2,
printBar: false,
title: gettext('CPU温度'),
textField: 'cpu_temperatures',
renderer: function(value) {
value = value.replace(/Â/g, '');
let data = [];
let cpus = value.matchAll(/^coretemp-isa-(\d{4})$\n.*?\n((?:Package|Core)[\s\S]*?^\n)+/gm);
for (const cpu of cpus) {
let cpuNumber = parseInt(cpu[1], 10);
data[cpuNumber] = {
packages: [],
cores: []
};
let packages = cpu[2].matchAll(/^Package id \d+:\s*\+([^°]+).*$/gm);
for (const package of packages) {
data[cpuNumber]['packages'].push(package[1]);
}
let cores = cpu[2].matchAll(/^Core \d+:\s*\+([^°]+).*$/gm);
for (const core of cores) {
data[cpuNumber]['cores'].push(core[1]);
}
}
let output = '';
for (const [i, cpu] of data.entries()) {
if (cpu.packages.length > 0) {
for (const packageTemp of cpu.packages) {
output += `CPU ${i+1}: ${packageTemp}°C `;
}
}
if (cpu.cores.length > 0) {
output += '(';
for (j = 1;j < cpu.cores.length;) {
for (const coreTemp of cpu.cores) {
output += `核心 ${j++}: ${coreTemp}°C, `;
}
}
output = output.slice(0, -2);
output += ')';
}
}
let acpitzs = value.matchAll(/acpitz-acpi-(\d*)\n.*?\n((?:temp)[\s\S]*?\n)+/gm);
for (const acpitz of acpitzs) {
let acpitzNumber = parseInt(acpitz[1], 10);
data[acpitzNumber] = {
acpisensors: []
};
let acpisensors = acpitz[2].matchAll(/^temp\d+:\s*\+([^°]+).*$/gm);
for (const acpisensor of acpisensors) {
data[acpitzNumber]['acpisensors'].push(acpisensor[1]);
}
for (const [k, acpitz] of data.entries()) {
if (acpitz.acpisensors.length > 0) {
output += ' | 主板: ';
for (m = 1; m <= acpitz.acpisensors.length; m++) {
for (const acpiTemp of acpitz.acpisensors) {
output += `${acpiTemp}°C, `;
}
}
output = output.slice(0, -2);
}
}
}
return output;
}
},
{
itemId: 'nvme_ssd1-status',
colspan: 2,
printBar: false,
title: gettext('NVME硬盘 1'),
textField: 'nvme_ssd1_status',
renderer:function(value){
if (value.length > 0) {
let nvmedevices = value.matchAll(/^Model.*:\s*([\s\S]*?)\n(^Total.*\[[\s\S]*?\]){0,1}\n{0,1}^Temperature:\s*(\d+)\s*Celsius\n^Percentage.*(\d+\%)\n^Data Units.*\[([\s\S]*?)\]\n^Data Units.*\[([\s\S]*?)\]\n^Power Cycles:\s*([\s\S]*?)\n^Power On Hours:\s*([\s\S]*?)\n^Unsafe Shutdowns.*:\s*([\s\S]*?)\nnvme\S+((\s*?\d+\.\d{2}){22})/gm);
for (const nvmedevice of nvmedevices) {
nvmemodel = nvmedevice[1].replace(/^Model.*:\s*([\s\S]*?)/m, '$1');
if (value.indexOf("Capacity") !== -1){
nvmecapacity = nvmedevice[2].replace(/.*\[([\s\S]*?)\]/m, '$1');
nvmecapacity = nvmecapacity.replace(/ /, '');
nvmecapacity = ` | 容量: ${nvmecapacity}`;
} else {
nvmecapacity = ``;
}
nvmepowerhour = nvmedevice[8].replace(/ |,/gm, '');
nvme_status = nvmedevice[10].replace(/\s+/gm, ',');
nvme_status = nvme_status.replace(/^,/gm, '');
nvme_status = nvme_status.split(",");
nvme_r_await = nvme_status[4]
nvme_w_await = nvme_status[10]
nvme_util = nvme_status[21]
if(value.indexOf("Cycles") !== -1){
nvmepowercycle = `${nvmedevice[7]}次`;
let nvmepowerloss = '';
if(value.indexOf("Unsafe") !== -1){
nvmepowerloss = `, 不安全断电${nvmedevice[9]}次`;
}
nvmepowercount = `${nvmepowercycle}${nvmepowerloss}`;
value = `${nvmemodel}${nvmecapacity} | 寿命: ${nvmedevice[4]} (读取: ${nvmedevice[5].replace(/ /, '')}, 写入: ${nvmedevice[6].replace(/ /, '')}) | 温度: ${nvmedevice[3]}°C\n通电: ${nvmepowercount}, 累计${nvmepowerhour}小时 | I/O: 读延迟${nvme_r_await}ms, 写延迟${nvme_w_await}ms, 负载${nvme_util}%\n`;
} else {
value = `${nvmemodel}${nvmecapacity} | 寿命: ${nvmedevice[4]} (读取: ${nvmedevice[5].replace(/ /, '')}, 写入: ${nvmedevice[6].replace(/ /, '')}) | 通电: ${nvmepowerhour}小时 | I/O: 读延迟${nvme_r_await}ms, 写延迟${nvme_w_await}ms, 负载${nvme_util}% | 温度: ${nvmedevice[31]}°C\n`;
}
}
return value.replace(/\n/g, '<br>');
} else {
return `提示: 未安装硬盘或已直通硬盘控制器`;
}
}
},
{
itemId: 'nvme_ssd2-status',
colspan: 2,
printBar: false,
title: gettext('NVME硬盘 2'),
textField: 'nvme_ssd2_status',
renderer:function(value){
if (value.length > 0) {
let nvmedevices = value.matchAll(/^Model.*:\s*([\s\S]*?)\n(^Total.*\[[\s\S]*?\]){0,1}\n{0,1}^Temperature:\s*(\d+)\s*Celsius\n^Percentage.*(\d+\%)\n^Data Units.*\[([\s\S]*?)\]\n^Data Units.*\[([\s\S]*?)\]\n^Power Cycles:\s*([\s\S]*?)\n^Power On Hours:\s*([\s\S]*?)\n^Unsafe Shutdowns.*:\s*([\s\S]*?)\nnvme\S+((\s*?\d+\.\d{2}){22})/gm);
for (const nvmedevice of nvmedevices) {
nvmemodel = nvmedevice[1].replace(/^Model.*:\s*([\s\S]*?)/m, '$1');
if (value.indexOf("Capacity") !== -1){
nvmecapacity = nvmedevice[2].replace(/.*\[([\s\S]*?)\]/m, '$1');
nvmecapacity = nvmecapacity.replace(/ /, '');
nvmecapacity = ` | 容量: ${nvmecapacity}`;
} else {
nvmecapacity = ``;
}
nvmepowerhour = nvmedevice[8].replace(/ |,/gm, '');
nvme_status = nvmedevice[10].replace(/\s+/gm, ',');
nvme_status = nvme_status.replace(/^,/gm, '');
nvme_status = nvme_status.split(",");
nvme_r_await = nvme_status[4]
nvme_w_await = nvme_status[10]
nvme_util = nvme_status[21]
if(value.indexOf("Cycles") !== -1){
nvmepowercycle = `${nvmedevice[7]}次`;
let nvmepowerloss = '';
if(value.indexOf("Unsafe") !== -1){
nvmepowerloss = `, 不安全断电${nvmedevice[9]}次`;
}
nvmepowercount = `${nvmepowercycle}${nvmepowerloss}`;
value = `${nvmemodel}${nvmecapacity} | 寿命: ${nvmedevice[4]} (读取: ${nvmedevice[5].replace(/ /, '')}, 写入: ${nvmedevice[6].replace(/ /, '')}) | 温度: ${nvmedevice[3]}°C\n通电: ${nvmepowercount}, 累计${nvmepowerhour}小时 | I/O: 读延迟${nvme_r_await}ms, 写延迟${nvme_w_await}ms, 负载${nvme_util}%\n`;
} else {
value = `${nvmemodel}${nvmecapacity} | 寿命: ${nvmedevice[4]} (读取: ${nvmedevice[5].replace(/ /, '')}, 写入: ${nvmedevice[6].replace(/ /, '')}) | 通电: ${nvmepowerhour}小时 | I/O: 读延迟${nvme_r_await}ms, 写延迟${nvme_w_await}ms, 负载${nvme_util}% | 温度: ${nvmedevice[31]}°C\n`;
}
}
return value.replace(/\n/g, '<br>');
} else {
return `提示: 未安装硬盘或已直通硬盘控制器`;
}
}
},
{
itemId: 'hdd1-status',
colspan: 2,
printBar: false,
title: gettext('SATA硬盘 1'),
textField: 'hdd1_status',
renderer:function(value){
if (value.length > 0) {
let devices = value.matchAll(/(\s*Model.*:\s*[\s\S]*?\n){1,2}^User.*\[([\s\S]*?)\]\n^\s*9[\s\S]*?\-\s*(\d+)[\s\S]*?\n(^\s*12[\s\S]*?\-\s*\d+[\s\S]*?\n){0,1}(^174[\s\S]*?\-\s*\d+[\s\S]*?\n){0,1}(^19[0,4][\s\S]*?$){0,2}\nsd\S+((\s*?\d+\.\d{2}){22})/gm);
for (const device of devices) {
if(device[1].indexOf("Family") !== -1){
devicemodel = device[1].replace(/.*Model Family:\s*([\s\S]*?)\n^Device Model:\s*([\s\S]*?)\n/m, '$1 - $2');
} else {
devicemodel = device[1].replace(/.*Model:\s*([\s\S]*?)\n/m, '$1');
}
devicecapacity = device[2].replace(/ |,/gm, '');
if (value.indexOf("Temperature") !== -1){
devicetemp = device[6].replace(/19[0,4].*[\-|In_the_past]\s*(\d+).*/m, '温度: $1°C');
} else {
devicetemp = `提示: 未检测到温度传感器`;
}
devicepowerhour = device[3].replace(/ |,/gm, '');
device_status = device[7].replace(/\s+/gm, ',');
device_status = device_status.replace(/^,/gm, '');
device_status = device_status.split(",");
device_r_await = device_status[4]
device_w_await = device_status[10]
device_util = device_status[21]
if(value.indexOf("Cycle_Count") !== -1){
devicepowercycle = device[4].replace(/^\s*12[\s\S]*?\-\s*(\d+)[\s\S]*?\n/m, '$1次');
let devicepowerloss = '';
if(value.indexOf("Power_Loss") !== -1){
devicepowerloss = device[5].replace(/^174[\s\S]*?\-\s*(\d+)[\s\S]*?\n/m, ', 不安全断电$1次');
}
devicepowercount = `${devicepowercycle}${devicepowerloss}`;
value = `${devicemodel} | 容量: ${devicecapacity} | ${devicetemp}\n通电: ${devicepowercount}, 累计${devicepowerhour}小时 | I/O: 读延迟${device_r_await}ms, 写延迟${device_w_await}ms, 负载${device_util}%\n`;
} else {
value = `${devicemodel} | 容量: ${devicecapacity} | 通电: ${devicepowerhour}小时 | I/O: 读延迟${device_r_await}ms, 写延迟${device_w_await}ms, 负载${device_util}% | ${devicetemp}\n`;
}
}
return value.replace(/\n/g, '<br>');
} else {
return `提示: 未安装硬盘或已直通硬盘控制器`;
}
}
},
{
itemId: 'hdd2-status',
colspan: 2,
printBar: false,
title: gettext('SATA硬盘 2'),
textField: 'hdd2_status',
renderer:function(value){
if (value.length > 0) {
let devices = value.matchAll(/(\s*Model.*:\s*[\s\S]*?\n){1,2}^User.*\[([\s\S]*?)\]\n^\s*9[\s\S]*?\-\s*(\d+)[\s\S]*?\n(^\s*12[\s\S]*?\-\s*\d+[\s\S]*?\n){0,1}(^174[\s\S]*?\-\s*\d+[\s\S]*?\n){0,1}(^19[0,4][\s\S]*?$){0,2}\nsd\S+((\s*?\d+\.\d{2}){22})/gm);
for (const device of devices) {
if(device[1].indexOf("Family") !== -1){
devicemodel = device[1].replace(/.*Model Family:\s*([\s\S]*?)\n^Device Model:\s*([\s\S]*?)\n/m, '$1 - $2');
} else {
devicemodel = device[1].replace(/.*Model:\s*([\s\S]*?)\n/m, '$1');
}
devicecapacity = device[2].replace(/ |,/gm, '');
if (value.indexOf("Temperature") !== -1){
devicetemp = device[6].replace(/19[0,4].*[\-|In_the_past]\s*(\d+).*/m, '温度: $1°C');
} else {
devicetemp = `提示: 未检测到温度传感器`;
}
devicepowerhour = device[3].replace(/ |,/gm, '');
device_status = device[7].replace(/\s+/gm, ',');
device_status = device_status.replace(/^,/gm, '');
device_status = device_status.split(",");
device_r_await = device_status[4]
device_w_await = device_status[10]
device_util = device_status[21]
if(value.indexOf("Cycle_Count") !== -1){
devicepowercycle = device[4].replace(/^\s*12[\s\S]*?\-\s*(\d+)[\s\S]*?\n/m, '$1次');
let devicepowerloss = '';
if(value.indexOf("Power_Loss") !== -1){
devicepowerloss = device[5].replace(/^174[\s\S]*?\-\s*(\d+)[\s\S]*?\n/m, ', 不安全断电$1次');
}
devicepowercount = `${devicepowercycle}${devicepowerloss}`;
value = `${devicemodel} | 容量: ${devicecapacity} | ${devicetemp}\n通电: ${devicepowercount}, 累计${devicepowerhour}小时 | I/O: 读延迟${device_r_await}ms, 写延迟${device_w_await}ms, 负载${device_util}%\n`;
} else {
value = `${devicemodel} | 容量: ${devicecapacity} | 通电: ${devicepowerhour}小时 | I/O: 读延迟${device_r_await}ms, 写延迟${device_w_await}ms, 负载${device_util}% | ${devicetemp}\n`;
}
}
return value.replace(/\n/g, '<br>');
} else {
return `提示: 未安装硬盘或已直通硬盘控制器`;
}
}
},
{
itemId: 'hdd3-status',
colspan: 2,
printBar: false,
title: gettext('SATA硬盘 3'),
textField: 'hdd3_status',
renderer:function(value){
if (value.length > 0) {
let devices = value.matchAll(/(\s*Model.*:\s*[\s\S]*?\n){1,2}^User.*\[([\s\S]*?)\]\n^\s*9[\s\S]*?\-\s*(\d+)[\s\S]*?\n(^\s*12[\s\S]*?\-\s*\d+[\s\S]*?\n){0,1}(^174[\s\S]*?\-\s*\d+[\s\S]*?\n){0,1}(^19[0,4][\s\S]*?$){0,2}\nsd\S+((\s*?\d+\.\d{2}){22})/gm);
for (const device of devices) {
if(device[1].indexOf("Family") !== -1){
devicemodel = device[1].replace(/.*Model Family:\s*([\s\S]*?)\n^Device Model:\s*([\s\S]*?)\n/m, '$1 - $2');
} else {
devicemodel = device[1].replace(/.*Model:\s*([\s\S]*?)\n/m, '$1');
}
devicecapacity = device[2].replace(/ |,/gm, '');
if (value.indexOf("Temperature") !== -1){
devicetemp = device[6].replace(/19[0,4].*[\-|In_the_past]\s*(\d+).*/m, '温度: $1°C');
} else {
devicetemp = `提示: 未检测到温度传感器`;
}
devicepowerhour = device[3].replace(/ |,/gm, '');
device_status = device[7].replace(/\s+/gm, ',');
device_status = device_status.replace(/^,/gm, '');
device_status = device_status.split(",");
device_r_await = device_status[4]
device_w_await = device_status[10]
device_util = device_status[21]
if(value.indexOf("Cycle_Count") !== -1){
devicepowercycle = device[4].replace(/^\s*12[\s\S]*?\-\s*(\d+)[\s\S]*?\n/m, '$1次');
let devicepowerloss = '';
if(value.indexOf("Power_Loss") !== -1){
devicepowerloss = device[5].replace(/^174[\s\S]*?\-\s*(\d+)[\s\S]*?\n/m, ', 不安全断电$1次');
}
devicepowercount = `${devicepowercycle}${devicepowerloss}`;
value = `${devicemodel} | 容量: ${devicecapacity} | ${devicetemp}\n通电: ${devicepowercount}, 累计${devicepowerhour}小时 | I/O: 读延迟${device_r_await}ms, 写延迟${device_w_await}ms, 负载${device_util}%\n`;
} else {
value = `${devicemodel} | 容量: ${devicecapacity} | 通电: ${devicepowerhour}小时 | I/O: 读延迟${device_r_await}ms, 写延迟${device_w_await}ms, 负载${device_util}% | ${devicetemp}\n`;
}
}
return value.replace(/\n/g, '<br>');
} else {
return `提示: 未安装硬盘或已直通硬盘控制器`;
}
}
},
{
itemId: 'hdd4-status',
colspan: 2,
printBar: false,
title: gettext('SATA硬盘 4'),
textField: 'hdd4_status',
renderer:function(value){
if (value.length > 0) {
let devices = value.matchAll(/(\s*Model.*:\s*[\s\S]*?\n){1,2}^User.*\[([\s\S]*?)\]\n^\s*9[\s\S]*?\-\s*(\d+)[\s\S]*?\n(^\s*12[\s\S]*?\-\s*\d+[\s\S]*?\n){0,1}(^174[\s\S]*?\-\s*\d+[\s\S]*?\n){0,1}(^19[0,4][\s\S]*?$){0,2}\nsd\S+((\s*?\d+\.\d{2}){22})/gm);
for (const device of devices) {
if(device[1].indexOf("Family") !== -1){
devicemodel = device[1].replace(/.*Model Family:\s*([\s\S]*?)\n^Device Model:\s*([\s\S]*?)\n/m, '$1 - $2');
} else {
devicemodel = device[1].replace(/.*Model:\s*([\s\S]*?)\n/m, '$1');
}
devicecapacity = device[2].replace(/ |,/gm, '');
if (value.indexOf("Temperature") !== -1){
devicetemp = device[6].replace(/19[0,4].*[\-|In_the_past]\s*(\d+).*/m, '温度: $1°C');
} else {
devicetemp = `提示: 未检测到温度传感器`;
}
devicepowerhour = device[3].replace(/ |,/gm, '');
device_status = device[7].replace(/\s+/gm, ',');
device_status = device_status.replace(/^,/gm, '');
device_status = device_status.split(",");
device_r_await = device_status[4]
device_w_await = device_status[10]
device_util = device_status[21]
if(value.indexOf("Cycle_Count") !== -1){
devicepowercycle = device[4].replace(/^\s*12[\s\S]*?\-\s*(\d+)[\s\S]*?\n/m, '$1次');
let devicepowerloss = '';
if(value.indexOf("Power_Loss") !== -1){
devicepowerloss = device[5].replace(/^174[\s\S]*?\-\s*(\d+)[\s\S]*?\n/m, ', 不安全断电$1次');
}
devicepowercount = `${devicepowercycle}${devicepowerloss}`;
value = `${devicemodel} | 容量: ${devicecapacity} | ${devicetemp}\n通电: ${devicepowercount}, 累计${devicepowerhour}小时 | I/O: 读延迟${device_r_await}ms, 写延迟${device_w_await}ms, 负载${device_util}%\n`;
} else {
value = `${devicemodel} | 容量: ${devicecapacity} | 通电: ${devicepowerhour}小时 | I/O: 读延迟${device_r_await}ms, 写延迟${device_w_await}ms, 负载${device_util}% | ${devicetemp}\n`;
}
}
return value.replace(/\n/g, '<br>');
} else {
return `提示: 未安装硬盘或已直通硬盘控制器`;
}
}
},
{
itemId: 'hdd5-status',
colspan: 2,
printBar: false,
title: gettext('SATA硬盘 5'),
textField: 'hdd5_status',
renderer:function(value){
if (value.length > 0) {
let devices = value.matchAll(/(\s*Model.*:\s*[\s\S]*?\n){1,2}^User.*\[([\s\S]*?)\]\n^\s*9[\s\S]*?\-\s*(\d+)[\s\S]*?\n(^\s*12[\s\S]*?\-\s*\d+[\s\S]*?\n){0,1}(^174[\s\S]*?\-\s*\d+[\s\S]*?\n){0,1}(^19[0,4][\s\S]*?$){0,2}\nsd\S+((\s*?\d+\.\d{2}){22})/gm);
for (const device of devices) {
if(device[1].indexOf("Family") !== -1){
devicemodel = device[1].replace(/.*Model Family:\s*([\s\S]*?)\n^Device Model:\s*([\s\S]*?)\n/m, '$1 - $2');
} else {
devicemodel = device[1].replace(/.*Model:\s*([\s\S]*?)\n/m, '$1');
}
devicecapacity = device[2].replace(/ |,/gm, '');
if (value.indexOf("Temperature") !== -1){
devicetemp = device[6].replace(/19[0,4].*[\-|In_the_past]\s*(\d+).*/m, '温度: $1°C');
} else {
devicetemp = `提示: 未检测到温度传感器`;
}
devicepowerhour = device[3].replace(/ |,/gm, '');
device_status = device[7].replace(/\s+/gm, ',');
device_status = device_status.replace(/^,/gm, '');
device_status = device_status.split(",");
device_r_await = device_status[4]
device_w_await = device_status[10]
device_util = device_status[21]
if(value.indexOf("Cycle_Count") !== -1){
devicepowercycle = device[4].replace(/^\s*12[\s\S]*?\-\s*(\d+)[\s\S]*?\n/m, '$1次');
let devicepowerloss = '';
if(value.indexOf("Power_Loss") !== -1){
devicepowerloss = device[5].replace(/^174[\s\S]*?\-\s*(\d+)[\s\S]*?\n/m, ', 不安全断电$1次');
}
devicepowercount = `${devicepowercycle}${devicepowerloss}`;
value = `${devicemodel} | 容量: ${devicecapacity} | ${devicetemp}\n通电: ${devicepowercount}, 累计${devicepowerhour}小时 | I/O: 读延迟${device_r_await}ms, 写延迟${device_w_await}ms, 负载${device_util}%\n`;
} else {
value = `${devicemodel} | 容量: ${devicecapacity} | 通电: ${devicepowerhour}小时 | I/O: 读延迟${device_r_await}ms, 写延迟${device_w_await}ms, 负载${device_util}% | ${devicetemp}\n`;
}
}
return value.replace(/\n/g, '<br>');
} else {
return `提示: 未安装硬盘或已直通硬盘控制器`;
}
}
}
重启服务
systemctl restart pveproxy