Running a cron job manually means executing the exact command string from your crontab entry in your terminal, replicating the minimal environment variables and working directory that cron uses. This lets you debug failures immediately without waiting for the next scheduled interval.
Why Manual Execution Matters
Scheduled jobs often fail silently because the environment differs from your interactive shell. When cron runs a task, it typically starts with a minimal environment, lacking the custom paths or variables you might rely on during development. By running the command manually, you can catch issues like missing dependencies or incorrect file paths before they cause a production outage.
The goal is to simulate the scheduled environment as closely as possible. If you run my_script.sh in your terminal and it works, but fails at 2 AM, the discrepancy is usually environmental. Manual execution allows you to bridge this gap by explicitly setting the conditions under which the job will run.
The Basic Command Structure
The most common mistake is assuming your interactive shell environment matches the cron environment. To run a job exactly as cron sees it, you should invoke the command with the same working directory and shell options. Most cron implementations run commands using /bin/sh by default, not your preferred bash or zsh configuration.
You can inspect your current crontab entries to see the exact commands defined. Use the -l flag to list them.
crontab -l
Suppose your entry looks like this:
0 2 * * * /home/dev/backup.sh
To run this manually, do not just type /home/dev/backup.sh. Instead, replicate the likely cron environment. Cron often sets HOME and PATH differently. A robust manual invocation looks like this:
env -i HOME=/home/dev PATH=/usr/local/bin:/usr/bin:/bin /bin/sh -c "/home/dev/backup.sh"
This command clears your current environment (env -i), sets the essential variables cron typically provides, and runs the script via /bin/sh. This ensures that if the script relies on specific paths or home directories, it behaves identically to the scheduled run.
Handling Environment Variables
Environment variables are the primary source of discrepancy between manual and scheduled execution. If your script relies on variables defined in .bashrc or .profile, they may not be available when cron runs. Cron reads /etc/crontab and /etc/cron.d/ but often ignores user-specific shell initialization files depending on the system configuration.
To test this, compare your interactive environment with a minimal cron-like environment. First, check your current variables:
env
Then, run your command with a stripped environment to see if it fails. If it does, you need to explicitly define missing variables in the command line or within the script itself.
Consider a script that backs up a database. It might rely on PGPASSWORD. If cron does not inherit this from your shell profile, the backup fails. In your crontab, you can define variables directly above the command entry, but when testing manually, you must pass them explicitly.
PGPASSWORD=secret123 /usr/bin/pg_dump mydb > backup.sql
If the script works with explicit variables but fails without them, your cron entry needs those variables defined at the top of the crontab file. For example:
PGPASSWORD=secret123
0 2 * * * /usr/bin/pg_dump mydb > backup.sql
This ensures the variable is available to the command regardless of shell initialization files.
Verifying Output and Logs
Cron jobs often redirect output to /dev/null or log files. When testing manually, you want to see immediate feedback. Redirect standard output and error streams to the terminal to diagnose issues in real time.
If your scheduled entry redirects output to a log file, temporarily remove that redirection for your manual test. This allows you to see error messages directly.
Suppose your scheduled entry is:
0 2 * * * /home/dev/backup.sh >> /var/log/backup.log 2>&1
For manual testing, run the command without redirection first to catch immediate errors:
env -i HOME=/home/dev PATH=/usr/local/bin:/usr/bin:/bin /bin/sh -c "/home/dev/backup.sh"
If this succeeds, verify that the log redirection works as expected by adding it back. Check the log file immediately after execution to ensure the content is written correctly.
cat /var/log/backup.log
This two-step process—first running without redirection to catch errors, then verifying log output—ensures both the script logic and the logging mechanism function correctly. It prevents scenarios where the script succeeds but logs nothing, or logs errors that are invisible due to incorrect redirection syntax.
Using CronExplain for Schedule Validation
Before running the command manually, confirm that the schedule itself matches your intent. A common issue is misunderstanding how cron interprets day-of-week or month fields. For instance, 0 2 * * * runs every day at 2 AM, but 0 2 * * 1 runs only on Mondays. Misinterpreting these fields can lead to unexpected behavior when you think the job should have run but didn’t.
CronExplain helps clarify these expressions. Paste your cron expression into the tool to get a plain-English explanation and see the next ten firing times. This confirms whether the schedule aligns with your testing window. For example, if you expect a job to run every weekday but see weekend dates in the preview, you know to adjust the day-of-week field before testing the command logic.
This step prevents debugging the script when the issue is actually the schedule definition. By validating the timing logic first, you ensure that when you manually execute the command, you are testing the correct scenario for the intended frequency.