How to Troubleshoot When a Linux cron job runs manually but not scheduled

A Linux cron job runs manually but not scheduled when the command depends on conditions available in your interactive shell but missing from cron. The command itself may work, yet cron uses a different user, environment, working directory, shell, and timing context.

Linux cron job runs manually but not scheduled troubleshooting shown on a server administration workstation

This guide uses an evidence-first sequence. It covers schedule syntax, executable paths, permissions, environment variables, output handling, and service-specific execution context. Test one change at a time, and record the original configuration before editing it.

Confirm that cron is running

Start with the scheduler rather than the script. Traditional cron implementations usually run as a system service. Some Linux distributions instead use a service name such as crond. The correct name depends on the operating system.

Check the service state with the appropriate service-management command. For systemd systems, systemctl status cron or systemctl status crond may apply. Do not assume both names exist. The systemctl manual explains how to inspect service state and recent events.

Next, review the scheduler’s logs. Common locations include the system journal and a dedicated authentication or cron log. The exact file varies by distribution and logging configuration. Search for the expected user, command, or execution time.

journalctl -u cron --since "today"
journalctl -u crond --since "today"

Those commands are examples, not universal answers. If the service name differs, the first command will return no useful results. If logging is configured elsewhere, inspect that source instead.

Verify the schedule and time context

A valid cron entry has five time fields followed by a command:

minute hour day-of-month month day-of-week command

For example, 15 2 * * * means 02:15 every day according to the system’s local time. A small punctuation error can produce a valid schedule that runs at an unexpected time. A weekday value can also behave differently across implementations, especially when both zero and seven represent Sunday.

Check the server’s clock and time zone:

date
timedatectl

Confirm whether the host uses UTC, local time, or a configured cron-specific time zone. Cloud servers and containers often make UTC easy to overlook.

Use a harmless schedule test

Temporarily replace the real command with a timestamp test. A frequent schedule can show whether cron launches anything at all:

*/5 * * * * /usr/bin/date >> /tmp/cron-check.log 2>&1

Use a controlled location, and remove the test after diagnosis. If the file never changes, focus on the service, crontab location, permissions, or schedule. If it does change, the scheduler works and the original command needs closer examination.

When a Linux cron job runs manually but not scheduled, verify the expected run time with the host’s clock before changing the entry. A correct expression can still appear broken when the administrator watches a different time zone.

Compare the manual and cron environments

An interactive shell loads profile files and sets variables that cron may not provide. Important differences include PATH, HOME, SHELL, locale, proxy settings, application variables, and the current directory.

Capture the cron environment with a temporary entry:

* * * * * /usr/bin/env > /tmp/cron-environment.txt 2>&1

Compare that output with env from the shell of the same user. Avoid leaving sensitive variables in a world-readable temporary file. Delete the file after review, because environment output can contain credentials or tokens.

When a Linux cron job runs manually but not scheduled, compare the complete execution context before changing the script. A missing variable or different interpreter often explains the difference.

Do not rely on a relative command such as python, php, mysqldump, or node. Find the intended executable and use its absolute path:

command -v python3
command -v php
command -v mysqldump

You can define a limited path near the top of a user crontab:

SHELL=/bin/sh
PATH=/usr/local/bin:/usr/bin:/bin

Choose paths that match the host. A shell script may also depend on Bash features while cron invokes /bin/sh. In that case, specify the interpreter in the script’s first line, such as #!/bin/bash, and call the script deliberately.

Check users, files, and working directories

Manual testing often happens as an administrator. Cron may run as a service account with fewer permissions. A command that reads a private configuration file or writes to a home directory can therefore fail silently.

Identify which crontab contains the entry. A user crontab runs as that user. A system crontab, such as /etc/crontab, includes an extra user field. Confusing those formats can shift fields and change the command.

Test the command as the scheduled user, where appropriate:

sudo -u appuser /absolute/path/to/script.sh

Use a controlled test account and review the command before running it. The user needs execute permission on the script and traverse permission on every parent directory. It also needs access to input files, output directories, sockets, and credentials.

