SHOW:
|
|
- or go back to the newest paste.
| 1 | #!/bin/bash | |
| 2 | ||
| 3 | # ############################################# | |
| 4 | # SmartOS Zombie Zone Cleanup Script | |
| 5 | # Usage: ./nuke_zone.sh <UUID> | |
| 6 | # 20200112 | |
| 7 | # Use as ./nuke_zone.sh ecc5d57a-3d90-44ca-a89b-8869a120487d | |
| 8 | # ############################################# | |
| 9 | ||
| 10 | UUID=$1 | |
| 11 | ||
| 12 | # 1. Validation | |
| 13 | if [[ -z "$UUID" ]]; then | |
| 14 | echo "Error: No UUID provided." | |
| 15 | echo "Usage: $0 <zone-uuid>" | |
| 16 | exit 1 | |
| 17 | fi | |
| 18 | ||
| 19 | if [[ "$UUID" == "global" ]]; then | |
| 20 | echo "Error: Cannot delete the global zone." | |
| 21 | exit 1 | |
| 22 | fi | |
| 23 | ||
| 24 | # Basic check to see if the UUID string format looks roughly correct (simple check) | |
| 25 | if [[ ! "$UUID" =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ ]]; then
| |
| 26 | echo "Warning: Format of '$UUID' does not look like a standard UUID." | |
| 27 | read -p "Are you sure you want to proceed? (y/n) " -n 1 -r | |
| 28 | echo | |
| 29 | if [[ ! $REPLY =~ ^[Yy]$ ]]; then | |
| 30 | exit 1 | |
| 31 | fi | |
| 32 | fi | |
| 33 | ||
| 34 | echo "--- Starting cleanup for Zone: $UUID ---" | |
| 35 | ||
| 36 | # 2. Check current status | |
| 37 | STATE=$(zoneadm -z "$UUID" list -p 2>/dev/null | cut -d: -f3) | |
| 38 | ||
| 39 | if [[ -z "$STATE" ]]; then | |
| 40 | echo "Zone currently not recognized by zoneadm. Checking ZFS leftovers..." | |
| 41 | else | |
| 42 | echo "Current Zone State: $STATE" | |
| 43 | fi | |
| 44 | ||
| 45 | # 3. Analyze and Kill Suspicious Processes | |
| 46 | echo "Checking for stuck processes..." | |
| 47 | # We look for zoneadmd specifically, as it is the controller. | |
| 48 | # We also look for qemu/bhyve instances associated with the UUID. | |
| 49 | PIDS=$(pgrep -f "$UUID") | |
| 50 | ||
| 51 | if [[ -n "$PIDS" ]]; then | |
| 52 | echo "Found the following processes associated with this UUID:" | |
| 53 | pgrep -lf "$UUID" | |
| 54 | ||
| 55 | echo "Attempting to kill these processes to release locks..." | |
| 56 | # We use kill -9 (SIGKILL) because if we are here, the process is likely unresponsive to SIGTERM. | |
| 57 | echo "$PIDS" | xargs kill -9 | |
| 58 | sleep 2 | |
| 59 | ||
| 60 | # Verify they are gone | |
| 61 | REMAINING=$(pgrep -f "$UUID") | |
| 62 | if [[ -n "$REMAINING" ]]; then | |
| 63 | echo "WARNING: Some processes refused to die: $REMAINING" | |
| 64 | echo "This may indicate a kernel-level hung task (zombie)." | |
| 65 | else | |
| 66 | echo "Processes cleared." | |
| 67 | fi | |
| 68 | else | |
| 69 | echo "No locking processes found." | |
| 70 | fi | |
| 71 | ||
| 72 | # 4. Force state to installed/halted if possible | |
| 73 | # If the zone is technically 'running' in the kernel, we must halt it before uninstalling. | |
| 74 | if [[ "$STATE" == "running" || "$STATE" == "shutting_down" ]]; then | |
| 75 | echo "Forcing zone halt..." | |
| 76 | zoneadm -z "$UUID" halt | |
| 77 | sleep 2 | |
| 78 | fi | |
| 79 | ||
| 80 | # 5. Force Uninstall | |
| 81 | echo "Attempting forced uninstall (zoneadm)..." | |
| 82 | zoneadm -z "$UUID" uninstall -F | |
| 83 | RET=$? | |
| 84 | ||
| 85 | if [[ $RET -eq 0 ]]; then | |
| 86 | echo "zoneadm uninstall reported success." | |
| 87 | else | |
| 88 | echo "zoneadm uninstall reported an error (exit code $RET)." | |
| 89 | echo "Proceeding to ZFS cleanup anyway." | |
| 90 | fi | |
| 91 | ||
| 92 | # 6. ZFS Dataset Cleanup | |
| 93 | # vmadm requires the dataset 'zones/<UUID>' to be gone to consider the VM deleted. | |
| 94 | DATASET="zones/$UUID" | |
| 95 | if zfs list "$DATASET" > /dev/null 2>&1; then | |
| 96 | echo "ZFS dataset $DATASET still exists. Destroying it..." | |
| 97 | ||
| 98 | # Check if there are dependent snapshots or clones (unlikely for a deletion, but possible) | |
| 99 | # -r recursively destroys children/snapshots | |
| 100 | zfs destroy -r "$DATASET" | |
| 101 | ||
| 102 | if [[ $? -eq 0 ]]; then | |
| 103 | echo "Dataset destroyed." | |
| 104 | else | |
| 105 | echo "Failed to destroy dataset. Check 'zfs list' manually." | |
| 106 | fi | |
| 107 | else | |
| 108 | echo "ZFS dataset $DATASET is already gone." | |
| 109 | fi | |
| 110 | ||
| 111 | # 7. Final Verification | |
| 112 | echo "--- Final Status Check ---" | |
| 113 | if vmadm list | grep -q "$UUID"; then | |
| 114 | echo "FAILURE: $UUID still appears in 'vmadm list'." | |
| 115 | vmadm list | grep "$UUID" | |
| 116 | else | |
| 117 | echo "SUCCESS: $UUID is no longer in 'vmadm list'." | |
| 118 | fi | |
| 119 | ||
| 120 | if zoneadm list -cv | grep -q "$UUID"; then | |
| 121 | echo "WARNING: $UUID still appears in 'zoneadm list'." | |
| 122 | else | |
| 123 | echo "SUCCESS: $UUID is no longer in 'zoneadm list'." | |
| 124 | fi | |
| 125 | ||
| 126 | # ############################################# |