Debugging

crontab: command not found.

This error means the cron package isn't installed. Most desktop Linuxes include it by default, but minimal server images, Docker base images, and Alpine commonly don't. Install it via your package manager.

Install on Ubuntu / Debian

sudo apt update
sudo apt install -y cron
sudo systemctl enable --now cron

Install on RHEL / CentOS / Fedora / Amazon Linux

sudo yum install -y cronie       # CentOS 7, Amazon Linux
sudo dnf install -y cronie       # CentOS 8+, Fedora
sudo systemctl enable --now crond

Note the service is crond on RHEL-family distros, but cron on Debian-family.

Install on Alpine Linux

apk add --no-cache busybox-suid    # provides crontab
# Or for full feature set:
apk add --no-cache dcron
rc-update add dcron default
rc-service dcron start

Alpine commonly appears in Docker base images. busybox-suid is the lightweight option.

Install on macOS

cron is preinstalled on macOS, but Apple discourages its use in favor of launchd. If crontab really is missing or you get permission errors, you may need to grant Terminal full disk access in System Preferences.

Better long-term: switch to launchd. Create a plist:

~/Library/LaunchAgents/com.example.myjob.plist
<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.example.myjob</string>
    <key>ProgramArguments</key>
    <array>
      <string>/path/to/script.sh</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
      <key>Hour</key>
      <integer>9</integer>
      <key>Minute</key>
      <integer>0</integer>
    </dict>
  </dict>
</plist>

Load with launchctl load ~/Library/LaunchAgents/com.example.myjob.plist.

Install in a Docker container

Most slim base images strip cron. To add it:

# Dockerfile for Debian/Ubuntu base
RUN apt-get update && apt-get install -y cron && rm -rf /var/lib/apt/lists/*

# Then in your entrypoint or CMD, start cron:
CMD ["cron", "-f"]

The -f keeps cron in the foreground so the container doesn't immediately exit.

For Kubernetes — don't install cron, use CronJob

If you're trying to install cron inside a Kubernetes pod, you almost certainly want a Kubernetes CronJob instead — it's a first-class resource type:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: my-job
spec:
  schedule: "0 9 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: app
              image: myapp:latest

See our Kubernetes CronJob tool.

Verifying the install worked

which crontab           # Should print a path
crontab -l              # Should list your jobs (or "no crontab")
systemctl status cron   # Should be active (or "crond" on RHEL)
Related

Continue reading.