Cron Job on Mac: Fixing Permissions, Sleep & Silent Failures
September 1, 2026


Cron on Mac Isn't the Same as Cron on Linux
The syntax for a cron job on Mac is identical to Linux — five time fields, a command, done. Open a terminal, run crontab -e, and add a line like:
*/15 * * * * /usr/bin/curl -s https://example.com/ping
That schedules a request every 15 minutes, exactly as it would on any Linux server. For a refresher on full crontab syntax, this breakdown of cron syntax, risks, and monitoring covers it in detail.
Where things diverge is everything around that syntax. macOS wraps the filesystem in a permissions layer called TCC (Transparency, Consent, and Control) that Linux doesn't have, and it aggressively suspends background processes when the machine sleeps. A crontab on Mac can be scheduled perfectly and still never touch the file it's supposed to read, or never run at all, with no visible error unless you know exactly where to look. Developers moving from Linux servers to a MacBook for local scripts hit this constantly — the job "works," but nothing happens.
Fixing "Operation Not Permitted": Full Disk Access for Cron
The most common failure: your script runs fine when executed directly in Terminal, but fails silently — or throws Operation not permitted — when cron runs it. This is TCC blocking cron from reading or writing files it doesn't have explicit consent to touch, even though Unix file permissions (chmod, ownership, etc.) are correct. Unix permissions and TCC are two separate gatekeepers, and macOS checks both.
The fix is granting Full Disk Access explicitly:
- Open System Settings > Privacy & Security > Full Disk Access.
- Click the + button and add
/usr/sbin/cron. - Also add
/usr/bin/crontab. - If your job runs through a specific binary — Terminal.app, iTerm, Python, Node, or a shell interpreter — add that binary too, since it's the process actually opening the files.
This is the single most common cause of "crontab permission denied" on a Mac, and it's easy to miss because the error rarely says "permission" outright — you'll more often just see the job fail with no output, or an Operation not permitted mac-style message buried in a log you have to redirect to manually. Grant access, restart cron (or reboot), and re-test.
Other Mac-Specific Reasons Cron Jobs Silently Fail
Full Disk Access solves one class of problem. Several more are specific to macOS and catch developers who assume a cron job on Mac not running means a syntax mistake:
- Stripped PATH. Cron runs with a minimal environment, not your shell's. If your job calls a Homebrew-installed binary (
node,python3,aws, etc.), cron won't find it unless you use the full path (e.g.,/opt/homebrew/bin/node) or explicitly setPATHat the top of the crontab. This is one of the most common mac crontab pitfalls, and it silently exits with "command not found" written only to a log you probably aren't checking. - Sleep skips the run entirely. Unlike a server that's always on, a MacBook that's asleep doesn't queue up missed cron jobs. There's no anacron-style catch-up on macOS — if the scheduled minute passes while the lid is closed, that run simply never happens.
- Protected folders stay blocked. Even after granting Full Disk Access, directories like
~/Desktop,~/Documents, or~/.Trashare gated separately under TCC for certain apps. If your script writes there, you may need to add the specific interpreter binary to Full Disk Access as well, not justcronitself.
Each of these produces the same symptom: the job was scheduled, but nothing verifiable happened, and there's no crash to alert you.
launchd vs Cron: When to Switch on macOS
Apple has treated cron as a legacy tool for years, favoring launchd — the system that actually manages background processes on macOS, including waking the machine for scheduled tasks. The cron vs launchd mac decision doesn't need to be complicated:
- Stick with cron for simple, always-on scripts on a machine that rarely sleeps — a Mac mini acting as a home server, for example, or quick personal scripts where occasional missed runs during sleep are tolerable.
- Switch to launchd if you need the job to survive sleep/wake cycles reliably, trigger on system events (login, file change, network state) rather than just a clock time, or run with more predictable timing on a laptop that closes and reopens throughout the day.
launchd's .plist-based configuration is more verbose than a crontab line, but it integrates with macOS's power management instead of fighting it — which matters a lot for a laptop, and not at all for an always-on Linux box.
Permissions Fix the Errors — They Don't Prove the Job Ran
Here's the part that trips up even developers who've done everything above correctly: Full Disk Access fixes permission errors. It does nothing for a job that got skipped because the Mac was asleep, a script that ran but exited with a silent internal error, or a job that hung indefinitely and never completed. None of those show up as a TCC prompt or a permissions log — they just look like nothing happened, because nothing did.
Local logs make this worse on a laptop. A log file sitting on a machine that sleeps, closes, and disconnects from Wi-Fi isn't something you can rely on to alert you — you have to remember to open it. For background on why silent cron failures are so hard to catch by log-watching alone, it's worth understanding that this isn't a Mac-only problem — Mac just makes it worse by adding sleep on top of it.
The reliable fix is external check-in monitoring: your cron job pings a monitoring endpoint (a heartbeat or API call) at the start and end of each run. If the ping doesn't arrive on schedule — because the Mac was asleep, the script crashed, or it hung — you get alerted from outside the machine, not by hoping you notice a missing log entry. This explainer on pull, push, and heartbeat health-check systems walks through exactly how that mechanism works.
Full Disk Access gets your Mac cron job past macOS's permission wall. It doesn't tell you the job actually succeeded, and it can't, because success and sleep are outside cron's own visibility. The only way to know for certain that a Mac cron job ran and finished is a heartbeat alert sent to something outside the laptop itself. Cronevra is built for exactly that — cron jobs that never fail silently, on Mac or anywhere else. Check the pricing page if you're ready to stop guessing whether your scheduled jobs actually ran.
Frequently Asked Questions
Why does my cron job work when I run it manually but not from crontab on Mac?
This almost always comes down to two things: a stripped PATH (cron can't find Homebrew-installed binaries without a full path) or TCC blocking file access that your interactive shell already has permission for. Add full binary paths to your script and grant Full Disk Access to cron and crontab in System Settings.
Do I need to give Terminal full disk access for cron to work on macOS?
Yes, in many cases — cron itself needs Full Disk Access, but so does the actual process executing your script, often Terminal, iTerm, or the interpreter binary (Python, Node, etc.). If your script touches protected folders like Desktop or Documents, that executing binary needs access too, not just cron.
Should I use launchd instead of cron on a Mac?
Use launchd if you need the job to survive sleep/wake cycles or trigger on system events rather than a fixed time; it's Apple's preferred background-task system and integrates with power management. Stick with cron for simple, low-stakes scripts on a machine that stays powered on most of the time.
Why did my Mac cron job stop running after a macOS update?
macOS updates frequently reset TCC permissions, meaning Full Disk Access grants for cron, crontab, or your script's interpreter can silently disappear. Check System Settings > Privacy & Security > Full Disk Access after every major update and re-add any missing binaries.
Does a cron job run on a MacBook if the lid is closed or it's asleep?
No — if the scheduled time passes while the Mac is asleep, that run is skipped entirely, with no catch-up mechanism like anacron. This is one of the biggest differences between running cron on a Mac laptop versus an always-on Linux server.
How do I check if a cron job actually ran on my Mac?
Redirecting output to a log file only helps if you remember to check it, and it won't catch runs skipped during sleep. The reliable method is external check-in monitoring — your script pings a monitoring service at the start and end of each run, so you get alerted the moment an expected ping doesn't arrive.