NOTE

Gemini 3 Pro 真的好用啊。

Code

#!/bin/bash
 
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
 
echo -e "${CYAN}=========================================================${NC}"
echo -e "${CYAN}       Proxmox VE Memory Allocation & Headroom check     ${NC}"
echo -e "${CYAN}=========================================================${NC}"
 
# 1. 获取主机物理内存信息 (单位 MB)
HOST_TOTAL_MB=$(free -m | awk '/^Mem:/{print $2}')
HOST_USED_MB=$(free -m | awk '/^Mem:/{print $3}')
 
# 2. 获取 ZFS ARC 信息 (如果是 ZFS)
ARC_SIZE_MB=0
if [ -f /proc/spl/kstat/zfs/arcstats ]; then
    ARC_BYTES=$(awk '/^size/ {print $3}' /proc/spl/kstat/zfs/arcstats)
    ARC_SIZE_MB=$((ARC_BYTES / 1024 / 1024))
fi
 
# 3. 初始化计数器
TOTAL_ALLOC_RUNNING=0
TOTAL_ALLOC_ALL=0
COUNT_RUNNING=0
COUNT_STOPPED=0
 
echo -e "\n${YELLOW}[Details by Instance]${NC}"
printf "%-6s %-6s %-20s %-10s %-15s\n" "ID" "Type" "Name" "Status" "MaxRAM(MB)"
echo "-------------------------------------------------------------"
 
# 4. 遍历 LXC 容器
for id in $(pct list | awk 'NR>1 {print $1}'); do
    STATUS=$(pct list | awk -v id="$id" '$1 == id {print $2}')
    # 获取配置的内存 (MB)
    MEM=$(pct config $id | grep -w "memory:" | awk '{print $2}')
    # 如果没有设置,默认为 512 (LXC默认值,虽少见但为了稳妥)
    [ -z "$MEM" ] && MEM=512
    
    NAME=$(pct config $id | grep -w "hostname:" | awk '{print $2}')
    
    TOTAL_ALLOC_ALL=$((TOTAL_ALLOC_ALL + MEM))
    
    if [ "$STATUS" == "running" ]; then
        TOTAL_ALLOC_RUNNING=$((TOTAL_ALLOC_RUNNING + MEM))
        COUNT_RUNNING=$((COUNT_RUNNING + 1))
        printf "%-6s %-6s %-20s ${GREEN}%-10s${NC} %-15s\n" "$id" "LXC" "${NAME:0:19}" "$STATUS" "$MEM"
    else
        COUNT_STOPPED=$((COUNT_STOPPED + 1))
        printf "%-6s %-6s %-20s ${RED}%-10s${NC} %-15s\n" "$id" "LXC" "${NAME:0:19}" "$STATUS" "$MEM"
    fi
done
 
# 5. 遍历 QEMU/KVM 虚拟机
for id in $(qm list | awk 'NR>1 {print $1}'); do
    STATUS=$(qm list | awk -v id="$id" '$1 == id {print $3}')
    # 获取配置的内存 (MB)
    MEM=$(qm config $id | grep -w "memory:" | awk '{print $2}')
    [ -z "$MEM" ] && MEM=0 # 异常保护
    
    NAME=$(qm config $id | grep -w "name:" | awk '{print $2}')
    
    TOTAL_ALLOC_ALL=$((TOTAL_ALLOC_ALL + MEM))
    
    if [ "$STATUS" == "running" ]; then
        TOTAL_ALLOC_RUNNING=$((TOTAL_ALLOC_RUNNING + MEM))
        COUNT_RUNNING=$((COUNT_RUNNING + 1))
        printf "%-6s %-6s %-20s ${GREEN}%-10s${NC} %-15s\n" "$id" "VM" "${NAME:0:19}" "$STATUS" "$MEM"
    else
        COUNT_STOPPED=$((COUNT_STOPPED + 1))
        printf "%-6s %-6s %-20s ${RED}%-10s${NC} %-15s\n" "$id" "VM" "${NAME:0:19}" "$STATUS" "$MEM"
    fi
done
 
echo "-------------------------------------------------------------"
 
# 6. 计算 Headroom 和 Overcommit
# 真正可用的内存 = 物理空闲 + ZFS ARC (因为ARC在内存紧张时会自动释放)
REAL_FREE_MB=$((HOST_TOTAL_MB - HOST_USED_MB + ARC_SIZE_MB))
 
