Time Machine Auto-mount/unmount Drive OS X

Here’s a way to avoid having to manually mount and unmount (eject) a USB backup drive before and after a Time Machine backup on OS X Lion or later by using a shell script and creating a LaunchAgent.

I have a USB backup drive connected through my monitor to my Macbook Pro and I often find myself wanting to quickly unplug and go without the consequences of the drive not being ejected properly. As well, I need the drive to be mounted so that Time Machine can do its automatic backups.

Well I found a way to avoid having to manually mount and unmount (eject) my drive by using shell scripts and LaunchAgents to achieve the task. The added benefit is that I have control over the timing of the frequency of the Time Machine backups too!

Note: This works on OS X Lion or later. There is one caveat, in that when attempting to restore files from your Time Machine drive, you will need to disable the launch agents, as well you should re-activate Time Machine in the system preferences so that the system recognizes the drive for restore purposes.

Step 1

Create a plain text file named timemachine_mounter.sh with the following contents:

#!/bin/bash
# Set the drive name that we mount for our backups 
vol_mount="Time Machine"
# Conditional argument: if mounted entry has the volume name in the variable string
if ! mount | grep "$vol_mount" ; then
	# Drive isn't mounted, so: mount. A LaunchAgent will pick this OnMount action up and run the backup script
	diskutil mount "$vol_mount"
else
	# Drive is mounted, so: run the backup script
	timemachine_backup.sh
fi

Save the file in the /usr/local/bin/ directory at the base of your system drive. You may need to first save the file to your desktop then use finder to move it to that directory, it will ask to authenticate. Or use sudo in Terminal to move the file there instead, and make sure that ownership belongs to you (the user that logs in), in my case the assigned user:group was mike:staff.

Step 2

Create a plain text file named timemachine_backup.sh with the following contents:

#!/bin/bash
# Set the drive name that we mount for our backups 
vol_mount="Time Machine"
# Conditional argument: if mounted entry has the volume name in the variable string
if mount | grep "$vol_mount" ; then
	# Drive is mounted, so: backup and then eject after
	tmutil startbackup -b && 
	diskutil unmount "$vol_mount"
fi

Save the file in the /usr/local/bin/ directory again with the same ownership credentials as the previous script.

Step 3

Create a plain text file named com.apple.TimeMachine_OnLoadSchedule.plist with the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd>
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>com.apple.TimeMachine_OnLoadSchedule</string>
	<key>RunAtLoad</key>
	<true/>
	<key>StartInterval</key>
	<integer>7200</integer>
	<key>Program</key>
	<string>/usr/local/bin/timemachine_mounter.sh</string>
</dict>
</plist>

Save the file in the ~/Library/LaunchAgents/ directory inside your User folder/directory (~/).

What the above file does is register in the system to run the mounter script:

  • when I first log in
  • consecutively every 2 hours

Step 4

Create a plain text file named com.apple.TimeMachine_OnMount.plist with the following contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd>
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>com.apple.TimeMachine_OnMount</string>
	<key>StartOnMount</key>
	<true/>
	<key>Program</key>
	<string>/usr/local/bin/timemachine_backup.sh</string>
</dict>
</plist>

Save the file in the ~/Library/LaunchAgents/ directory as well.

What the above file does is register the system to run the Time Machine backup script whenever the drive gets mounted. This can happen when:

  • I physically connect the drive
  • the scheduler LaunchAgent above, runs the driver mounter script

In Terminal, make sure the shell scripts are executable, unload the default plist (if you didn’t turn off your Time Machine automatic backups in the System Preferences) and finally load the new LaunchAgent in your local LaunchAgent startup folder:

chmod +x /usr/local/bin/timemachine_*.sh
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.backupd-auto.plist
launchctl load ~/Library/LaunchAgents/com.apple.TimeMachine_OnMount.plist
launchctl load ~/Library/LaunchAgents/com.apple.TimeMachine_OnLoadSchedule.plist

Lastly…

You can change the com.apple.TimeMachine_OnLoadSchedule.plist’s integer value for the starting interval 7200 integer to something more reasonable (e.g., 3600 seconds is one hour,… multiply at will.) I have my backups run every two hours.