Cron does not promise the same working directory as your shell. Scripts should set their own directory or use absolute paths:

#!/bin/bash
set -u
cd /opt/example-job || exit 1
/usr/bin/python3 /opt/example-job/run.py

Add error handling that fits the script. Do not blindly add set -e to complex automation, because it can change behavior in ways that require testing. Check ownership and modes with ls -l, and inspect parent directories when access fails.

For a deeper review of service accounts, parent directories, ACLs, and security policies, see Linux service permission troubleshooting.

Capture standard output and errors

A successful manual run may display an error immediately. Cron has no visible terminal, so failures can disappear unless the job redirects output or sends mail.

Use temporary logging during diagnosis:

17 * * * * /opt/example-job/run.sh >> /var/log/example-job.log 2>&1

The scheduled user must be able to create or append to the log. A root-owned log may work for a system crontab but fail for an ordinary user. A safer design uses a directory with deliberate ownership and rotation, rather than allowing unlimited log growth.

Keep standard output and standard error together while investigating. Once the cause is known, send useful failures to a monitored location. Avoid logging passwords, API keys, full customer data, or other secrets.

Inspect application and service-specific context

Some programs behave differently outside their normal service environment. A web application may require a virtual environment, a specific configuration file, a database socket, or credentials supplied by a service manager.

For instance, a script may work from an activated Python virtual environment but fail when cron calls the system interpreter. Call the virtual environment’s executable directly. Similarly, a PHP task may depend on a specific PHP binary or command-line configuration.

Services managed by systemd may have environment files, working-directory settings, sandboxing, and dedicated users. Running a command from your shell does not reproduce those controls. If the task belongs inside a long-running service, consider whether a systemd timer or a service-managed job provides clearer ownership and logging.

Do not move a production task from cron to another scheduler without checking dependencies, overlap behavior, alerting, and rollback. First document the current schedule and confirm whether another process already runs the same task.

If the problem involves a service rather than a simple batch command, compare its unit configuration and logs. The guide to troubleshooting a Linux service that will not start covers a related evidence-gathering process.

Look for overlapping, locking, and timeout problems

A job may start on schedule but appear not to run because an earlier instance still holds a lock. Long database exports, backups, and synchronization tasks commonly overlap when their run time varies.

Check process listings and logs around the expected time. Look for lock files, “already running” messages, timeouts, and partial output. A lock must handle abnormal termination safely. A stale lock can block every later run, while no lock can allow competing processes to damage shared data.

Also check resource limits. Cron jobs may inherit limits that differ from your login session. Storage, open files, memory, network access, and execution time can all affect results. If a task calls a remote service, record the response and timeout rather than assuming the network is unavailable.

A safe diagnostic sequence

Use this order to reduce guesswork:

  1. Confirm the correct crontab and scheduled user.
  2. Verify the cron service is active and review its logs.
  3. Check the server clock, time zone, and next expected run.
  4. Run a harmless timestamp test at a frequent interval.
  5. Replace relative commands and files with absolute paths.
  6. Compare cron’s environment with the same user’s shell.
  7. Test permissions, parent directories, credentials, and working directory.
  8. Capture standard output and error in a controlled log.
  9. Check application-specific interpreters, configuration, locks, and timeouts.
  10. Remove temporary tests and document the verified fix.

Change one variable at a time. Otherwise, a successful run will not show which correction mattered. Keep a copy of the original crontab, but protect it if it contains sensitive command arguments.

This checklist helps separate a schedule problem from an execution-context problem. That distinction matters because changing the timing will not fix a command that lacks its required path, permissions, or configuration.

When to request technical help

A Linux cron job runs manually but not scheduled problem often needs only a path, user, or environment correction. Escalate when the task affects backups, billing, security monitoring, customer data, or production services. Tech Rescue Ops LLC can help compare execution contexts, review logs, and build safer monitoring without exposing credentials unnecessarily.

Scroll to Top