Ubuntu’s cron.hourly (and, presumably, .daily, .weekly and .monthly) appears simple, but really has a jawdropping number of gotchas.

Mostly for my own sake, I’m archiving here how I finally got my cron.hourly script to run. It took months of off-and-on fiddling. Hopefully what I learned will be helpful to you.

$ ls -l /etc/cron.hourly/
-rwx------ 1 myusername myusername 143 Nov 27 23:03 myscriptname

Your script runs with as your user. So be sure that you have permissions to execute it.

$ cat /etc/cron.hourly/myscriptname

Your script can’t have any sort of file extension. Technically, your script can’t include any non-alphanumeric characters [except underscores (“”) and hyphens (“-“)]1, i.e. it has to match /[A-Za-z0-9-]*/. This is silly, but them’s the breaks…

#!/bin/sh

You must include a shebang line.

/usr/bin/scp /home/username/Desktop/todo.txt username@destination.com:/home/username/destination.com/todo.txt

Finally! The meat of the script! All of… one lines. (Its purpose is to copy my todo list to my website, where I can check it from my phone. It’s hidden behind HTTP auth.)

Use absolute paths, not relative paths. Your cron scripts are run with root permissions and god-knows-what path, so ensure it doesn’t get confused with a relative path.

Bonus:

$ run-parts --test /etc/cron.hourly

You can test whether run-parts understands your script with this command. It lists all the files that would run, if you ran run-parts. If your script is listed (and it works normally), it should run. If it doesn’t, there’s a problem. This tool, which I only discovered late in this process, ensures you don’t have to wait an hour to see if your script finally runs.