Scheduling posts with Jekyll

[Tweet : nvALT]

After my downloads system was sorted (post coming up) and I had a writing workflow worked out, my big concern with my Jekyll system was scheduling future posts. I tend to write in streaks and, given that very little of my work is exactly time sensitive, spread the posts out to make up for the days I decide to sleep in my free time. That’s a little harder to do with static blogs.

You can rig up a whole setup with Hazel and Dropbox and triggers that make your site build when certain filename prefixes show up, but it gets tedious and sometimes unreliable. While there are some elements of that in my current system — especially with the work I’m doing to be able to post remotely — it’s not a setup I want to rely on.

So here’s what I do have going…

The what

  1. Write a draft in my _drafts folder with a name that’s just a slug. It doesn’t even matter what the slug is, it will be renamed with the date and a new slug based either on the “title:” field or a “slug:” field if it exists. I’ll go into more detail on my draft system soon.
  2. Add a “date:” field in the headers of the draft for some time in the future.
  3. Run rake publish. Without arguments, my publish command scans my _drafts folder and offers a menu of recently-edited drafts. I type a number and the system reads it in.
  4. Headers are checked, modified and updated. If a date header is found at this point, it’s checked against the current time. If the post is for the future, the system schedules a build and deploy for that moment. My Jekyll is configured to not publish future-dated posts, so I can do other builds before the post goes up without worrying about spoiling surprises.
  5. Morning comes, the sun comes up, my post goes live.

The how (meet the at command)

The basis of the system is the Unix at command. The at command is really, really handy and available on most Unix flavors. I’ve been told it’s deprecated, but it’s been so dependable thus far that I’m not certain why it would be (other than Apple passed on it in favor of launchd). With this command you can type something like at 12PM tomorrow, then type a series of commands and terminate with ^d. It will report that a task is scheduled and that task will run, whether you log out of the shell or not. It’s perfect for starting jobs on remote servers, too, and has a batch mode that will queue jobs as CPU allows.

To enable at on OS X, you need to modify its launchd plist. On Lion and later this can be done with just the launchctl command1.

launchctl load -w /System/Library/LaunchDaemons/

The plist file comes with a disabled flag set, but running load -w will override that, so you don’t have to worry about it. Once you’ve run that command, you should be able to test at out.

  1. Open a terminal and type: notifyutil -1 && say "Boom"
  2. Open a second terminal and type:

     $ at now + 1 minutes
     notifyutil -p
  3. You can close the second terminal now, just to prove that the command will run in its own shell.
  4. In one minute from the time you hit ^d, your computer should speak the word “Boom.” And there you go, at is working. Boom.

at can also take input from a file, which makes it easy to automate in a Rake task or other script: at -f /path/to/file 15:30 2012.01.29. You can quickly defer or batch queue execution of tasks with a quick call to at from another script. You can also pass the task on STDIN, so you can generate the tasks dynamically in the script and pass it to at when the time comes: echo str_variable|at now + 5 minutes. See man at for a rundown of all the date formats that at can understand.

You can also manage the jobs that are still in the queue waiting to fire. atq queries the database and shows you what jobs are scheduled, each with a number before it.

$ atq
28	Fri Jan 18 15:00:00 2013
29	Fri Jan 18 14:00:00 2013

You can then use at -r 28 to delete job number 28, or at -c 29 to view the contents of job 29.

So, how am I using this? I’m sure you can imagine the setup by now, but I’ll post some code from my Rakefile tomorrow (in a scheduled post) for anyone who’s interested. I’ll eventually publish the whole Rakefile, but it has a ways to go yet as I knock out the features I want one by one. I will get there.

I’ve also worked out a direct upload system that I can use from my iPhone and iPad with direct camera integration. I’m not sure how much I’ll use it, but I’ll show you how I did it soon in this series.

  1. Get lunchy, you’ll thank yourself later.