The good thing about using a LaunchAgent is that:

  • if your computer goes to sleep or is shut off, the backup will begin at the next time you log in and reset the countdown from that point onward
  • if Time Machine is already running it won’t try to run the process until the next projected sync time
  • if the drive is freshly connected or mounted already, Time Machine will begin backing up your changes and eject after its done
  • Michael Shulman

    I believe this line:

    chmod +x /bin/automount_timemachine.sh

    should be:

    chmod +x /bin/timemachine_*.sh

    -ms

    • Ahh yes, that will work nicely! Thanks for the revision!

      • dwain0Wilder

        Fascinating. I found this while looking for just this solution, in order to increase lifetime by not having the Time Machine volume sat idly spinning.

        But I have a MacBook duo-core on snow leopard (10.6.8). Will this script work there?

        • I do believe it should, but I cannot be certain since all of my machines that run the script are using Mavericks. Give it a try!

  • jason

    I cannot get the plist from steps 3 and 4 to load. I consistently get a “nothing found to load” error.

    I copied the scripts above to a textedit document, saved and then changed the extension to a .plist before copying both files into the ~/Library/LaunchAgents/ folder.

    I’m at a loss for what is going wrong. Any help would be greatly appreciated!

    • Can you clarify,… which scripts did you paste into the plist?
      There are four files in total, each with separate content.

      As a rule, plists don’t necessarily contain “scripts”.

      But .sh files (are shell scripts).

      • jason

        Thanks for the quick replies!

        In steps 1 and 2, I copied and pasted each script you provided into their own textedit file and saved each according to your naming provided. Next I changed the file name to a .sh and moved them into the /bin folder (Macintosh HD –> bin) folder.

        Next I copied the contents in steps 3 and 4 into their own textedit file and named each according to your naming scheme. I renamed the extension of each file to a .plist and I saved each into the ~/Library/LaunchAgents/ folder (I figured out the difference in the two LaunchAgents locations with some googling but was stuck there for a bit).

        Everything seems to be OK until I get to here:

        launchctl load ~/Library/LaunchAgents/com.apple.TimeMachine_OnMount.plist
        launchctl load ~/Library/LaunchAgents/com.apple.TimeMachine_OnLoadSchedule.plist

        and that is where I get the nothing found to load error. Also, how do I know if the chmod +x /bin/timemachine_*.sh command actually works? I don’t get any errors so I assumed it did, but when I open up that folder the files are still shown as a text file and not a Unix Executable File.

        This setup is exactly what I’ve been searching for, but terminal is new to me so I’m learning as I go. Thanks for the help!

        • Did you make sure to make your textedit file a plain text file? See the attached image for details on how to do that.

          Generally, Terminal doesn’t give you a “completed” response, if it was successful at its commands … it often just sends you back to the prompt.

          • jason

            That worked! Now, another (hopefully final) question.

            I never logoff my machine and instead sleep it when I’m stepping away. Then, I wake and login to unlock it when I return. Can the script be modified to backup upon wakeup/unlock instead of at login and an interval following? I assumed this would occur this way, but I guess unlocking isn’t treated the same and logging in.

            This modification appears to be working great otherwise and is otherwise exactly what I’ve been trying to do for a long time. Thank you.

          • Ask yourself this: are you going to be having files change while your computer is asleep?

            If not: then the most recent backup would likely be the last one that was performed when your computer was last awake. So you don’t need to run a backup if nothing gets changed while your system was asleep.

            If you do, you somehow have files change while your computer is asleep or locked: this is very rare, and I don’t necessarily know how to address that. There’s no system on wake-up event programmed into LaunchD that I know of.

          • jason

            My thought for having it backup when I wake my Mac from sleep and unlock/login was because sometimes take a quick look at email in the morning and then disconnect it from my monitor and head out the door. Since I wouldn’t necessarily know at what time my backup from the night before ran, it would be nice to leave knowing a backup just ran.

            In reality and the more I think about it, it’s not a big deal and I can always manually mount the drive and have it run a quick backup before I disconnect it if I need to.

            All your help with this was much appreciated!

          • There are some solutions that you could install from this discussion online here:

            http://apple.stackexchange.com/questions/27036/possible-to-run-scripts-on-sleep-and-wake

            Then just direct them to run timemachine_mounter.sh and that will mount the drive. Once that occurs, the system will recognized that the drive is newly mounted and then start the backup.

    • Also make sure that you placed the plists into ~/Library/LaunchAgents/ and not /Library/LaunchAgents/
      (note the “~” before)

      If you place the files into the “~” prefixed folder, that will go into the user’s LaunchAgents that load up when they log in. Otherwise, you are attempting to load LaunchAgents from the system startup (before logging in).

      I chose to only have backups happen while I am logged in, because, well, essentially that’s the only time when my files are being changed and need to be backed up.

  • jason

    Hi Mike, have you tested this with Mavericks yet? Just curious if it works…. this has been working great for me with Mountain Lion since you helped me through my issues and I don’t want to lose this functionality.

    Thanks!

    • I have installed mavericks, and the job hasn’t loaded due to issues with permissions and user ownership, and thus it skips the job. However I do not know why the system says “Dubious ownership on file (skipping)”, if nothing changed, and other jobs in the same directory have the same ownership and permissions.

    • Well, I found out that Installing Mavericks has deleted the two shell script files that we used to place in the root bin directory. That being said, I recreated them and placed them in the /usr/local/bin/ directory (where they really should be after researching more). I made them executable again by using the command in the post. Then I edited the two plist files to reflect the new locations of the .sh files. Then I reloaded both of them by running a launchctl unload -w command on the two plist files in their ~/LaunchAgents/ directory, then the load command in the post as well.

      I’ve edited the post to reflect all of the changes. If you follow the steps again, you’ve already done half of the work.

      • jason

        Hi Mike,

        I made the changes you discussed and followed the steps again. I thought I had everything working but turns out the volume wasn’t mounting on its schedule. If I mounted it manually the backup would run. So, I went back in and went through the steps again. I realized I never unloaded the old .plist files from steps 3 and 4 before so I ran launchctl unload -w ~/Library/LaunchAgents/com.apple.TimeMachine_OnMount.plist and launchctl unload -w ~/Library/LaunchAgents/com.apple.TimeMachine_OnLoadSchedule.plist then continued with loading the new .plist with
        launchctl load ~/Library/LaunchAgents/com.apple.TimeMachine_OnMount.plist and

        launchctl load ~/Library/LaunchAgents/com.apple.TimeMachine_OnLoadSchedule.plist When attempting to load both .plist files, I get “nothing found to load” and no idea what I’m missing. Do you have any suggestions as to where I’m going wrong? Thanks!

        • Are you sure you’re pointing to the correct filenames of the plists? I think I may have cleaned that up to reflect a more semantic naming of what the plists do.

          • jason

            I’m positive I am. It just seems the plist’s do not want to load. I know there has to be an easy explanation for it, but I’m not sure what it is. Did I unload the prior plist’s correctly?

          • if you type:

            nano ~/Library/LaunchAgents/com.apple.TimeMachine_OnLoadSchedule.plist

            … and it comes up blank — then you’re not pointing to the correct file location. They are not in your User Folder’s LaunchAgents folder (be sure that you’re placing it in your User defined LaunchAgents directory for the load command to work .. (that’s what the “~” is for)

            To get out of nano press ctrl+x

          • jason

            Doing that command returns the OnLoadSchedule.plist in terminal so that seems okay…

          • jason

            Through terminal, I was able to execute the two .sh files to verify that they ran and they did so I confirmed my issue came down to the 3rd and 4th lines of the commands above. After creating completely new .plist files with no luck, I modified each command line to read:

            sudo launchctl load -w -F ~/Library/LaunchAgents/com.apple.TimeMachine_OnMount.plist

            and

            sudo launchctl load -w -F ~/Library/LaunchAgents/com.apple.TimeMachine_OnLoadSchedule.plist

            and they both loaded (finally). Do you know why this modification would be necessary and is it okay to run this way?

            Thanks for all your help and suggestions!

          • jason

            It seems that what really goofed something up was when I ran

            launchctl unload -w ~/Library/LaunchAgents/com.apple.TimeMachine_OnMount.plist

            and

            launchctl unload -w ~/Library/LaunchAgents/com.apple.TimeMachine_OnLoadSchedule.plist

            earlier so the newly modified plist could be loaded. Did I do something wrong here?

          • Please try this:

            launchctl list | grep Time

            Do any entries come up?

          • jason

            If I paste the line above directly into terminal and hit enter, nothing comes up.

          • jason

            The two load commands work just including the -w (without the sudo or -F like I posted above) to force load the plist. From what I’ve been reading, the message “nothing found to load” means that the config is overriden by another config. You force the loading by using the option “-w” when using launchctl load or unload. When having to force the load or unload of a plist file, it means that you have a config which overrides the plist. This overriding is created when you use the “-w” otherwise no override will be added to the overrides file. To prevent this, it sounds as though the plist can be modified but I’m not sure what needs to be modified.

            I should have noted earlier that this setup is on a brand new Macbook Pro that came with Mavericks installed. I had no problems on my prior machine which I upgraded to Mavericks shortly before I sold it although Mavericks did delete the two .sh files (as you mentioned occurred to you in your initial post) so I had to copy them back over into the bin folder and everything work flawlessly again.

          • go to your ~/Library/LaunchAgents/ folder and type:

            ls -Gal

            Is there an @ symbol beside the permissions for the plists? If so, perform the next command:

            xattr -l com.apple.TimeMachine_On*

            What do the two entries say at the end?

          • jason

            I do get an @ symbol for both of them. Here’s what I get:

            JRS-Macbook-Pro-447:LaunchAgents JRS$ ls -Gal

            -rw-r–r–@ 1 JRS staff 423 Dec 1 00:34 com.apple.TimeMachine_OnLoadSchedule.plist

            -rw-r–r–@ 1 JRS staff 367 Dec 1 00:35 com.apple.TimeMachine_OnMount.plist

            JRS-Macbook-Pro-447:LaunchAgents JRS$ xattr -l com.apple.TimeMachine_On*

            com.apple.TimeMachine_OnLoadSchedule.plist: com.apple.TextEncoding: utf-8;134217984

            com.apple.TimeMachine_OnMount.plist: com.apple.TextEncoding: utf-8;134217984

            Now what?

          • okay .. I just wanted to make sure that there weren’t any extra bits assigned to the file that were blocking them from loading up. Seems like you figured it all out though.

          • jason

            Thanks again for all your help!

          • That’s good, there are no actively running processes with the word “Time” in their process name.

          • jason

            I think I figured it out… if I use -w to unload the two LaunchAgents, then I have to include -w to load them again. However, if I unload them without using the -w then I can load them without the -w and can use your 4 lines of script above exactly. I don’t know nearly enough about how these commands work to know why it worked this way but it’s working. See below:

            JRS-Macbook-Pro-447:~ JRS$ launchctl unload -w ~/Library/LaunchAgents/com.apple.TimeMachine_OnMount.plist

            JRS-Macbook-Pro-447:~ JRS$ launchctl load ~/Library/LaunchAgents/com.apple.TimeMachine_OnMount.plist

            nothing found to load

            JRS-Macbook-Pro-447:~ JRS$ launchctl unload -w ~/Library/LaunchAgents/com.apple.TimeMachine_OnLoadSchedule.plist

            JRS-Macbook-Pro-447:~ JRS$ launchctl load ~/Library/LaunchAgents/com.apple.TimeMachine_OnLoadSchedule.plist

            nothing found to load

            JRS-Macbook-Pro-447:~ JRS$ launchctl list | grep Time

            ——————————————————————
            JRS-Macbook-Pro-447:~ JRS$ launchctl unload ~/Library/LaunchAgents/com.apple.TimeMachine_OnMount.plist

            JRS-Macbook-Pro-447:~ JRS$ launchctl unload ~/Library/LaunchAgents/com.apple.TimeMachine_OnLoadSchedule.plist

            JRS-Macbook-Pro-447:~ JRS$ chmod +x /usr/local/bin/timemachine_*.sh

            JRS-Macbook-Pro-447:~ JRS$ sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.backupd-auto.plist

            JRS-Macbook-Pro-447:~ JRS$ launchctl load ~/Library/LaunchAgents/com.apple.TimeMachine_OnMount.plist

            JRS-Macbook-Pro-447:~ JRS$ launchctl load ~/Library/LaunchAgents/com.apple.TimeMachine_OnLoadSchedule.plist

          • Your bash scripts should work fine regardless of the plists for the launch agent.

  • Super Duper

    Hi. Thanks for this, just implemented this on Yosemite 10.10.3. However it didn’t work without modification, at least not with this OSX version + encrypted external USB drive. I changed the line in timemachine_backup.sh that says “diskutil eject “$vol_mount” to diskutil unmount “$vol_mount” – with eject it would not mount the drive again. My guess is that eject makes the encryption state to change to “locked”.

    • Thanks SD, cool! I wonder, did you have the password for the encrypted drive stored in your system Keychain?

  • Thanks. I was planning on doing the same. You saved me a lot of time!

    There’s one thing I don’t fully understand though. Is it necessary to turn off Time Machine in the System Prefs as well as unload com.apple.backupd-auto? They don’t seem to do the exact same thing. When I set the big TM switch to off, the backupd-auto service is unloaded, but on unloading the service, the switch doesn’t reflect this.

    What can happen when you don’t disable the launch agents when restoring files?

    • I can’t explain what is happening on your machine, but turning off Time Machine in the System Preferences on my machine prevents the computer from running backups on its (apple’s) own automatic schedule (or at least it should in your case as well). It may not unload any agents, but what it may do is set a plist setting or disable that MTM snapshot which in turn lets Time Machine know to not backup automatically.
      All we’re doing here is circumventing the default and augmenting it with our own customization: to backup when we plug the drive in, and unmount after, then remount at a future time and backup, then cycle until either the drive is not mountable or we disable our custom agents.

      When restoring files from Time Machine, you need to disable the launch agents that we create here because they work in concert to backup the computer when you mount the drive (physically plug it in). And in a short time (at least in my experience of backing up in most cases), the backup completes and unmounts the disk before I can find the files I want to restore from Time Machine.

      • Turning off TIme Machine in System Preferences It’s just that you didn’t say to turn off Time Machine in System Preferences, so I wanted to know if there was any difference with just unloading com.apple.backupd-auto. Setting the switch to OFF does unload that agent, but additionally also the MTM agent. I suppose we want to keep the latter, so the recommendation should be to not switch Time Machine to OFF, but unload com.apple.backupd-auto from the command line. In that case the switch stays in the ON position, so I think you might not need to touch it when you want to restore files.

        Restoring files Ah yes, of course it will be difficult to restore any files if the drive can be unmounted suddenly. I was thinking of file corruption when I read your warning and that’s why I asked.