Mac OS diskutil does not work from cron

Being a backup freak, I have implemented a backup routine, which copies my main Mac disks to others, either locally or on other Macs. For this, I use two programs, basically, SuperDuper! and ChronoSync. SuperDuper! is used for local copies (copies to disks in my main Mac), while ChronoSync is used to copy disks between disks of my main Mac and disks on my other Mac computers. Of course, I have also created several scripts which monitor those backup operations, so that I have a list of copies done, on a daily basis. In that way, I always know which disk contains my latest backup.

Part of my backup operation, is to check my disks for free space. I have created a special script to do that, the script is run every evening at midnight by cron, and registers its results in my log files. Yesterday though, something strange made me look in that script. I remembered that there was one of my backup disks, which was almost full to capacity (96% used space), and I was not getting an error message for this disk in my log, as I should! So I went in the script to figure out what was wrong. What was weird was that when I run the script from the Terminal, I was getting an error about that almost-full disk! I couldn’t understand what why the log file showed no disks exceeding the specified limit (85%) while the script was showing the disk being over the limit. And then it occured to me, that when I was running the script from cron, I couldn’t see my backup disks being mounted, like I could when I was running the script from Terminal. Hint! Hint!

In order to figure out the problem, I created another small script, which was mounting two of my disks. Here it is:


#!/bin/bash

SAFE_FOLDER=”~/Desktop”
cp /dev/null $SAFE_FOLDER/DC_time.txt
cp /dev/null $SAFE_FOLDER/DC_test.txt

echo “`date +%H:%M`” > $SAFE_FOLDER/DC_time.txt

DEV=$(diskutil list | grep -E “\bBackup_Disk\b” | awk -v N=6 ‘{print $N}’)
diskutil mount /dev/$DEV >> $SAFE_FOLDER/DC_test.txt

DEV=$(diskutil list | grep -E “\bCentos_Backup\b” | awk -v N=6 ‘{print $N}’)
diskutil mount /dev/$DEV >> $SAFE_FOLDER/DC_test.txt

diskutil unmount /Volumes/MacSSD_Int >> $SAFE_FOLDER/DC_test.txt
diskutil unmount /Volumes/Centos_Backup >> $SAFE_FOLDER/DC_test.txt

As you can see, I am using two files, one is the file DC_time.txt, where I store the time the script was run, and DC_test.txt, where I save the output if the diskutil commands. SAFE_FOLDER is a directory where the script has write permissions, which is my Desktop directory. When I run the script from Terminal I could see the two disks being mounted on my Desktop, and unmounted, as I was expecting. The file DC_test.txt contained the followings:

Volume MacSSD_Int on /dev/disk6s2 mounted
Volume Centos_Backup on /dev/disk8s3 mounted
Volume MacSSD_Int on disk6s2 unmounted
Volume Centos_Backup on disk8s3 unmounted

So everything was as expected.

When I run the script from cron though, I couldn’t see the mounted disk icons on my Desktop, and the DC_test.txt file contained nothing!!! What was also strange, was that I was getting no errors in the system log file.

Puzzled! I made sure that I was running the script as root, from Terminal and that I was using root’s cron to run it.

I did some Google search trying to figure this out. You know, if you look for errors occuring in our computers, you usually get pages and pages of results, some more relevant than the others. This time, I got nothing! By changing my search terms, I finally got one single result. Check it out here:

Wow! There is a comment, at the bottom of this discussion, from none other than the author of SuperDuper!, a program I use. So I wrote to Dave Nanian, the coder behind SuperDuper! who verified what I had suspected.

diskutil DOES NOT WORK INSIDE CRON !!!

Dave was kind enough to suggest that I use launchd instead of cron, to run my script. After a few failed efforts to create the required .plist file, which is necessary to run my script as a Daemon, launched by launchd, I finally came up with the correct settings. The first time my script was run by launchd, boom! The disks mounted fine, shown on my Desktop and the DC_test.txt file contained the same info, as when I run the script from Terminal! Success!!!

So the conclusion is:

For some strange reason, Apple does not allow diskutil to be run from cron! There is no way you can mount a disk using diskutil from inside a script you run by cron. If you need to run diskutil commands at a predefined time, use launchd.

For those interested on how to do the same thing, here is a short description. There are plenty of links in Google for that, but since they are not all correct, here is how I did it.

First, you need to create a .plist file, which contains the followings:

plist file

You can download this file, by clicking here: .plist file. Copy its contents in your editor.

Save the file you just created, using a name like com.mydomain.check_disk_space.plist on your Desktop.

Please note that my script which is doing the disk testing, resides in /Volumes/MyUsersDisk/John/Backup_Scripts directory and it is named Check_Disk_Space.sh. This is the file that contains the diskutil commands that do not run when using cron. That is a shell script. Also, please note that in the code above, I have specified that I want the script to be run every evening at 00:01 hour. You can obviously change these values to whatever time you want your script to run.

Then, copy that file to your /Library/LaunchDaemons directory.

To enter the file in the launchd queue, issue the following command.

launchctl load com.mydomain.check_disk_space.plist

If you do not get any error message, you are all set and your script will be run at the time you specified. To remove your script from launchd queue, enter:

launchctl unload com.mydomain.check_disk_space.plist

And there you have it! You can now run your script, which contains the diskutil commands at your specified time.

P.S.: I have no idea when Apple started this thing, with which Mac OS version. So please keep that in mind.

Leave a Reply

Your email address will not be published. Required fields are marked *