Cron job works manually but fails with command not found because cron uses a minimal PATH

2026-11-14 · 3 min read

Cron job works manually but fails with command not found because cron uses a minimal PATH

A nightly backup fails at 02:15 with backup.sh: not found or aws: command not found, while the same command runs when you paste it into an SSH session. The cost is quiet: a missing backup, a failed report, or an alert that fires hours later. The usual cause is not a broken script. The cron PATH environment is not your interactive shell’s PATH.

Cron starts jobs with a minimal environment. On many systems the default PATH is something like /usr/bin:/bin, and cron does not read your shell startup files such as .bashrc or .profile. [link needed] So a script that calls aws, node, python3, or a binary in /usr/local/bin can work in your terminal and fail under cron.

First, confirm the cron PATH environment

Do not guess. Capture what cron actually sees. Add a temporary job with an absolute path to env:


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

Wait for the minute to pass, then compare it with your login shell:


grep '^PATH=' /tmp/cron-env.txt
printf '%s\n' "$PATH"

You will normally see a shorter PATH in the cron output. Check whether the missing command is in a directory that exists in your shell but not in cron’s PATH. Also check the script’s shebang: #!/usr/bin/env bash uses PATH to find bash, so an absolute #!/bin/bash is less fragile. [link needed]

Fix the cron PATH environment explicitly

Use a narrow, explicit PATH for the job. Do not copy your whole interactive PATH; include only directories the job needs.

1. Find the binary’s real location in your login shell: command -v aws or command -v node.

2. Open the user crontab with crontab -e.

3. Add a PATH assignment above the job, using absolute directories:

```cron

PATH=/usr/local/bin:/usr/bin:/bin

```

4. Run the job with absolute paths anyway:

```cron

*/15 * * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

```

5. Save, then trigger the job manually or wait for the next schedule. Check the log and cron-env.txt again.

The PATH line in a crontab applies to later entries in that crontab. Confirm the syntax against man 5 crontab on your system. [link needed] Keep the redirects: cron often mails job output only if mail is configured, so a log file is easier to inspect. [link needed]

Set PATH inside the script as a second layer

If the script may also run from systemd, CI, or another scheduler, set PATH inside the script itself:


#!/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
export PATH

Then call commands normally, or keep using absolute paths for critical binaries. This makes the cron PATH environment irrelevant to the script’s internals. It also prevents a crontab edit from silently fixing one job while leaving another broken.

When NOT to change the cron PATH environment

Do not widen PATH blindly if the script depends on a version manager such as nvm, pyenv, or rbenv. Those tools often need shell initialization, not just a directory on PATH. In that case, source the version-manager setup in the script or use the absolute path to the correct interpreter.

Do not add user-writable directories to a root crontab unless you intend root to execute from them. And do not change the global /etc/crontab if only one user job is affected; a per-user crontab or in-script PATH is narrower.

Checklist