External USB drive unmounts or powers down randomly

Thanks Eric - I think we ended up going down the same rabbit hole. I had previously tried xscreensaver, xfce-screensaver and no screensaver at all with no discernible difference in behavior.

I threw this together earlier today, reformatted the USB drive to ext4, fired up the cooling fan on the drive and started a new backup. It’s been running almost eight hours now without any indication of the disc powering down. I was going to wait until morning to share so as not to jinx it but after your post I thought I should share.

#!/bin/bash
##===================================================================##
# File.......: mksim (mouse keyboard simulator)
# Date.......: May-11-2026
# Description: Utility script to simulate mouse and keyboard activity.
#              Considered safe for use to prevent power mangement from
#              powering down devices during extended processing (e.g.
#              to prevent unmounting USB external drives during 
#              backup processing). Screen burn is still a problem
#              particularly for OLED displays so extended use is 
#              discouraged since this will defeat screen savers and 
#              other power management services.
##===================================================================##
set +x

# default delay is 30 seconds
delay=30

# check for a cmdline delay override
if [ $# -eq 1 ]; then
  if [[ "${1}" =~ ^[0-9]+$ ]]; then
    delay=${1}
  fi
fi

if ! type -P xdotool &> /dev/null; then
  printf "\nRun \"sudo apt install xdotool\" to use this utility\n\n" 
  exit 1
fi

# Get the display geometry
read width height <<< $(xdotool getdisplaygeometry 2>/dev/null)
if [[ -z "$width" || -z "$height" ]]; then
  printf "\nFailed to get display geometry - aborting!\n\n"
  exit 1
fi

# log some startup messages
printf "\nStarting at: `date '+%Y/%d/%m %H:%M:%S'`\n"
printf "Display geometry is width:$width height:$height\n"
printf "Using loop delay $delay\n"
printf "Infinite loop - press <CTL+C> to terminate\n\n"

# initialize some variables
x=0
y=0
xincr=$(($width / 20))
yincr=$(($height / 20))

# main loop
while [ 1 ]
do
  # simulate a mouse move
  xdotool mousemove $x $y

  # increment the mouse coordinates
  (( x += $xincr ))
  (( y += $yincr ))

  # if coordinates get outside the display reset to the origin
  [[ $x -gt $width ]] && x=0
  [[ $y -gt $height ]] && y=0

  # simulate a key press for the left shift key - should be a noop
  # this seems to be more reliable than the mouse move for preventing idle detection
  # the mouse movements provide a nice visual confirmation everything's working
  xdotool key Shift_L

  # pause
  sleep $delay
done