destroy_vm.sh Updated, Supports Multiple Hosts and --force option now

The updated script now accepts multiple VMIDs as command-line arguments, making it easier to remove several VMs at once. Additionally, a --force option has been added, so you no longer have to confirm deletion for each VM manually.

This update streamlines VM cleanup by automating the process, reducing confirmation prompts, and ensuring SSH key cleanup for smoother re-deployment.

What’s New in This Update?

  1. Supports Multiple VMIDs – Instead of running the script one VM at a time, you can now pass multiple VMIDs as arguments.
  2. New --force Option – If you are sure about deleting VMs, use --force to bypass manual confirmation.
  3. Displays VM Details Before Deletion – Helps verify the correct VM is being deleted.
  4. Cleans Up Old SSH Keys – Prevents SSH host verification issues after VM destruction.

Usage

Run the script with one or more VMIDs:

./vm_destroyer.sh 101 102 103

Or use --force to skip confirmations:

./vm_destroyer.sh --force 101 102 103

How It Works

The script loops through each provided VMID, retrieves VM details, and prompts for confirmation unless --force is specified. It then stops the VM, waits for it to shut down, and deletes it. Finally, if the VM had a Cloud-Init assigned IP, the script removes the old SSH key entry to prevent connection issues in future deployments.

This update makes Proxmox VM lifecycle management faster and more efficient, particularly when dealing with batch deletions.

Eventually this will be programmed in Go as part of CodexMCP, but at this stage this was the fastest option.

destroy_vm.sh

  #!/bin/bash

# Set Proxmox API Details
PROXMOX_HOST="your-proxmox-host"
NODE="mcp"
API_TOKEN="your-proxmox-api-token"

# Check if --force option is provided
FORCE_MODE=false
if [[ "$1" == "--force" ]]; then
    FORCE_MODE=true
    shift # Remove --force from argument list
fi

# Ensure at least one VMID is provided
if [ "$#" -lt 1 ]; then
    echo "Usage: $0 [--force]  [VMID2] [VMID3] ..."
    exit 1
fi

# Loop through each VM ID provided as argument
for VMID in "$@"; do
    echo "Fetching information for VM ID: $VMID..."

    # Fetch VM Details
    VM_INFO=$(curl -s -k -H "Authorization: PVEAPIToken=$API_TOKEN" \
        "https://$PROXMOX_HOST:8006/api2/json/nodes/$NODE/qemu/$VMID/config")

    # Extract Name and Display Info
    VM_NAME=$(echo "$VM_INFO" | jq -r '.data.name')
    VM_DISK=$(echo "$VM_INFO" | jq -r '.data.scsi0')
    VM_MEMORY=$(echo "$VM_INFO" | jq -r '.data.memory')
    VM_IP=$(echo "$VM_INFO" | jq -r '.data.ipconfig0' | sed -n 's/ip=\(.*\)\/.*/\1/p')

    if [ "$VM_NAME" == "null" ]; then
        echo "VM with ID $VMID not found on node $NODE."
        continue
    fi

    echo "VM Found: $VM_NAME ($VMID)"
    echo "   - Disk: $VM_DISK"
    echo "   - Memory: ${VM_MEMORY}MB"
    if [ -n "$VM_IP" ]; then
        echo "   - Cloud-Init Assigned IP: $VM_IP"
    else
        echo "   - No IP Found (Check Cloud-Init Configuration)"
    fi
    echo ""

    # Confirm deletion unless --force is used
    if [ "$FORCE_MODE" = false ]; then
        read -p "Are you sure you want to STOP and DESTROY this VM? (yes/no): " CONFIRM
        if [[ "$CONFIRM" != "yes" ]]; then
            echo "Skipping VM $VMID."
            continue
        fi
    fi

    # Stop the VM
    echo "Stopping VM $VMID..."
    curl -s -k -X POST -H "Authorization: PVEAPIToken=$API_TOKEN" \
        "https://$PROXMOX_HOST:8006/api2/json/nodes/$NODE/qemu/$VMID/status/stop"

    # Wait for the VM to shut down
    echo "Waiting for VM to fully stop..."
    sleep 10

    # Destroy the VM
    echo "Destroying VM $VMID..."
    curl -s -k -X DELETE -H "Authorization: PVEAPIToken=$API_TOKEN" \
        "https://$PROXMOX_HOST:8006/api2/json/nodes/$NODE/qemu/$VMID"

    echo "VM $VMID ($VM_NAME) has been destroyed."

    # Remove the old SSH key to prevent host key verification errors
    if [ -n "$VM_IP" ]; then
        echo "Cleaning up old SSH key for $VM_IP..."
        ssh-keygen -f "$HOME/.ssh/known_hosts" -R "$VM_IP" >/dev/null 2>&1
    fi

    echo "Old SSH key removed. You can now reconnect without errors."
    echo "------------------------------------------------------------"
done