Original .sh file

This commit is contained in:
phil committed 2026-10-29 21:54:43 +00:00
1 parent e9ee3ff3fe
commit 6f44deff64
1 file changed
+229
Executable
+229
View File
@@ -0,0 +1,229 @@
#!/usr/bin/env bash
set -uo pipefail
# Simple interactive toolkit for a Proxmox VE node.
# Run as root. Uses whiptail for the GUI and does not execute arbitrary input.
if [[ $EUID -ne 0 ]]; then
printf 'Run this script as root, for example: sudo bash %s\n' "$0" >&2
exit 1
fi
if ! command -v whiptail >/dev/null 2>&1; then
printf 'whiptail is required. Install it with: apt install whiptail\n' >&2
exit 1
fi
TMPDIR_TOOLKIT=$(mktemp -d)
trap 'rm -rf "$TMPDIR_TOOLKIT"' EXIT
require_command() {
if ! command -v "$1" >/dev/null 2>&1; then
whiptail --title "Command unavailable" \
--msgbox "The command '$1' is not installed or not available on this node." 8 70
return 1
fi
}
valid_id() {
[[ "$1" =~ ^[0-9]+$ ]]
}
ask_id() {
local prompt=$1
local value
value=$(whiptail --title "Enter ID" --inputbox "$prompt" 9 60 3>&1 1>&2 2>&3) || return 1
if ! valid_id "$value"; then
whiptail --title "Invalid ID" --msgbox "Enter a numeric VM or container ID." 8 55
return 1
fi
printf '%s' "$value"
}
show_output() {
local title=$1
shift
local output="$TMPDIR_TOOLKIT/output.txt"
local status=0
"$@" >"$output" 2>&1 || status=$?
if [[ ! -s "$output" ]]; then
printf 'Command completed with exit status %s; no output.\n' "$status" >"$output"
elif (( status != 0 )); then
printf '\nCommand exited with status %s.\n' "$status" >>"$output"
fi
whiptail --title "$title" --textbox "$output" 24 85
}
confirm_action() {
whiptail --title "Confirm" --yesno "$1" 10 70
}
vm_menu() {
local choice id
while true; do
choice=$(whiptail --title "Virtual Machines (QEMU)" --menu "Choose an action:" \
16 72 8 \
"list" "List VMs (qm list)" \
"config" "Show VM configuration" \
"memory" "Show VM memory setting" \
"unlock" "Unlock a VM" \
"back" "Back" 3>&1 1>&2 2>&3) || return
case "$choice" in
list)
require_command qm && show_output "VM list" qm list
;;
config|memory|unlock)
require_command qm || continue
id=$(ask_id "Enter the VMID:") || continue
case "$choice" in
config) show_output "VM $id configuration" qm config "$id" ;;
memory) show_output "VM $id memory" bash -c 'qm config "$1" | grep -E "^memory:" || true' _ "$id" ;;
unlock)
if confirm_action "Unlock VM $id?\n\nOnly do this if you have confirmed that no task is still running for this VM."; then
show_output "Unlock VM $id" qm unlock "$id"
fi
;;
esac
;;
back) return ;;
esac
done
}
container_menu() {
local choice id
while true; do
choice=$(whiptail --title "Containers (LXC)" --menu "Choose an action:" \
14 72 6 \
"list" "List containers (pct list)" \
"config" "Show container configuration" \
"unlock" "Unlock a container" \
"back" "Back" 3>&1 1>&2 2>&3) || return
case "$choice" in
list)
require_command pct && show_output "Container list" pct list
;;
config|unlock)
require_command pct || continue
id=$(ask_id "Enter the container ID:") || continue
if [[ "$choice" == "config" ]]; then
show_output "Container $id configuration" pct config "$id"
elif confirm_action "Unlock container $id?\n\nOnly do this if you have confirmed that no task is still running for this container."; then
show_output "Unlock container $id" pct unlock "$id"
fi
;;
back) return ;;
esac
done
}
backup_menu() {
local id
require_command vzdump || return
id=$(ask_id "Enter the VM or container ID to back up:") || return
if confirm_action "Start a backup for ID $id using vzdump defaults?\n\nReview your node's backup configuration and storage capacity first."; then
show_output "Backup ID $id" vzdump "$id"
fi
}
restore_menu() {
local choice id archive
choice=$(whiptail --title "Restore" --menu "Choose what to restore:" \
12 72 4 \
"vm" "Restore a QEMU VM (qmrestore)" \
"ct" "Restore a container (pct restore)" \
"back" "Back" 3>&1 1>&2 2>&3) || return
[[ "$choice" == "back" ]] && return
id=$(ask_id "Enter the new VMID or container ID:") || return
archive=$(whiptail --title "Backup archive" --inputbox \
"Enter the full path to the vzdump archive:" 9 72 3>&1 1>&2 2>&3) || return
if [[ -z "$archive" || ! -f "$archive" ]]; then
whiptail --title "Archive not found" --msgbox "That file does not exist or is not a regular file." 8 65
return
fi
if ! confirm_action "Restore '$archive' as ID $id?\n\nRestoring can create or overwrite resources. Confirm the target ID and archive carefully."; then
return
fi
if [[ "$choice" == "vm" ]]; then
require_command qmrestore && show_output "Restore VM $id" qmrestore "$archive" "$id"
else
require_command pct && show_output "Restore container $id" pct restore "$id" "$archive"
fi
}
storage_menu() {
local choice
while true; do
choice=$(whiptail --title "Storage / LVM" --menu "Choose a read-only report:" \
14 72 6 \
"pvs" "Physical volumes (pvs)" \
"vgs" "Volume groups (vgs)" \
"lvs" "Logical volumes (lvs)" \
"back" "Back" 3>&1 1>&2 2>&3) || return
case "$choice" in
pvs) require_command pvs && show_output "Physical volumes" pvs ;;
vgs) require_command vgs && show_output "Volume groups" vgs ;;
lvs) require_command lvs && show_output "Logical volumes" lvs ;;
back) return ;;
esac
done
}
while true; do
choice=$(whiptail --title "Proxmox VE Toolkit" --menu "Select a task:" \
21 76 13 \
"vms" "Virtual machines (QEMU)" \
"containers" "Containers (LXC)" \
"backup" "Back up a VM or container (vzdump)" \
"restore" "Restore a VM or container" \
"cluster" "Cluster status (pvecm status)" \
"version" "Proxmox version (pveversion -v)" \
"storage" "Storage / LVM reports" \
"perf" "Host performance test (pveperf)" \
"subscription" "Subscription status" \
"dab" "Debian Appliance Builder help" \
"quit" "Exit" 3>&1 1>&2 2>&3) || break
case "$choice" in
vms) vm_menu ;;
containers) container_menu ;;
backup) backup_menu ;;
restore) restore_menu ;;
cluster) require_command pvecm && show_output "Cluster status" pvecm status ;;
version) require_command pveversion && show_output "Proxmox VE version" pveversion -v ;;
storage) storage_menu ;;
perf)
if require_command pveperf && confirm_action "Run pveperf?\n\nThis can cause temporary disk activity."; then
show_output "Host performance" pveperf
fi
;;
subscription) require_command pvesubscription && show_output "Subscription status" pvesubscription get ;;
dab)
if require_command dab; then
show_output "Debian Appliance Builder help" dab help
fi
;;
quit) break ;;
esac
done