Feedback Needed: AppleScript for Automating Time Machine Backup

Hi all,

I’ve developed an AppleScript that automates Time Machine backups, including checking if the backup drive is mounted, verifying backup status, using caffeinate to prevent sleep, and ejecting the drive post-backup. I’m looking for feedback on its reliability and potential edge cases (e.g., drive disconnection mid-backup, error handling improvements). Any suggestions or insights from experienced users would be appreciated.

Here is my script:

#!/usr/bin/osascript

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Time Machine Backup
# @raycast.mode silent

# Optional parameters:
# @raycast.icon 💾
# @raycast.packageName Utilities
# @raycast.needsConfirmation true

# Documentation:
# @raycast.description Runs Time Machine backup

-- Define the Time Machine volume name
set timeMachineVolume to "SSD"
-- Initialize a global variable to store log messages
global statusMessages
set statusMessages to {}

-- Function to log messages and collect them for Shortcuts (with notifications)
on logMessage(messageText)
	copy messageText to the end of statusMessages -- Add message to the list
	log messageText -- Log to Script Editor for debugging
	display notification messageText with title "Time Machine Backup"
end logMessage

-- Function to check if the drive is mounted
on isDriveMounted(volumeName)
	try
		set result to do shell script "mount | grep '/Volumes/" & volumeName & "'"
		logMessage("Drive is mounted: " & result)
		return true
	on error
		logMessage("Drive " & volumeName & " is not mounted.")
		return false
	end try
end isDriveMounted

-- Function to check if Time Machine backup is running
on isBackupRunning()
	try
		set status to do shell script "tmutil status | awk -F '= ' '/Running/{gsub(/;/,\"\",$2); print $2}'"
		logMessage("Time Machine running status: " & status)
		return status is "1"
	on error
		logMessage("Failed to check Time Machine status.")
		return false
	end try
end isBackupRunning

-- Function to start Time Machine backup with caffeinate
on startBackup(volumeName)
	if not isDriveMounted(volumeName) then
		logMessage("Drive " & volumeName & " is not mounted. Backup cannot proceed.")
		error "Drive not mounted."
	end if
	
	-- Start caffeinate to prevent sleep; capture its PID
	set caffeinatePID to do shell script "caffeinate -dims & echo $!"
	logMessage("Caffeinate started with PID: " & caffeinatePID)
	
	logMessage("Checking Time Machine status...")
	if isBackupRunning() then
		logMessage("Backup is already in progress.")
	else
		logMessage("Starting Time Machine backup...")
		try
			set result to do shell script "tmutil startbackup --auto --block"
			logMessage("Backup completed successfully.")
		on error errMsg
			logMessage("Failed to complete backup. Please check your Time Machine configuration. Error: " & errMsg)
			do shell script "kill " & caffeinatePID -- terminate caffeinate on error
			error "Backup failed."
		end try
	end if
	
	-- Terminate caffeinate after backup completes
	do shell script "kill " & caffeinatePID
	logMessage("Caffeinate process terminated.")
end startBackup

-- Function to eject the Time Machine volume
on ejectVolume(volumeName)
	logMessage("Preparing to eject Time Machine volume...")
	try
		set unmountResult to do shell script "diskutil unmount '/Volumes/" & volumeName & "'"
		logMessage("Volume unmounted successfully: " & unmountResult)
		
		set ejectResult to do shell script "diskutil eject '/Volumes/" & volumeName & "'"
		logMessage("Volume ejected successfully.")
	on error errMsg
		logMessage("Error during ejection: " & errMsg)
	end try
end ejectVolume

-- Main script execution
try
	logMessage("Script started.")
	startBackup(timeMachineVolume)
	ejectVolume(timeMachineVolume)
	logMessage("Script completed successfully.")
on error errMsg
	logMessage("Script failed with error: " & errMsg)
end try

-- Return the collected status messages to Shortcuts
return statusMessages


Thanks!

Hi @zonal-oculars. Welcome to MacScripter.

Just looking through your script quickly, AppleScript’s result variable is automatically set to the result of each result-returning command. It’s not meant to be set explicitly.