Crontab Task Not Running? 90% of Ops Die in These 3 Environment Variable Traps
Mysterious "Disappearance" Scene
You wrote a perfect backup script backup.sh:
#!/bin/bash
# Backup database
mysqldump -u root -p123456 dbname > /backup/db.sql
echo "Backup done" >> /tmp/log.txt
Running ./backup.sh manually works perfectly.
So you confidently add it to Crontab:
0 3 * * * /home/user/backup.sh
The next morning, you check /backup/db.sql —— file does not exist.
Check /tmp/log.txt —— no logs either.
You start questioning life: Did the server restart at midnight? Is Crontab not running?
Stop guessing, 90% of the reasons are environment variable issues.
Trap 1: "Amnesia" of the PATH Variable
When you log into the terminal (Shell), the system automatically loads configuration files like /etc/profile and ~/.bashrc. Your PATH variable contains common paths like /usr/local/bin and /usr/bin.
However, the environment when Crontab executes is "barebones".
In the Crontab execution environment, PATH is usually only /usr/bin:/bin. If your mysqldump is installed at /usr/local/mysql/bin/mysqldump, the script will throw an error: command not found.
✅ Solution
Method 1: Use Absolute Paths (Recommended)
Write all commands in the script with absolute paths:
#!/bin/bash
/usr/local/mysql/bin/mysqldump -u root ...
Method 2: Manually Define PATH
Redefine PATH at the beginning of the script:
#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Your business logic
Trap 2: "Getting Lost" with Relative Paths
#!/bin/bash
# Wrong demonstration
cat ./config.ini
When executing in Crontab, the Current Working Directory (CWD) is usually the user's home directory (~), not the directory where the script is located. If you use ./config.ini in your script, it will look in the home directory, not in the same directory as the script.
✅ Solution
cd to the script's directory first:
#!/bin/bash
cd "$(dirname "$0")" || exit
# Now you can use relative paths
cat ./config.ini
Trap 3: Special Meaning of the % Symbol
You want to write a single line command in Crontab with a timestamp:
# Wrong demonstration
* * * * * echo "Run at $(date +%Y-%m-%d)" >> /tmp/cron.log
You'll find that the command doesn't execute at all, or throws an error.
The reason is: In Crontab files, % is treated as a newline character. Everything after the first % is sent to the command as standard input.
✅ Solution
You must escape %:
# Correct demonstration
* * * * * echo "Run at $(date +\%Y-\%m-\%d)" >> /tmp/cron.log
Ultimate Debugging Method
If you've checked all of the above and it still doesn't work, add this to your Crontab entry:
* * * * * /path/to/script.sh > /tmp/cron_debug.log 2>&1
This will redirect both standard output (stdout) and standard error (stderr) to a log file. Open the log, and the error message will usually be clear at a glance.
Ops rely not only on experience but also on tools. Having trouble with time calculations? Try our Timestamp Converter, which supports second/millisecond conversion and time zone handling.