Two Faces of the Crontab: Scheduled Tasks as Scripts vs. Services
Every small service or application eventually needs to do something on a schedule. A backup job at 2 AM, a database cleanup every Sunday, a cache refresh every five minutes. For decades, the answer has been simple: the crontab. It’s the quintessential piece of boring technology, ticking away in the background of countless servers. But how we use it reveals a fundamental philosophical split in how we think about these automated tasks. On one side, there’s the approach of the script; on the other, the approach of the service.
The 'script' method is what most of us learn first. You write a shell script—`backup.sh`—that performs a series of steps. You make it executable, and you drop a line into the crontab pointing directly to it: `0 2 * * * /home/app/scripts/backup.sh`. The logic is all contained within that file. It's simple, self-contained, and feels straightforward. The job succeeds or fails, and hopefully, you’ve remembered to add some logging inside the script so you can check `/var/log/syslog` later to see what happened. The cron daemon is just a dumb trigger; all the intelligence resides in the script.
This approach works, but it has a subtle brittleness. The script owns its entire world. It might assume certain environment variables are set, or that it’s running from a specific directory. It might even call other scripts, creating a fragile chain of dependencies. When it fails, troubleshooting often involves manually running the script from the command line, trying to replicate the exact environment that cron provides (which is notoriously sparse). It’s a unit of work, but not necessarily a managed one.
Then there’s the 'service' approach. Here, you treat the scheduled task not as a script to be executed, but as a service to be managed. Instead of pointing cron at a script, you point it at a command that starts a well-defined process. For example, you might use a process supervisor like systemd to create a service unit for your backup job. The cron entry becomes as simple as `0 2 * * * systemctl start my-app-backup.service`. The service unit, in turn, defines the environment, the user, the working directory, and, crucially, where the stdout and stderr logs go.
The immediate benefit is structure. The service unit acts as a declaration of the job’s requirements and behavior. Logging is no longer an afterthought; it’s integrated into the system’s journal, making it easy to query with `journalctl -u my-app-backup.service`. You gain the ability to set resource limits, dependencies, and timeouts. If the job is complex, the 'main' function moves into a more robust application, and the service is just the clean, monitored entry point.
Neither approach is inherently right or wrong; they serve different masters. The script method is fast, uncomplicated, and perfect for one-off, fire-and-forget tasks. It embodies the Unix philosophy of a tool doing one thing well. The service method introduces a layer of ceremony, but in return, it offers resilience, observability, and a better fit for a world where even cron jobs are expected to be first-class citizens in our operational landscape. The humble crontab hasn’t changed, but our interpretation of what it triggers has. The choice between scripting a task and servicing it is a quiet but significant reflection of how we value long-term maintainability over immediate convenience.
Notes & further reading
A few pages I came back to while writing this:
- one area's overview
- The Trusty Kitchen Timer: A Lesson in Stateful Reliability
- a useful directory
- The Autumn of the Logfile
- a practical rundown
- The Seductive Lie of 'Everything as a Service'
- a place-by-place guide
- a local resource
- a nearby resource
- Washington, DC
- a regional guide
- a helpful reference
- a regional guide