I recently encountered a puzzling situation where my crontab would only execute the first wget or lynx command while ignoring subsequent ones. Here's a deep dive into what I discovered and how to fix it.
My crontab configuration looked like this:
*/15 * * * * ~root/apache.sh > /var/log/checkapache.log
10 0 * * * wget -O /path/to/file-sv.sql "http://mydomain.com/path/?lang=sv"
11 0 * * * wget -O /path/to/file-en.sql "http://mydomain.com/path/?lang=en"
The strange behavior exhibited these characteristics:
- Only the first wget command executed successfully
- Swapping line positions made the previously ignored command work
- The apache.sh script always ran correctly regardless of position
- Substituting wget with lynx showed the same behavior
After extensive testing, I identified several potential culprits:
Environment Variables
Cron jobs run with a minimal environment. Unlike your shell session, they don't inherit your PATH or other environment variables. This can cause commands to fail silently.
Test solution:
10 0 * * * /usr/bin/wget -O /path/to/file-sv.sql "http://mydomain.com/path/?lang=sv"
11 0 * * * /usr/bin/wget -O /path/to/file-en.sql "http://mydomain.com/path/?lang=en"
Output Handling
Cron sends output via email by default. If there's no mail system configured, this can cause issues.
Better approach:
10 0 * * * /usr/bin/wget -O /path/to/file-sv.sql "http://mydomain.com/path/?lang=sv" >/dev/null 2>&1
11 0 * * * /usr/bin/wget -O /path/to/file-en.sql "http://mydomain.com/path/?lang=en" >/dev/null 2>&1
Here's the working configuration I ultimately implemented:
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
*/15 * * * * ~root/apache.sh > /var/log/checkapache.log 2>&1
10 0 * * * /usr/bin/wget --quiet -O /path/to/file-sv.sql "http://mydomain.com/path/?lang=sv" >/dev/null 2>&1
11 0 * * * /usr/bin/wget --quiet -O /path/to/file-en.sql "http://mydomain.com/path/?lang=en" >/dev/null 2>&1
- Check cron logs:
grep CRON /var/log/syslog
- Test commands directly in shell:
sudo -u root /usr/bin/wget -O /path/to/test.sql "http://mydomain.com/path/?lang=en"
- Verify file permissions on output directories
- Consider using absolute paths for all files and commands
For more complex scenarios, consider these alternatives:
# Using a wrapper script
10 0 * * * /root/fetch_data.sh sv
11 0 * * * /root/fetch_data.sh en
Where fetch_data.sh contains:
#!/bin/bash
LANG=$1
wget -O "/path/to/file-${LANG}.sql" "http://mydomain.com/path/?lang=${LANG}"
I recently encountered a puzzling scenario with my crontab setup where only the first wget
command would execute successfully, despite having multiple similar commands scheduled. Here's the technical deep dive into what I discovered and how to resolve it.
Here's the crontab configuration that exhibited the issue:
*/15 * * * * ~root/apache.sh > /var/log/checkapache.log
10 0 * * * wget -O /path/to/file-sv.sql "http://mydomain.com/path/?lang=sv"
11 0 * * * wget -O /path/to/file-en.sql "http://mydomain.com/path/?lang=en"
In this setup, only the Swedish language file (file-sv.sql
) would be created, while the English version would mysteriously fail to generate.
Before diving into solutions, let's eliminate some common issues:
1. Verify cron service is running: systemctl status cron
2. Check user permissions: crontab -l -u yourusername
3. Examine logs: grep CRON /var/log/syslog
4. Test commands manually outside cron
The fundamental issue lies in how cron executes commands with a minimal environment. Unlike your interactive shell, cron doesn't have the same PATH or other environment variables.
Solution: Use absolute paths or set the environment explicitly:
10 0 * * * /usr/bin/wget -O /path/to/file-sv.sql "http://mydomain.com/path/?lang=sv"
11 0 * * * /usr/bin/wget -O /path/to/file-en.sql "http://mydomain.com/path/?lang=en"
For complex cron jobs, it's better to create a shell script:
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
URL="http://mydomain.com/path/"
DEST="/path/to"
wget -O "${DEST}/file-sv.sql" "${URL}?lang=sv"
wget -O "${DEST}/file-en.sql" "${URL}?lang=en"
Then call this script from cron:
10 0 * * * /path/to/your/script.sh > /var/log/yourscript.log 2>&1
If the issue persists, consider these alternatives:
1. Using curl instead:
10 0 * * * /usr/bin/curl -o /path/to/file-sv.sql "http://mydomain.com/path/?lang=sv"
11 0 * * * /usr/bin/curl -o /path/to/file-en.sql "http://mydomain.com/path/?lang=en"
2. Adding error handling:
10 0 * * * /usr/bin/wget -O /path/to/file-sv.sql "http://mydomain.com/path/?lang=sv" || echo "Failed sv" >> /var/log/cron-errors.log
11 0 * * * /usr/bin/wget -O /path/to/file-en.sql "http://mydomain.com/path/?lang=en" || echo "Failed en" >> /var/log/cron-errors.log
When troubleshooting, these commands can help:
# View cron environment variables
* * * * * /usr/bin/env > /tmp/cronenv
# Test with simpler commands first
* * * * * touch /tmp/crontest
# Capture output and errors
* * * * * /path/to/command > /tmp/output.log 2>&1