Debugging Crontab: Why Only the First Wget/Lynx Command Executes?


3 views

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