#!/bin/bash

# 先完成 sudo 认证
echo "请输入密码以开始监控..."
if ! sudo -v; then
    echo "认证失败,退出监控程序"
    exit 1
fi

# concise = 简洁
# aesthetic = 美观
# 显示类型
showType="aesthetic"
# 刷新频率(毫秒)
refreshRate=1000
# mW(毫瓦) 或 W(瓦)
powerUnit="W"
# 是否显示每小时耗电量:true 或 false
powerConsumptionPerHour=true

echo "开始监控 Combined Power 和 Thermal Pressure..."
echo "按 Ctrl+C 停止监控"
echo "----------------------------------------"

if [[ "$showType" == "concise" ]]; then
    # 监控循环
    sudo powermetrics --samplers cpu_power,thermal -i $refreshRate | grep --line-buffered -E "Combined Power|Current pressure level" | while IFS= read -r line; do
        timestamp=$(date "+%H:%M:%S")
        # 单位转换
        if [[ "$powerUnit" == "W" ]] && [[ "$line" == *"mW"* ]]; then
            line=$(echo "$line" | perl -pe 's/(\d+) mW/sprintf("%.3f W", $1\/1000)/ge')
        fi
        echo "[$timestamp] $line"
        if [[ "$line" == *"Current pressure level"* ]]; then
            echo "---"
        fi
    done
