Scheduling log rotation — and why you probably shouldn't use cron

Almost always logrotate's job, already wired into cron.daily — here's when to actually write your own.

The problem

This is the use case where the honest answer is: you probably don't need to write a cron job at all. Every mainstream Linux distribution ships logrotate, already invoked via /etc/cron.daily/logrotate (or a systemd timer on newer systemd-based distros), and most packaged services (nginx, postgres, mysql) drop a working /etc/logrotate.d/ config for themselves on install.

Hand-rolling log rotation with a cron line that runs `mv access.log access.log.1` doesn't reopen the file handle the running process is writing to, so the application keeps writing into the now-renamed (and eventually deleted) file — you get a silently growing deleted inode instead of rotated logs, until a restart reclaims the disk space or a full disk takes the box down first.

Use logrotate, not a bare cron job.

logrotate handles the copytruncate/reopen dance correctly, understands `postrotate` hooks to signal a process (`nginx -s reopen`, `kill -USR1`), and already runs on a schedule via cron.daily or its systemd timer. Writing your own rotation script is reinventing something that ships in every base image. The one place a small cron script is justified is rotating output from your own long-running script that logrotate doesn't know about — and even then, prefer adding a drop-in to /etc/logrotate.d/ over a cron job.

Recommended schedule

@daily

logrotate itself is already invoked daily by the distro's cron.daily mechanism — you don't add this line, you add a config file to /etc/logrotate.d/ and let the existing daily run pick it up.

Example crontab entry

# norc: not applicable — this is a logrotate config, not a crontab entry
# /etc/logrotate.d/myapp — no crontab change needed on most distros
/var/log/myapp/*.log {
  daily
  rotate 14
  compress
  delaycompress
  missingok
  notifempty
  postrotate
    systemctl reload myapp >/dev/null 2>&1 || true
  endscript
}

Failure modes to watch for

  • Renaming a log file without a postrotate hook: the process keeps its old file descriptor open and writes vanish into a deleted, disk-consuming inode.
  • No `rotate N` limit: logs accumulate forever and eventually fill the disk.
  • Forgetting `missingok`/`notifempty` on a low-traffic log path: logrotate errors out instead of skipping cleanly.
  • Compressing the just-rotated file immediately instead of using `delaycompress`, which can race a process that briefly still has the old path open.

How norc helps

For the cases where you do run your own rotation or archival script via cron, norc gives you run history so a broken postrotate hook shows up as a failed run instead of a slowly filling disk.