From aeea8e89bc3abf468ad325c46a1d598d23f2809e Mon Sep 17 00:00:00 2001 From: rmm Date: Sat, 27 Apr 2024 09:17:07 +0200 Subject: [PATCH 1/2] Fix grammar issue/typo in readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 6215dc3..4fe310f 100644 --- a/readme.md +++ b/readme.md @@ -12,7 +12,7 @@ The modification includes three main steps: 1. Create backups of the original files located at `/usr/share/pve-manager/js/pvemanagerlib.js` and `/usr/share/perl5/PVE/API2/Nodes.pm` in the `backup` directory relative to the script location. 2. Add a new line to the `Nodes.pm` file that enables host system sensor readings using the `sensors` command. -3. Modify the `pvemanagerlib.js` file to expand the space in the host summary view, add new items that displays the temperature information in Celsius for CPU, NVMe drives, HDDs/SSDs and fan speeds (actual view depend on the available sensor readings). The view layout is also adjusted to no longer match the column number settings and always expands to the full width of the browser window. It is also possible to collapse the panel vertically. +3. Modify the `pvemanagerlib.js` file to expand the space in the host summary view, add new items that displays the temperature information in Celsius for CPU, NVMe drives, HDDs/SSDs and fan speeds (the actual item list depends on the available sensor readings). The view layout is also adjusted to no longer match the column number settings and always expands to the full width of the browser window. It is also possible to collapse the panel vertically. The script provides two options: `install` and `uninstall`. The `install` option installs the modification, while the `uninstall` option removes it by copying the backup files to their original location. The script also restarts the `pveproxy` service to apply the changes. From 2a7e2deb16cf1ce48c0f1f033fd9539d8c0ed8d1 Mon Sep 17 00:00:00 2001 From: rmm Date: Sat, 11 May 2024 13:08:45 +0200 Subject: [PATCH 2/2] Sanitize "sensors -j" JSON output, add support for multiple CPUs --- pve-mod-gui-sensors.sh | 131 ++++++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 60 deletions(-) diff --git a/pve-mod-gui-sensors.sh b/pve-mod-gui-sensors.sh index 03e2271..4c72fc2 100644 --- a/pve-mod-gui-sensors.sh +++ b/pve-mod-gui-sensors.sh @@ -85,6 +85,54 @@ function configure { err "Sensor output error.\n\nCommand output:\n${sensorsOutput}\n\nExiting...\n" fi + # Check if CPU is part of known list for autoconfiguration + msg "\nDetecting support for CPU temperature sensors..." + for item in "${KNOWN_CPU_SENSORS[@]}"; do + if (echo "$sensorsOutput" | grep -q "$item"); then + case "$item" in + "coretemp-"*) + CPU_ADDRESS_PREFIX=$item + CPU_ITEM_PREFIX="Core " + CPU_TEMP_CAPTION="Core" + break + ;; + "k10temp-"*) + CPU_ADDRESS_PREFIX=$item + CPU_ITEM_PREFIX="Tccd" + CPU_TEMP_CAPTION="Temp" + break + ;; + *) + continue + ;; + esac + fi + done + + if [ -n "$CPU_ADDRESS_PREFIX" ]; then + msg "Detected sensor:\n$(echo "$sensorsOutput" | grep -o "\"${CPU_ADDRESS_PREFIX}[^\"]*\"" | sed 's/"//g')" + fi + + # If cpu is not known, ask the user for input + if [ -z "$CPU_ADDRESS_PREFIX" ]; then + warn "Could not automatically detect the CPU temperature sensor. Please configure it manually." + # Ask user for CPU information + # Inform the user and prompt them to press any key to continue + read -rsp $'Sensor output will be presented. Press any key to continue...\n' -n1 key + + # Print the output to the user + msg "Sensor output:\n${sensorsOutput}" + + # Prompt the user for adapter name and item name + read -p "Enter the CPU sensor address prefix (e.g.: coretemp-isa- or k10temp-pci-): " CPU_ADDRESS_PREFIX + read -p "Enter the CPU sensor input prefix (e.g.: Core or Tc): " CPU_ITEM_PREFIX + read -p "Enter the CPU temperature caption (e.g.: Core or Temp): " CPU_TEMP_CAPTION + fi + + if [[ -z "$CPU_ADDRESS_PREFIX" || -z "$CPU_ITEM_PREFIX" ]]; then + warn "The CPU configuration is not complete. Temperatures will not be available." + fi + # Check if HDD/SSD data is installed msg "\nDetecting support for HDD/SDD temperature sensors..." if (lsmod | grep -wq "drivetemp"); then @@ -110,61 +158,13 @@ function configure { enableNvmeTemp=false fi - # Check if CPU is part of known list for autoconfiguration - msg "\nDetecting support for CPU temperature sensors..." - for item in "${KNOWN_CPU_SENSORS[@]}"; do - if (echo "$sensorsOutput" | grep -q "$item"); then - case "$item" in - "coretemp-"*) - CPU_ADDRESS="$(echo "$sensorsOutput" | grep "$item" | sed 's/"//g;s/:{//;s/^\s*//')" - CPU_ITEM_PREFIX="Core " - CPU_TEMP_CAPTION="Core" - break - ;; - "k10temp-"*) - CPU_ADDRESS="$(echo "$sensorsOutput" | grep "$item" | sed 's/"//g;s/:{//;s/^\s*//')" - CPU_ITEM_PREFIX="Tccd" - CPU_TEMP_CAPTION="Temp" - break - ;; - *) - continue - ;; - esac - fi - done - - if [ -n "$CPU_ADDRESS" ]; then - msg "Detected sensor:\n$CPU_ADDRESS" - fi - - # If cpu is not known, ask the user for input - if [ -z "$CPU_ADDRESS" ]; then - warn "Could not automatically detect the CPU temperature sensor. Please configure it manually." - # Ask user for CPU information - # Inform the user and prompt them to press any key to continue - read -rsp $'Sensor output will be presented. Press any key to continue...\n' -n1 key - - # Print the output to the user - msg "Sensor output:\n${sensorsOutput}" - - # Prompt the user for adapter name and item name - read -p "Enter the CPU sensor address (e.g.: coretemp-isa-0000 or k10temp-pci-00c3): " CPU_ADDRESS - read -p "Enter the CPU sensor input prefix (e.g.: Core or Tc): " CPU_ITEM_PREFIX - read -p "Enter the CPU temperature caption (e.g.: Core or Temp): " CPU_TEMP_CAPTION - fi - - if [[ -z "$CPU_ADDRESS" || -z "$CPU_ITEM_PREFIX" ]]; then - warn "The CPU configuration is not complete. Temperatures will not be available." - fi - # Look for fan speeds - msg "\nDetecting support for fan speeds..." + msg "\nDetecting support for fan speed readings..." if (echo "$sensorsOutput" | grep -q "fan[0-9]*_input"); then - msg "Fan speeds detected:\n$(echo "$sensorsOutput" | grep -o 'fan[0-9]*_input[^"]*')" + msg "Detected fan speed sensors:\n$(echo "$sensorsOutput" | grep -o 'fan[0-9]*_input[^"]*')" enableFanSpeed=true else - warn "No fan speeds found." + warn "No fan speed sensors found." enableFanSpeed=false fi @@ -189,7 +189,7 @@ function install_mod { cp "$nodespm" "$BACKUP_DIR/Nodes.pm.$timestamp" msg "Backup of \"$nodespm\" saved to \"$BACKUP_DIR/Nodes.pm.$timestamp\"." - sed -i '/my $dinfo = df('\''\/'\'', 1);/i\'$'\t''$res->{sensorsOutput} = `sensors -j`;\n' "$nodespm" + sed -i '/my $dinfo = df('\''\/'\'', 1);/i\'$'\t''$res->{sensorsOutput} = `sensors -j`;\n\t# sanitize JSON output\n\t$res->{sensorsOutput} =~ s/ERROR:.+\\s(\\w+):\\s(.+)/\\"$1\\": 0.000,/g;\n\t$res->{sensorsOutput} =~ s/ERROR:.+\\s(\\w+)!/\\"$1\\": 0.000,/g;\n\t$res->{sensorsOutput} =~ s/,(.*[.\\n]*.+})/$1/g;\n' "$nodespm" msg "Sensors' output added to \"$nodespm\"." else warn "Sensors' output already integrated in in \"$nodespm\"." @@ -225,17 +225,20 @@ function install_mod { textField: 'sensorsOutput',\n\ renderer: function(value){\n\ // sensors configuration\n\ - const cpuAddress = \"$CPU_ADDRESS\";\n\ + const addressPrefix = \"$CPU_ADDRESS_PREFIX\";\n\ const cpuItemPrefix = \"$CPU_ITEM_PREFIX\";\n\ const cpuTempCaption = \"$CPU_TEMP_CAPTION\";\n\ // display configuration\n\ const itemsPerRow = $CPU_ITEMS_PER_ROW;\n\ // ---\n\ const objValue = JSON.parse(value);\n\ - if (objValue.hasOwnProperty(cpuAddress)) {\n\ - const items = objValue[cpuAddress];\n\ + const cpuKeys = Object.keys(objValue).filter(item => String(item).startsWith(addressPrefix)).sort();\n\ + const cpuCount = cpuKeys.length;\n\ + let temps = [];\n\ + cpuKeys.forEach((cpuKey, cpuIndex) => {\n\ + let cpuTemps = [];\n\ + const items = objValue[cpuKey];\n\ const itemKeys = Object.keys(items).filter(item => { return String(item).startsWith(cpuItemPrefix); });\n\ - let temps = [];\n\ itemKeys.forEach((coreKey) => {\n\ try {\n\ let tempVal = NaN, tempMax = NaN, tempCrit = NaN;\n\ @@ -264,14 +267,22 @@ function install_mod { } else {\n\ tempStr = \`\${cpuTempCaption}: \${tempVal}°C\`;\n\ }\n\ - temps.push(tempStr);\n\ + cpuTemps.push(tempStr);\n\ }\n\ - } catch (e) { /*_*/\n\ + } catch (e) { /*_*/ }\n\ + });\n\ + if(cpuTemps.length > 0) {\n\ + temps.push(cpuTemps);\n\ }\n\ });\n\ - const result = temps.map((strTemp, index, arr) => { return strTemp + (index + 1 < arr.length ? (itemsPerRow > 0 && (index + 1) % itemsPerRow === 0 ? '
' : ' | ') : ''); });\n\ - return '
' + (result.length > 0 ? result.join('') : 'N/A') + '
';\n\ + let result = '';\n\ + temps.forEach((cpuTemps, cpuIndex) => {\n\ + const strCoreTemps = cpuTemps.map((strTemp, index, arr) => { return strTemp + (index + 1 < arr.length ? (itemsPerRow > 0 && (index + 1) % itemsPerRow === 0 ? '
' : ' | ') : ''); })\n\ + if(strCoreTemps.length > 0) {\n\ + result += (cpuCount > 1 ? \`CPU \${cpuIndex+1}: \` : '') + strCoreTemps.join('') + (cpuIndex < cpuCount ? '
' : '');\n\ }\n\ + });\n\ + return '
' + (result.length > 0 ? result : 'N/A') + '
';\n\ }\n\ }, }" "$pvemanagerlibjs"