elif [[ "$showType" == "aesthetic" ]]; then
    # 更加美观的方式
    if [[ "$powerUnit" == "mW" ]]; then
        echo "功耗监控 (单位: mW)"
        unit_suffix=" mW"
    else
        echo "功耗监控 (单位: W)"
        unit_suffix=" W"
    fi
    
    # 根据是否显示耗电量调整表头
    if [[ "$powerConsumptionPerHour" == "true" ]]; then
        echo "时间     | CPU      | GPU      | ANE      | Combined | Thermal  | powerConsumptionPerHour"
        echo "-----------------------------------------------------------------------------------------"
    else
        echo "时间     | CPU      | GPU      | ANE      | Combined | Thermal"
        echo "---------------------------------------------------------------"
    fi

    sudo powermetrics --samplers cpu_power,thermal -i $refreshRate | {
        # 初始化变量
        cpu=""
        gpu=""
        ane=""
        combined=""
        thermal=""
        power_consumption=""
        
        while IFS= read -r line; do
            # 提取各组件功耗数值
            if [[ "$line" == *"CPU Power"* ]] && [[ "$line" != *"Combined"* ]]; then
                cpu_value=$(echo "$line" | grep -oE '[0-9]+ mW' | head -1 | grep -oE '[0-9]+')
                if [[ -n "$cpu_value" ]]; then
                    if [[ "$powerUnit" == "W" ]]; then
                        cpu_value_w=$(echo "scale=3; $cpu_value / 1000" | bc 2>/dev/null | sed 's/^\./0./' || echo "?")
                        cpu="${cpu_value_w}${unit_suffix}"
                    else
                        cpu="${cpu_value}${unit_suffix}"
                    fi
                fi
            elif [[ "$line" == *"GPU Power"* ]]; then
                gpu_value=$(echo "$line" | grep -oE '[0-9]+ mW' | head -1 | grep -oE '[0-9]+')
                if [[ -n "$gpu_value" ]]; then
                    if [[ "$powerUnit" == "W" ]]; then
                        gpu_value_w=$(echo "scale=3; $gpu_value / 1000" | bc 2>/dev/null | sed 's/^\./0./' || echo "?")
                        gpu="${gpu_value_w}${unit_suffix}"
                    else
                        gpu="${gpu_value}${unit_suffix}"
                    fi
                fi
            elif [[ "$line" == *"ANE Power"* ]]; then
                ane_value=$(echo "$line" | grep -oE '[0-9]+ mW' | head -1 | grep -oE '[0-9]+')
                if [[ -n "$ane_value" ]]; then
                    if [[ "$powerUnit" == "W" ]]; then
                        ane_value_w=$(echo "scale=3; $ane_value / 1000" | bc 2>/dev/null | sed 's/^\./0./' || echo "?")
                        ane="${ane_value_w}${unit_suffix}"
                    else
                        ane="${ane_value}${unit_suffix}"
                    fi
                fi
            elif [[ "$line" == *"Combined Power"* ]]; then
                combined_value=$(echo "$line" | grep -oE '[0-9]+ mW' | head -1 | grep -oE '[0-9]+')
                if [[ -n "$combined_value" ]]; then
                    if [[ "$powerUnit" == "W" ]]; then
                        combined_value_w=$(echo "scale=3; $combined_value / 1000" | bc 2>/dev/null | sed 's/^\./0./' || echo "?")
                        combined="${combined_value_w}${unit_suffix}"
                    else
                        combined="${combined_value}${unit_suffix}"
                    fi
                    
                    # 计算每小时耗电量(始终使用 kWh)
                    if [[ "$powerConsumptionPerHour" == "true" ]]; then
                        # 直接计算 kWh:mW → W → kW → kWh/小时
                        power_consumption_kwh=$(echo "scale=6; $combined_value / 1000 / 1000" | bc 2>/dev/null)
                        if [[ -n "$power_consumption_kwh" ]]; then
                            # 统一使用 kWh 显示,但根据数值大小调整精度
                            if (( $(echo "$power_consumption_kwh < 0.0001" | bc -l 2>/dev/null) )); then
                                power_consumption="0.0000 kWh"
                            elif (( $(echo "$power_consumption_kwh < 0.001" | bc -l 2>/dev/null) )); then
                                power_consumption=$(echo "scale=5; $power_consumption_kwh" | bc | xargs printf "%.5f kWh\n")
                            elif (( $(echo "$power_consumption_kwh < 0.01" | bc -l 2>/dev/null) )); then
                                power_consumption=$(echo "scale=4; $power_consumption_kwh" | bc | xargs printf "%.4f kWh\n")
                            else
                                power_consumption=$(echo "scale=3; $power_consumption_kwh" | bc | xargs printf "%.3f kWh\n")
                            fi
                        else
                            power_consumption="N/A"
                        fi
                    fi
                fi
            elif [[ "$line" == *"Current pressure level"* ]]; then
                thermal=$(echo "$line" | awk -F': ' '{print $2}')
                
                # 输出一行数据
                if [[ -n "$cpu" || -n "$gpu" || -n "$ane" ]]; then
                    timestamp=$(date "+%H:%M:%S")
                    if [[ "$powerConsumptionPerHour" == "true" ]]; then
                        printf "%-8s | %-8s | %-8s | %-8s | %-8s | %-8s | %s\n" \
                            "$timestamp" "${cpu:-N/A}" "${gpu:-N/A}" "${ane:-N/A}" "${combined:-N/A}" "${thermal:-N/A}" "${power_consumption:-N/A}"
                    else
                        printf "%-8s | %-8s | %-8s | %-8s | %-8s | %s\n" \
                            "$timestamp" "${cpu:-N/A}" "${gpu:-N/A}" "${ane:-N/A}" "${combined:-N/A}" "${thermal:-N/A}"
                    fi
                fi
                
                # 重置变量
                cpu=""
                gpu=""
                ane=""
                combined=""
                thermal=""
                power_consumption=""
            fi
        done
    }
fi

可配置统计单位,刷新频率,是否统计千瓦时(度)

并且提供简洁与美观(更详细的)

统计千瓦时仅在美观显示下才有

以下是两种效果的展示

使用方法:

  1. 打开终端输入vim <文件名>

  2. 复制上述代码粘贴进去

  3. 按下esc后输入:wq保存并退出

之后直接双击这个文件就可以使用了,效果如下