# 格式化输出
echo -e "\n${YELLOW}[Summary Analysis]${NC}"
echo "------------------------------------------"
printf "Host Physical RAM:        %8d MB\n" "$HOST_TOTAL_MB"
if [ "$ARC_SIZE_MB" -gt 0 ]; then
    printf "ZFS ARC (Reclaimable):    %8d MB (Included in 'Used' by Linux usually)\n" "$ARC_SIZE_MB"
fi
echo "------------------------------------------"
printf "Allocated to RUNNING VMs: %8d MB\n" "$TOTAL_ALLOC_RUNNING"
printf "Allocated to ALL VMs:     %8d MB\n" "$TOTAL_ALLOC_ALL"
echo "------------------------------------------"
 
# 7. 结论分析
echo -e "\n${YELLOW}[Overcommitment Status]${NC}"
 
# 场景 1: 针对当前运行的机器
RUNNING_PCT=$(awk "BEGIN {printf \"%.2f\", ${TOTAL_ALLOC_RUNNING}/${HOST_TOTAL_MB}*100}")
if [ "$TOTAL_ALLOC_RUNNING" -gt "$HOST_TOTAL_MB" ]; then
    echo -e "Current Status: ${RED}OVERCOMMITTED${NC} (Assigned: ${RUNNING_PCT}%)"
    echo -e "Warning: You have assigned more RAM to running VMs than physical RAM available."
    echo -e "Reliability depends on KSM (Deduplication) and Ballooning."
else
    echo -e "Current Status: ${GREEN}SAFE${NC} (Assigned: ${RUNNING_PCT}%)"
    HEADROOM=$((HOST_TOTAL_MB - TOTAL_ALLOC_RUNNING))
    echo -e "Headroom (RAM not yet promised to running VMs): ${GREEN}${HEADROOM} MB${NC}"
fi
 
# 场景 2: 针对所有机器(包括关机的)
ALL_PCT=$(awk "BEGIN {printf \"%.2f\", ${TOTAL_ALLOC_ALL}/${HOST_TOTAL_MB}*100}")
if [ "$TOTAL_ALLOC_ALL" -gt "$HOST_TOTAL_MB" ]; then
     echo -e "Worst Case Scenario: ${YELLOW}POTENTIALLY OVERCOMMITTED${NC} (Total Configured: ${ALL_PCT}%)"
     echo "Note: If you turn on ALL VMs, you will exceed physical RAM."
else
     echo -e "Worst Case Scenario: ${GREEN}SAFE${NC} (Total Configured: ${ALL_PCT}%)"
     echo "You can safely turn on all VMs without exhausting physical RAM."
fi
 
echo ""

Example output

=========================================================
       Proxmox VE Memory Allocation & Headroom check     
=========================================================
 
[Details by Instance]
ID     Type   Name                 Status     MaxRAM(MB)     
-------------------------------------------------------------
201    LXC    xxxxxxx              running    512            
202    LXC    xxxxxxx              running    512            
204    LXC    xxxxxxx xxx          running    2048           
205    LXC    xxxxxxxn             running    2048           
206    LXC    xxxxxxx              running    4096           
2000   LXC    ubuntu-lxc-igpu-tmp  stopped    2048           
100    VM     xxxxxxse             running    4096           
101    VM     xxxxxxs              running    65536          
102    VM     xxxxxx               running    2048           
103    VM     xxxxxx               running    4096           
104    VM     xxxxxxbox            running    8192           
105    VM     xxxxxxxxxbox         running    4096           
106    VM     xxxxxxxxxbox         running    4096           
107    VM     xxxxxx               running    8192           
108    VM     xxxxxx               running    4096           
109    VM     xxxxxxxxxxxbox       running    4096           
1000   VM     ubuntu-srv-tmpl      stopped    4096           
-------------------------------------------------------------
 
[Summary Analysis]
------------------------------------------
Host Physical RAM:          128663 MB
ZFS ARC (Reclaimable):       12866 MB (Included in 'Used' by Linux usually)
------------------------------------------
Allocated to RUNNING VMs:   117760 MB
Allocated to ALL VMs:       123904 MB
------------------------------------------
 
[Overcommitment Status]
Current Status: SAFE (Assigned: 91.53%)
Headroom (RAM not yet promised to running VMs): 10903 MB
Worst Case Scenario: SAFE (Total Configured: 96.30%)
You can safely turn on all VMs without exhausting physical RAM.