Back in October, I company-ized myself into an LLC, and on the advice of my travel guru Gil Saunders, I got a credit card that will give me 30,000 airline mileage points if I spend $1,000 on it within the first 90 days. So then, hmmmmmmmmm, what can my business spend $1,000 on, to get me half a trip to Paris?
Well, shifting my Adobe Creative Cloud subscription to annual and putting it on the card took care of more than half the challenge. :/
And then I replaced my inkjet printer, which—like every other inkjet I’ve ever owned—had died of infrequent use.
As anyone who’s owned an inkjet knows, if you don’t use it often enough, the heads dry up. Then you end up having to run the head-cleaning utility all the time, which wastes a lot of ink, and you have to replace the ink cartridges all the time, which wastes a lot more. And since printer ink is one of the most expensive liquids on the planet, wasting it is baaaaad. Besides which, eventually those underused nozzles get permanently gummed up, and the machine stops working altogether.
My last printer, a Canon PIXMA MX870, had an okay run, limping along from March 2010 until mid-2016. But for the last year of its life, it was basically a monochrome device—with its one color not necessarily being black—and finally it started displaying an error message upon startup and refused to print anything at all.
So, Amperbang LLC replaced it with Wirecutter’s recommended (or, more accurately, least loathed) all-in-one color printer, which is the HP OfficeJet Pro 8720, and yesterday, as soon as I was done setting up this appliance, I started researching how to automate having it print a test page every few days, to keep the heads clean. It turns out this is not difficult to do, but in case you—or Future Me—want to do something similar, I’ll try to make the process even easier by summarizing what I’ve learned.
- You’re on a Mac. I did this on a late-2013 MacBook Pro running Sierra (10.12.2).
- You have a wifi-enabled or otherwise always connected printer, which either is always on or can be scheduled to power up (and down) at regular intervals.
1. Schedule the printer to turn on and off at certain times each day.
Totally optional. If you don’t want to bother with this or if your printer doesn’t have this feature, you can either leave it on all the time, or let the print job sit in your Mac’s queue until the next time you turn the printer on.
On the HP OfficeJet 8720, this vaguely documented process goes as follows:
a. On the printer control panel, swipe down from the top of the screen to open the Dashboard.
b. Scroll the menu bar all the way to the right, and tap the icon that looks like two leaves.
c. Once you find the Environmental Settings screen, tap “Schedule On/Off.”
d. Follow the prompts to set the days and times at which you want the printer to turn off and on.
Since I wanted to schedule my printer tests by day of the month rather than day of the week (which would be a lot easier), I set the printer to turn on and off every day. (And then I undid it, on which more later.)
At 7:00 a.m., I am still in bed, but the cats are probably awake, so the printer’s powering up and down might enrich their boring lives.
“Every everyday,” forsooth.
2. Set up your Mac to turn on and off at the same times as the printer.
Optional. Per step 4 below, this is required if using cron, optional if you’re using launchd. You’re not required to use cron, though, so overall, it’s optional.
You can set this up using the Energy Saver preference pane.
The timing options are not very granular, which is partly why I decided to ditch this method. If I wanted to run this task only once a week, these options would be fine. For a twice-weekly task, though, you end up having to set the schedule for every day.
3. Create an Automator app that prints a document.
I accomplished this using the instructions in this post by Clay Harmon:
Exercising Your Printer With Automator And Crontab.
I set up my app to print this exciting PDF—
—but a Google image search for inkjet printer test page will turn up lots of other options. You might want one that uses less ink, for instance.
Here are the Automator settings. I saved it to ~/Applications1 as PrintTestPage.app:
4. Schedule your app to run.
Required. But there are (at least) two ways to do this, and you can choose either one, depending on your desired schedule and how completely automated you want this chore to be.
Cron, as in c[h]ronological, is a venerable Unix utility that performs tasks on a schedule. It can perform those tasks only if your computer is awake; otherwise, nothing happens. But if your computer is always awake—e.g., if you’re running the test-page-printing app from a server—or if you don’t mind scheduling for it to wake and sleep at predetermined times, per step 2 above, it’s rat simple.
To create a cron job to run your test-page-printing app, follow Clay Harmon’s step-by-step instructions.
Here’s the command I set up:
(The top 9 lines are just to show you what each part of the command does; they’re cribbed from Calomel.org’s Cron and At post.)
This job will run my Automator app at 7:30 a.m. on the 1st, 5th, 10th, 15th, 20th, and 25th day of each month, as long as my laptop is awake at that hour.
But then I thought that maybe I don’t want the printer and laptop turning on every day from 7 to 8 a.m., when I’m only going to print a test page every fifth day. Maybe I just want the job to run at approximately the same time on every fifth day, at whatever time I actually wake my laptop—which is nearly always going to be after 8 a.m. So…
If you just want the task to happen eventually, whether your computer is awake at the prescribed time or not, a better solution—and the method Apple prefers over cron—is to use the launchd framework, which was introduced with Mac OS X Tiger.
If a launchd agent is scheduled to start while your Mac is asleep, it just waits until the next time the computer is awake. And the task will run only once, even if more than one scheduled occurrence passed by while the computer was off or sleeping—so you won’t end up with a stack of test pages printing all in a row, if your computer’s been shut down for a month. (During which time your inkjet printer has diiiiiied…)
Setting up a launchd agent is slightly more complex than creating a cron job, but since this method lets you skip step 2 above, it’s probably a wash, effortwise.
There are apps that can help you create the necessary .plist file, such as Lingon X ($10) and LaunchControl ($10). The makers of LaunchControl also host the site launchd.info, which explains how to create and use artisanal launchd property lists, interlarded with pitches for letting their software handle everything for you.
If like me you don’t anticipate creating another launchd agent any time soon, and you aren’t $10 worth of lazy, you can probably just dive into the XML yourself. Here’s the file I created:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>EnvironmentVariables</key> <dict> <key>PATH</key> <string>/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/bin/bash:/usr/local/sbin</string> </dict> <key>Label</key> <string>com.amperbang.printTestPage</string> <key>ProgramArguments</key> <array> <string>/Applications/PrintTestPage.app/Contents/MacOS/Application Stub</string> </array> <key>RunAtLoad</key> <false/> <key>StartCalendarInterval</key> <array> <dict> <key>Day</key> <integer>1</integer> <key>Hour</key> <integer>7</integer> <key>Minute</key> <integer>30</integer> </dict> <dict> <key>Day</key> <integer>5</integer> <key>Hour</key> <integer>7</integer> <key>Minute</key> <integer>30</integer> </dict> <dict> <key>Day</key> <integer>10</integer> <key>Hour</key> <integer>7</integer> <key>Minute</key> <integer>30</integer> </dict> <dict> <key>Day</key> <integer>15</integer> <key>Hour</key> <integer>7</integer> <key>Minute</key> <integer>30</integer> </dict> <dict> <key>Day</key> <integer>20</integer> <key>Hour</key> <integer>7</integer> <key>Minute</key> <integer>30</integer> </dict> <dict> <key>Day</key> <integer>25</integer> <key>Hour</key> <integer>7</integer> <key>Minute</key> <integer>30</integer> </dict> </array> </dict> </plist>
This agent hopes to run my Automator app at 7:30 a.m. on the 1st, 5th, 10th, 15th, 20th, and 25th day of each month. If it can’t run it at 7:30—which it probably never will, because both I and my laptop are dead to the world at that hour—it does so when the laptop wakes, instead. If the printer doesn’t happen to also be awake at that time, the print queue app will squawk at me, which will remind me to turn the printer on.
I placed the .plist file in ~/Library/LaunchAgents/, and I ran the following terminal command to get it loaded the first time:
launchctl load ~/Library/LaunchAgents/com.amperbang.printTestPage.plist
That’s a one-time command, because I had just created this agent. From now on, as I understand matters, the agent should get loaded automatically every time I log in.
If I needed to unload the agent—for example, if I made a change to it and needed to restart it, I’d run
launchctl unload ~/Library/LaunchAgents/com.amperbang.printTestPage.plist
To actually use the agent a single time, off the schedule, I can run the terminal command
launchctl start com.amperbang.printTestPage
When I did this, the test page printed. Woo!
So, after all that research, I’ve ended up using just the Automator app and the launchd agent. No automatic waking and sleeping of printer and computer. It’ll just run when it runs.
Tune in five years from now to find out whether the printer’s still firing on all cylinders…
- I hate when instructions assume you know things, so let me explicitly say that whenever you see a path beginning with
~/in Mac-related instructions, this means the address is relative to your user folder. So, if my Mac login name is amperbang, ~/Applications would be in Macintosh HD > Users > amperbang > Applications. [↩]