From 3cb1ac83b939b5dd469795b3c2172718fbc5c581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=BE=E3=81=A3=E3=81=99=E3=82=8B?= <158264076+MusclePr@users.noreply.github.com> Date: Sun, 16 Feb 2025 00:17:41 +0900 Subject: [PATCH] [pve-mod-gui-sensors.sh] support for mixed core cluster (#81) * * Fixed to render correctly even if INTEL and AMD core nodes are mixed in the cluster. * Fixed the behavior of forcing configuration before being told "Mod is already installed". * Add motherboard information as an option in System Information settings. * Update to a simple CPU configuration. * Configure CPU temperature display settings independent of current sensor state. * Fixed a bug where AMD chiplet temperature was not displayed. * Add note about AMD only supports average * Update readme --------- Co-authored-by: Meliox --- pve-mod-gui-sensors.sh | 177 +++++++++++++++++++---------------------- readme.md | 2 +- 2 files changed, 82 insertions(+), 97 deletions(-) diff --git a/pve-mod-gui-sensors.sh b/pve-mod-gui-sensors.sh index 8529f57..8eb5b17 100644 --- a/pve-mod-gui-sensors.sh +++ b/pve-mod-gui-sensors.sh @@ -112,82 +112,28 @@ 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 - CPU_ADDRESS_PREFIX=$item - fi + # Prompt user for which temperature to use + while true; do + local choiceTempDisplayType=$(ask "Do you wish to display temperatures for all cores [C] or just an average temperature per CPU [a] (note: AMD only supports average)? (C/a)") + case "$choiceTempDisplayType" in + # Set temperature search criteria + [cC] | "") + CPU_TEMP_TARGET="Core" + info "Temperatures will be displayed for all cores." + ;; + [aA]) + CPU_TEMP_TARGET="Package" + info "An average temperature will be displayed per CPU." + ;; + *) + # If the user enters an invalid input, print an warning message and retry ask. + warn "Invalid input." + continue + ;; + esac + break done - if [ -n "$CPU_ADDRESS_PREFIX" ]; then - msg "Detected sensors:\n$(echo "$sensorsOutput" | grep -o "\"${CPU_ADDRESS_PREFIX}[^\"]*\"" | sed 's/"//g')" - - # Populate search criterias for known CPUs - if (echo "$sensorsOutput" | grep -q "coretemp-"); then - # Intel CPU - # Prompt user for which temperature to use - local choiceTempDisplayType=$(ask "Do you wish to display temperatures for all cores [C] or just an average temperature per CPU [a]? (C/a)") - case "$choiceTempDisplayType" in - # Set temperature search criteria - [cC] | "") - if (echo "$sensorsOutput" | grep -A 10 "coretemp-" | grep -q "Core "); then - CPU_ITEM_PREFIX="Core " - CPU_TEMP_CAPTION="Core" - info "Temperatures will be displayed for all cores." - fi - ;; - [aA]) - if (echo "$sensorsOutput" | grep -A 10 "coretemp-" | grep -q "Package id "); then - CPU_ITEM_PREFIX="Package id" - CPU_TEMP_CAPTION="Package" - info "An average temperature will be displayed per CPU." - fi - ;; - *) - # If the user enters an invalid input, print an error message and exit the script with a non-zero status code - err "Invalid input. Exiting..." - ;; - esac - elif (echo "$sensorsOutput" | grep -q "k10temp-"); then - # AMD CPU - # Find and set temperature search criteria - if (echo "$sensorsOutput" | grep -A 10 "$item" | grep -q "Tctl" && echo "$sensorsOutput" | grep -A 10 "$item" | grep -q "Tccd"); then - CPU_ADDRESS_PREFIX=$item - CPU_ITEM_PREFIX="Tccd" - CPU_TEMP_CAPTION="Temp" - elif (echo "$sensorsOutput" | grep -A 10 "$item" | grep -q -e "\"Tctl\""); then - CPU_ADDRESS_PREFIX=$item - CPU_ITEM_PREFIX="Tctl" - CPU_TEMP_CAPTION="Temp" - elif (echo "$sensorsOutput" | grep -A 10 "$item" | grep -q "\"temp1\""); then - CPU_ADDRESS_PREFIX=$item - CPU_ITEM_PREFIX="temp" - CPU_TEMP_CAPTION="Temp" - fi - fi - else - # If cpu is not known, ask the user for input - 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." - else - SENSORS_DETECTED=true - fi - # Look for ram temps msg "\nDetecting support for RAM temperature sensors..." if (echo "$sensorsOutput" | grep -q '"SODIMM":'); then @@ -271,12 +217,25 @@ function configure { esac fi - local choiceEnableSystemInfo=$(ask "Do you wish to enable system information? (Y/n)") + # DMI Type: + # 1 ... System Information + # 2 ... Base Board Information (for self-made PC) + for i in 1 2; do + echo "type ${i})" + dmidecode -t ${i} | awk -F': ' '/Manufacturer|Product Name|Serial Number/ {print $1": "$2}' + done + local choiceEnableSystemInfo=$(ask "Do you wish to enable system information? (1/2/n)") case "$choiceEnableSystemInfo" in - [yY] | "") + [1] | "") ENABLE_SYSTEM_INFO=true + SYSTEM_INFO_TYPE=1 info "System information will be displayed..." ;; + [2]) + ENABLE_SYSTEM_INFO=true + SYSTEM_INFO_TYPE=2 + info "Motherboard information will be displayed..." + ;; [nN]) ENABLE_SYSTEM_INFO=false info "System information will NOT be displayed..." @@ -291,6 +250,11 @@ function configure { # Function to install the modification function install_mod { + if [[ -n $(cat $NODES_PM_FILE | grep -e "$res->{sensorsOutput}") ]] && [[ -n $(cat $NODES_PM_FILE | grep -e "$res->{systemInfo}") ]]; then + err "Mod is already installed. Uninstall existing before installing." + exit + fi + msg "\nPreparing mod installation..." # Provide sensor configuration @@ -302,18 +266,13 @@ function install_mod { local timestamp=$(date '+%Y-%m-%d_%H-%M-%S') # Perform backup - if [[ -z $(cat $NODES_PM_FILE | grep -e "$res->{sensorsOutput}") ]] || [[ -z $(cat $NODES_PM_FILE | grep -e "$res->{systemInfo}") ]]; then - # Create backup of original file - cp "$NODES_PM_FILE" "$BACKUP_DIR/Nodes.pm.$timestamp" - msg "Backup of \"$NODES_PM_FILE\" saved to \"$BACKUP_DIR/Nodes.pm.$timestamp\"." + # Create backup of original file + cp "$NODES_PM_FILE" "$BACKUP_DIR/Nodes.pm.$timestamp" + msg "Backup of \"$NODES_PM_FILE\" saved to \"$BACKUP_DIR/Nodes.pm.$timestamp\"." - # Create backup of original file - cp "$PVE_MANAGER_LIB_JS_FILE" "$BACKUP_DIR/pvemanagerlib.js.$timestamp" - msg "Backup of \"$PVE_MANAGER_LIB_JS_FILE\" saved to \"$BACKUP_DIR/pvemanagerlib.js.$timestamp\"." - else - err "Mod is already installed. Uninstall existing before installing." - exit - fi + # Create backup of original file + cp "$PVE_MANAGER_LIB_JS_FILE" "$BACKUP_DIR/pvemanagerlib.js.$timestamp" + msg "Backup of \"$PVE_MANAGER_LIB_JS_FILE\" saved to \"$BACKUP_DIR/pvemanagerlib.js.$timestamp\"." if [ $SENSORS_DETECTED = true ]; then local sensorsCmd @@ -329,7 +288,7 @@ function install_mod { fi if [ $ENABLE_SYSTEM_INFO = true ]; then - local systemInfoCmd=$(dmidecode -t 1 | awk -F': ' '/Manufacturer|Product Name|Serial Number/ {print $1": "$2}' | awk '{$1=$1};1' | sed 's/$/ |/' | paste -sd " " - | sed 's/ |$//') + local systemInfoCmd=$(dmidecode -t ${SYSTEM_INFO_TYPE} | awk -F': ' '/Manufacturer|Product Name|Serial Number/ {print $1": "$2}' | awk '{$1=$1};1' | sed 's/$/ |/' | paste -sd " " - | sed 's/ |$//') sed -i "/my \$dinfo = df('\/', 1);/i\\\t\$res->{systemInfo} = \"$(echo "$systemInfoCmd")\";\n" "$NODES_PM_FILE" msg "System information output added to \"$NODES_PM_FILE\"." fi @@ -470,9 +429,6 @@ Ext.define('PVE.mod.TempHelper', {\n\ textField: 'sensorsOutput',\n\ renderer: function(value){\n\ // sensors configuration\n\ - const addressPrefix = \"$CPU_ADDRESS_PREFIX\";\n\ - const cpuItemPrefix = \"$CPU_ITEM_PREFIX\";\n\ - const cpuTempCaption = \"$CPU_TEMP_CAPTION\";\n\ const cpuTempHelper = Ext.create('PVE.mod.TempHelper', $tempHelperCtorParams);\n\ // display configuration\n\ const itemsPerRow = $CPU_ITEMS_PER_ROW;\n\ @@ -483,7 +439,36 @@ Ext.define('PVE.mod.TempHelper', {\n\ } catch(e) {\n\ objValue = {};\n\ }\n\ - const cpuKeys = Object.keys(objValue).filter(item => String(item).startsWith(addressPrefix)).sort();\n\ + const cpuKeysI = Object.keys(objValue).filter(item => String(item).startsWith('coretemp-isa-')).sort();\n\ + const cpuKeysA = Object.keys(objValue).filter(item => String(item).startsWith('k10temp-pci-')).sort();\n\ + const bINTEL = cpuKeysI.length > 0 ? true : false;\n\ + const INTELPackagePrefix = '$CPU_TEMP_TARGET' == 'Core' ? 'Core ' : 'Package id';\n\ + const INTELPackageCaption = '$CPU_TEMP_TARGET' == 'Core' ? 'Core' : 'Package';\n\ + let AMDPackagePrefix = 'Tccd';\n\ + let AMDPackageCaption = 'Chiplet';\n\ + if (cpuKeysA.length > 0) {\n\ + let bTccd = false;\n\ + let bTctl = false;\n\ + cpuKeysA.forEach((cpuKey, cpuIndex) => {\n\ + let items = objValue[cpuKey];\n\ + if (Object.keys(items).findIndex(item => { return String(item).startsWith('Tccd'); })) bTccd = true;\n\ + if (Object.keys(items).findIndex(item => { return String(item).startsWith('Tctl'); })) bTctl = true;\n\ + });\n\ + if (bTccd && bTctl && '$CPU_TEMP_TARGET' == 'Core') {\n\ + AMDPackagePrefix = 'Tccd';\n\ + AMDPackageCaption = 'Chiplet';\n\ + } else if (bTctl) {\n\ + AMDPackagePrefix = 'Tctl';\n\ + AMDPackageCaption = 'Temp';\n\ + } else {\n\ + AMDPackagePrefix = 'temp';\n\ + AMDPackageCaption = 'Temp';\n\ + }\n\ + }\n\ + const cpuKeys = bINTEL ? cpuKeysI : cpuKeysA;\n\ + const cpuItemPrefix = bINTEL ? INTELPackagePrefix : AMDPackagePrefix;\n\ + const cpuTempCaption = bINTEL ? INTELPackageCaption : AMDPackageCaption;\n\ + const formatTemp = bINTEL ? '0' : '0.0';\n\ const cpuCount = cpuKeys.length;\n\ let temps = [];\n\ cpuKeys.forEach((cpuKey, cpuIndex) => {\n\ @@ -514,9 +499,9 @@ Ext.define('PVE.mod.TempHelper', {\n\ let tempIndex = coreKey.match(/\\\S+\\\s*(\\\d+)/);\n\ if (tempIndex !== null && tempIndex.length > 1) {\n\ tempIndex = tempIndex[1];\n\ - tempStr = \`\${cpuTempCaption} \${tempIndex}: \${Ext.util.Format.number(tempVal, '0.#')}\${cpuTempHelper.getUnit()}\`;\n\ + tempStr = \`\${cpuTempCaption} \${tempIndex}: \${Ext.util.Format.number(tempVal, formatTemp)}\${cpuTempHelper.getUnit()}\`;\n\ } else {\n\ - tempStr = \`\${cpuTempCaption}: \${Ext.util.Format.number(tempVal, '0.#')}\${cpuTempHelper.getUnit()}\`;\n\ + tempStr = \`\${cpuTempCaption}: \${Ext.util.Format.number(tempVal, formatTemp)}\${cpuTempHelper.getUnit()}\`;\n\ }\n\ cpuTemps.push(tempStr);\n\ }\n\ @@ -592,7 +577,7 @@ Ext.define('PVE.mod.TempHelper', {\n\ if (!isNaN(tempCrit) && tempVal >= tempCrit) {\n\ tempStyle = 'color: red; font-weight: bold;';\n\ }\n\ - const tempStr = \`Drive \${index + 1}: \${Ext.util.Format.number(tempVal, '0.#')}\${tempHelper.getUnit()}\`;\n\ + const tempStr = \`Drive \${index + 1}: \${Ext.util.Format.number(tempVal, '0.0')}\${tempHelper.getUnit()}\`;\n\ temps.push(tempStr);\n\ }\n\ } catch(e) { /*_*/ }\n\ @@ -655,7 +640,7 @@ Ext.define('PVE.mod.TempHelper', {\n\ if (!isNaN(tempCrit) && tempVal >= tempCrit) {\n\ tempStyle = 'color: red; font-weight: bold;';\n\ }\n\ - const tempStr = \`Drive \${index + 1}: \${Ext.util.Format.number(tempVal, '0.#')}\${tempHelper.getUnit()}\`;\n\ + const tempStr = \`Drive \${index + 1}: \${Ext.util.Format.number(tempVal, '0.0')}\${tempHelper.getUnit()}\`;\n\ temps.push(tempStr);\n\ }\n\ } catch(e) { /*_*/ }\n\ diff --git a/readme.md b/readme.md index 6763a66..cc1b5df 100644 --- a/readme.md +++ b/readme.md @@ -7,7 +7,7 @@ If you find this helpful, a small donation is appreciated, [![Donate](https://ww (Tested compatibility: 7.x - 8.3.2) ![Promxox temp mod](https://github.com/Meliox/PVE-mods/blob/main/pve-mod-sensors.png?raw=true) -This bash script installs a modification to the Proxmox Virtual Environment (PVE) web user interface (UI) to display sensor readings in a flexible and readable manner. Supported are CPU, NVMe/HDD/SSD temperatures (Celsius/Fahrenheit), fan speeds and ram temperatures. +This bash script installs a modification to the Proxmox Virtual Environment (PVE) web user interface (UI) to display sensor readings in a flexible and readable manner. Supported are CPU, NVMe/HDD/SSD temperatures (Celsius/Fahrenheit), fan speeds, ram temperatures, mixed CPU's core nodes setups, motherboard information or system information. The modification includes three main steps: