How to Identify and Terminate Processes Locking an External HDD on macOS for Safe Ejection


2 views

Every macOS user has encountered this situation: you right-click an external drive and select "Eject," only to get the frustrating "Disk Not Ejected Properly" message because some process is holding files open. Forcing ejection risks data corruption, especially when dealing with important storage devices.

The most reliable method uses the lsof (list open files) command in Terminal. Here's the complete solution:

# First, identify your disk's mount point
diskutil list

# Then run lsof against that mount point
lsof +D /Volumes/YourDriveName

Example output will show processes with open file handles:

COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
mds        123 root   24r   DIR   1,12     1024    2 /Volumes/BackupDrive
Adobe_CC   456 user  txt    REG   1,12   123456  789 /Volumes/BackupDrive/Project/file.psd

For more detailed analysis, combine lsof with other UNIX tools:

# Find all processes accessing the volume
lsof +f -- /Volumes/YourDriveName | awk '{print $1,$2}' | sort | uniq

# Get full process tree information
ps auxwww | grep [PID_from_lsof]

Create a bash function for your .zshrc or .bash_profile:

function find_disk_users() {
    if [ -z "$1" ]; then
        echo "Usage: find_disk_users /Volumes/DriveName"
        return 1
    fi
    echo "Processes using $1:"
    lsof +D "$1" | awk 'NR==1 || !/^COMMAND/ {print $1,$2,$9}' | sort | uniq
}

function safe_eject() {
    find_disk_users "$1"
    read -p "Kill these processes? (y/n) " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        lsof +D "$1" | awk 'NR>1 {print $2}' | xargs kill -9
        diskutil eject "$1"
    fi
}

For those preferring graphical tools:

  • Use Activity Monitor's "Disk" tab
  • Try third-party utilities like What's Keeping Me or Ejector

To avoid this issue in development environments:

# For Node.js projects
process.on('SIGINT', () => {
  // Clean up file handles
  db.close() 
  fs.closeSync(fd)
  process.exit()
})

Remember that some macOS services (like Spotlight or Time Machine) may periodically access drives. Consider temporary disabling them before maintenance:

# Disable Spotlight indexing
sudo mdutil -i off /Volumes/YourDriveName

Many macOS users encounter the frustrating situation where they can't safely eject an external drive because the system claims it's "in use." This commonly occurs when:

  • Running Time Machine backups
  • Having open files in applications like Photoshop or Final Cut Pro
  • Background processes accessing the drive
  • Spotlight indexing in progress

The most reliable way to identify processes accessing your drive is through the command line. Open Terminal and run:

lsof | grep "/Volumes/YourDriveName"

Replace "YourDriveName" with your actual volume name. This will output all processes with open file handles to that volume.

A typical output looks like:

Photoshop  1234  username  txt   REG   1,4  2147483648 123456789 /Volumes/ExtDrive/Project.psd

Key columns to note:

  • Column 1: Process name
  • Column 2: Process ID (PID)
  • Last column: Accessed file path

For frequent use, create a shell script:

#!/bin/bash
if [ -z "$1" ]; then
    echo "Usage: $0 /Volumes/DriveName"
    exit 1
fi
lsof | grep "$1" | awk '{print $1, $2}' | sort | uniq -c | sort -nr

Save as find_drive_users.sh, make executable with chmod +x, then run with your volume path.

For those preferring graphical tools:

  1. Open Activity Monitor
  2. Go to the Disk tab
  3. Sort by "Bytes Written" or "Bytes Read"
  4. Look for processes with significant activity

Once you've identified the PID, you can:

  • Gracefully quit the application normally
  • Force quit using: kill -9 PID (use cautiously)
  • For system processes: sudo kill -9 PID

Consider these preventive measures:

# Disable Spotlight indexing for external drives
sudo mdutil -i off /Volumes/DriveName

# Create an eject alias that checks first
alias safe_eject='lsof /Volumes/DriveName >/dev/null 2>&1 || diskutil eject /Volumes/DriveName'

If you must force eject, first unmount as safely as possible:

diskutil unmount force /Volumes/DriveName

Then physically disconnect. Run disk repair afterward:

diskutil verifyVolume /Volumes/DriveName
diskutil repairVolume /Volumes/DriveName