Search code examples
linuxbashcron

Why isn't my crontab executing bash properly?


I am a total noob to Linux and am using Raspbian on a Raspberry Pi 4. I created a bash script which updates an HTML file and runs some python programs to tweet a random article from Wikipedia's List of Unusual Articles. This is the bash script I'm running:

#! /bin/bash
wget -q en.wikipedia.org/wiki/Wikipedia:Unusual_articles -O Wikipedia:Unusual_articles
python3 parser.py
python3 tweeter.py

In my crontab, I have this command to run the bash script every day at 12 PM:

0 12 * * * /home/pi/Code/Python/TwitterBots/UArticleBot/TweetRandom.sh

When I run the script manually with bash it works just fine, but I don't understand why my cron isn't working. Even when I set [email protected] it doesn't e-mail me anything.

EDIT: I ran echo $PATH and added what was outputted to my cron. Here's what the cron looks like now (I'm having it run every 2 minutes for debugging purposes):

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
[email protected]
*/2 * * * * bash /home/pi/Code/Python/TwitterBots/UArticleBot/TweetRandom.sh

And this is what the bash script looks like now:

#! /bin/bash
wget -q en.wikipedia.org/wiki/Wikipedia:Unusual_articles -O Wikipedia:Unusual_articles
python3 parser.py
python3 tweeter.py

Solution

  • cron jobs run with the user's home directory as their working directory. That means that all file references that don't specify an explicit path (or use a lookup via something like $PATH) will be in your home directory.

    Specifying the path to the script does not change this at all. I suspect when you test the script interactively, you do something like this:

    cd /home/pi/Code/Python/TwitterBots/UArticleBot
    ./TweetRandom.sh
    

    Try doing this instead, and see what it does:

    cd ~
    /home/pi/Code/Python/TwitterBots/UArticleBot/TweetRandom.sh
    

    My guess is it'll do the same thing it does when run from a cron job: create a Wikipedia:Unusual_articles file in your home directory, then get errors because it can't find either the parser.py or tweeter.py script.

    One way to solve this is to use explicit paths for everything (which'll probably involve modifying the python scripts as well, because they probably assume the Wikipedia file is in the current directory).

    Another option is to have your script cd to its own directory before doing anything else. This can be a little tricky in general (see BashFAQ #28), but this should work for your case:

    #!/bin/bash
    cd "$(dirname "$BASH_SOURCE")" || {
        echo "Error cd'ing to script directory" >&2
        exit 1
    }
    ... rest of script here
    

    BTW, when troubleshooting cron jobs, it's incredibly useful to capture the errors and other info they print as they run. cron sort of tries to take care of this for you, but it doesn't always work well. You can direct output to a log file by adding a redirect like this to the end of the cron entry:

    0 12 * * * /home/pi/Code/Python/TwitterBots/UArticleBot/TweetRandom.sh >>/tmp/tweetjob.log 2>&1