How to Fix Cron Job Not Running in Ubuntu

When automated scheduled tasks configured in crontab fail to execute on Ubuntu—leaving database backup scripts unexecuted, log rotation jobs stalled, or routine maintenance commands ignored—the issue rarely stems from total cron daemon failure. Instead, scheduled cron jobs typically fail silently due to truncated PATH environment variables (causing commands to fail because system binaries cannot be located), relative file path assumptions, missing executable file permissions, crontab formatting flaws (such as missing trailing newlines or unescaped percent signs), or user account permission restrictions. Because cron executes tasks in a strictly stripped, non-interactive shell environment, resolving execution stalls requires systematic auditing of environment definitions, log streams, and script privileges.

Understanding Cron’s Execution Environment Limitations

When a user executes a script manually in the Ubuntu terminal, the interactive shell automatically imports extensive environment variables defined in ~/.bashrc, ~/.profile, and /etc/environment. However, the cron daemon (cron.service) executes jobs in a minimal subshell where the environment PATH is typically restricted to /usr/bin:/bin. If a bash or python script calls binaries located in /usr/local/bin, /snap/bin, or custom user directories without supplying their full absolute paths, cron crashes silently at that line without outputting terminal warnings.

Common technical reasons cron jobs fail to run include:

  • Stripped Environment Variables (PATH): Commands failing because cron’s minimal subshell cannot find external dependencies or interpreters. For repository errors, see our guide on fixing GPG error NO_PUBKEY in Ubuntu.
  • Missing Trailing Newline in Crontab: The Vixie Cron parser ignoring the final scheduled line if the crontab file does not conclude with a clean newline character. For package status faults, check our guide on fixing dpkg error parsing file status in Ubuntu.
  • Missing Executable Permissions (chmod +x): Shell scripts lacking executable bit permissions for the executing user account.
  • Unescaped Percent Signs (%): Cron treating literal percent signs in commands (such as date formatting strings) as newline delimiters unless escaped with backslashes.
  • Cron Daemon Stalled: The underlying cron.service systemd daemon being disabled or entering an inactive state.
Issue Category Broken Crontab Example Corrected Functional Crontab
Relative Path Assumption * * * * * python script.py * * * * * /usr/bin/python3 /home/user/script.py
Unescaped Date Formatting 0 0 * * * tar -czf bk-$(date +%Y%m%d).tar.gz /data 0 0 * * * tar -czf bk-$(date +\%Y\%m\%d).tar.gz /data
Missing Environment PATH Relies on default cron PATH Add PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin at top
Missing Output Logging 0 * * * * /bin/bash /opt/job.sh 0 * * * * /bin/bash /opt/job.sh >> /var/log/job.log 2>&1

Method 1: Verify the Cron Daemon Service Status

Before debugging script logic, verify that Ubuntu’s background cron daemon is actively running and configured to launch on system boot.

  1. Open your terminal by pressing Ctrl + Alt + T.
  2. Check the status of the cron systemd unit:
    systemctl status cron.service
  3. Examine the output. It should indicate Active: active (running) in green text.
  4. If the service is stopped or inactive, start and enable it immediately:
    sudo systemctl enable --now cron.service

Method 2: Use Absolute Paths for All Binaries and Scripts

Because cron does not inherit your normal shell environment, every program, script, and input/output target must be referenced using its full absolute file system path.

  1. Find the exact absolute path to your language interpreter or binary using the which command:
    which python3 (e.g. /usr/bin/python3)
    which node (e.g. /usr/bin/node)
    which bash (e.g. /usr/bin/bash)
  2. Open your user crontab for editing:
    crontab -e
  3. Ensure your scheduled line references the exact binary and script path:
    0 2 * * * /usr/bin/python3 /home/ubuntu/scripts/backup.py
  4. Alternatively, define the global PATH explicitly at the very top of your crontab file:
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Method 3: Redirect Output and Errors to a Log File for Debugging

By default, cron attempts to email script output to the local user’s mailbox (via postfix or sendmail). If no local mail transport agent is installed, error messages are discarded. Redirecting standard output and errors to a log file captures failures instantly.

  1. In crontab -e, append >> /home/[user]/cron.log 2>&1 to the end of your cron instruction:
    */10 * * * * /home/ubuntu/script.sh >> /home/ubuntu/cron.log 2>&1
  2. Save and exit the crontab editor.
  3. Wait for the scheduled interval to trigger, then inspect the log file:
    cat /home/ubuntu/cron.log
  4. The log file will reveal the exact error (e.g., “command not found”, “permission denied”, or missing python libraries).

Method 4: Ensure Script Executable Permissions and Trailing Newline

Files that cannot be executed by the target user account or crontabs lacking trailing newlines prevent successful cron execution.

  1. Grant explicit executable permissions to your target shell or python script:
    chmod +x /home/ubuntu/scripts/backup.sh
  2. Open crontab:
    crontab -e
  3. Navigate to the very last line of the crontab file.
  4. Press Enter to create a blank empty line at the end of the file. The Vixie Cron parser requires this trailing newline character to parse the final scheduled job.
  5. Save and close the editor.

Method 5: Check System Cron Logs in journalctl and syslog

Ubuntu records every cron task invocation in system journal logs, allowing you to confirm whether cron even attempted to launch your task.

  1. Inspect recent cron executions using journalctl:
    sudo journalctl -u cron.service --since "1 hour ago"
  2. On older Ubuntu versions or systems running rsyslog, filter /var/log/syslog:
    sudo grep -i CRON /var/log/syslog | tail -n 25
  3. Review the timestamps and commands. If you see (CRON) info (No MTA installed, discarding output), ensure you have implemented log redirection as detailed in Method 3.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.