Skip to content

Instantly share code, notes, and snippets.

@swateek
Created March 27, 2026 04:23
Show Gist options
  • Select an option

  • Save swateek/1bbd781eda99f2e9019044cc5e38dcdf to your computer and use it in GitHub Desktop.

Select an option

Save swateek/1bbd781eda99f2e9019044cc5e38dcdf to your computer and use it in GitHub Desktop.
Repairs Vagrant VMs By Removing Lock and Swap Files
#!/bin/bash
###############################################################################
# Vagrant VMware Repair Script
#
# Purpose: Fix "Directory not empty" and disk access errors when a computer
# restarts while Vagrant is running or the VM crashes unexpectedly.
#
# Usage:
# bash vagrant-vmware-repair.sh <vm-name> # Interactive mode (recommended)
# bash vagrant-vmware-repair.sh <vm-name> --force # Skip confirmations
# bash vagrant-vmware-repair.sh --help # Show this help
#
# Author: Generated for Vagrant troubleshooting
# License: MIT
###############################################################################
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Default settings
FORCE_MODE=false
VAGRANT_DIR=""
VM_NAME=""
# Functions
show_help() {
cat << EOF
${BLUE}Vagrant VMware Repair Script${NC}
This script fixes common Vagrant VMware issues caused by:
- Computer restarts during VM operation
- VM crashes or hard shutdowns
- Corrupted lock files (.lck, .vswp)
- "Directory not empty" errors
${YELLOW}Usage:${NC}
bash vagrant-vmware-repair.sh <vm-name> # Interactive mode
bash vagrant-vmware-repair.sh <vm-name> --force # Skip confirmations
bash vagrant-vmware-repair.sh --help # Show this help
${YELLOW}Arguments:${NC}
<vm-name> Name of the Vagrant VM to repair (REQUIRED)
Example: ubuntu24-apple-m1
${YELLOW}Options:${NC}
--force Skip confirmation prompts (useful for automation)
--help Show this help message
${YELLOW}What it does:${NC}
1. Searches for your Vagrant project (.vagrant directory)
2. Locates the specified VM
3. Force halts the VM
4. Removes lock files (.lck, .vswp) that block disk access
5. Prepares VM for restart with 'vagrant up'
${YELLOW}Examples:${NC}
bash vagrant-vmware-repair.sh ubuntu24-apple-m1
bash vagrant-vmware-repair.sh my-dev-vm --force
bash vagrant-vmware-repair.sh --help
${YELLOW}Tip:${NC}
This script can be run from ANY directory - it will find your
Vagrant project automatically. Just make sure you're within the
same project hierarchy.
EOF
}
log_info() {
echo -e "${BLUE}ℹ${NC} $1"
}
log_success() {
echo -e "${GREEN}✓${NC} $1"
}
log_warning() {
echo -e "${YELLOW}⚠${NC} $1"
}
log_error() {
echo -e "${RED}✗${NC} $1"
}
confirm() {
local prompt="$1"
local default="${2:-n}"
if [ "$FORCE_MODE" = true ]; then
return 0
fi
local response
if [ "$default" = "y" ]; then
read -p "$(echo -e ${YELLOW}$prompt${NC} [Y/n]: )" response
response=${response:-y}
else
read -p "$(echo -e ${YELLOW}$prompt${NC} [y/N]: )" response
response=${response:-n}
fi
[[ "$response" =~ ^[Yy]$ ]]
}
find_vagrant_root() {
# Search up the directory tree for .vagrant directory
local current_dir=$(pwd)
while [ "$current_dir" != "/" ]; do
if [ -d "$current_dir/.vagrant" ]; then
VAGRANT_DIR="$current_dir"
return 0
fi
current_dir=$(dirname "$current_dir")
done
return 1
}
find_vmware_vm_dir() {
local vm_name="$1"
local vagrant_machines_dir="$VAGRANT_DIR/.vagrant/machines"
if [ ! -d "$vagrant_machines_dir" ]; then
return 1
fi
# Look for the specific VM in vmware_desktop
if [ -d "$vagrant_machines_dir/$vm_name/vmware_desktop" ]; then
echo "$vagrant_machines_dir/$vm_name/vmware_desktop"
return 0
fi
return 1
}
list_available_vms() {
local vagrant_machines_dir="$VAGRANT_DIR/.vagrant/machines"
if [ ! -d "$vagrant_machines_dir" ]; then
return 1
fi
echo ""
log_info "Available Vagrant VMs in this project:"
for vm_dir in "$vagrant_machines_dir"/*; do
if [ -d "$vm_dir" ]; then
local vm=$(basename "$vm_dir")
if [ -d "$vm_dir/vmware_desktop" ]; then
echo " • $vm"
fi
fi
done
}
repair_vm() {
local vm_dir="$1"
local vm_name=$(basename $(dirname "$vm_dir"))
log_info "Repairing VM: ${BLUE}$vm_name${NC}"
if [ ! -d "$vm_dir" ]; then
log_error "VM directory not found: $vm_dir"
return 1
fi
# Count lock files before
local lock_files=$(find "$vm_dir" -type f \( -name "*.lck" -o -name "*.vswp" \) 2>/dev/null | wc -l)
if [ "$lock_files" -gt 0 ]; then
log_warning "Found $lock_files lock file(s)"
# Remove lock files
if find "$vm_dir" -type f \( -name "*.lck" -o -name "*.vswp" \) -delete 2>/dev/null; then
log_success "Removed lock files"
else
log_error "Failed to remove some lock files (may need sudo)"
fi
else
log_info "No lock files found"
fi
# Check for corrupted snapshots
if [ -d "$vm_dir" ] && [ -n "$(find "$vm_dir" -name "*.vmsd" 2>/dev/null)" ]; then
log_warning "Found snapshot metadata files"
fi
}
main() {
echo -e "${BLUE}╔════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ Vagrant VMware Repair Script${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════════════╝${NC}"
echo ""
# Parse arguments
while [ $# -gt 0 ]; do
case "$1" in
--help)
show_help
exit 0
;;
--force)
FORCE_MODE=true
log_info "Force mode enabled (skipping confirmations)"
;;
-*)
log_error "Unknown option: $1"
show_help
exit 1
;;
*)
# First non-option argument is the VM name
if [ -z "$VM_NAME" ]; then
VM_NAME="$1"
else
log_error "Unexpected argument: $1"
show_help
exit 1
fi
;;
esac
shift
done
# Validate VM name was provided
if [ -z "$VM_NAME" ]; then
log_error "VM name is required!"
echo ""
show_help
exit 1
fi
log_info "Target VM: ${BLUE}$VM_NAME${NC}"
echo ""
# Find Vagrant root directory
log_info "Looking for Vagrant project (.vagrant directory)..."
if ! find_vagrant_root; then
log_error ".vagrant directory not found in current directory or parents"
echo ""
log_info "Make sure you're within a Vagrant project hierarchy"
exit 1
fi
log_success "Found Vagrant project: ${BLUE}$VAGRANT_DIR${NC}"
echo ""
# Find the specific VM
log_info "Looking for VM: ${BLUE}$VM_NAME${NC}..."
local vm_dir=$(find_vmware_vm_dir "$VM_NAME")
if [ -z "$vm_dir" ]; then
log_error "VMware VM not found: ${BLUE}$VM_NAME${NC}"
list_available_vms
exit 1
fi
log_success "Found VM at: ${BLUE}$vm_dir${NC}"
echo ""
# Confirm before proceeding
if ! confirm "Repair VM '${BLUE}$VM_NAME${NC}'? This will halt the VM and remove lock files." "y"; then
log_warning "Cancelled"
exit 0
fi
echo ""
# Halt VMs
log_info "Halting VM: ${BLUE}$VM_NAME${NC}..."
cd "$VAGRANT_DIR"
if vagrant halt "$VM_NAME" -f 2>/dev/null; then
log_success "VM halted"
else
log_warning "VM was already stopped (this is OK)"
fi
echo ""
# Repair the VM
log_info "Removing lock files..."
if repair_vm "$vm_dir"; then
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════════════╗${NC}"
log_success "Repair complete!"
echo ""
echo -e "${GREEN}Next steps:${NC}"
echo " 1. cd $VAGRANT_DIR"
echo " 2. vagrant up $VM_NAME"
echo ""
log_info "Your VM should start normally now"
echo -e "${BLUE}╚════════════════════════════════════════════════════╝${NC}"
else
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════════════╗${NC}"
log_error "Repair encountered errors"
echo ""
echo -e "${YELLOW}Try these next:${NC}"
echo " 1. Run: vagrant destroy $VM_NAME -f"
echo " 2. Then: vagrant up $VM_NAME"
echo -e "${BLUE}╚════════════════════════════════════════════════════╝${NC}"
exit 1
fi
}
# Run main function
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment