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.