Search code examples
bashshellcurlconky

Conky runs the same curl request multiple times per interval


The API responds with an XML file containing everything. I want some of the data in that XML to appear in parts of my conky

I have a bash script to fetch and parse the data. It looks like

#!/bin/sh
if [ -z $1 ]; then
        echo "missing arguments"
        exit 0;
fi
curl -s http://example.com/api.php | xmllint --xpath "//${1}/text()" -

and in .conkyrc I have

${color slate grey}Number of cats: ${color }
${execi 3600 myscript.sh cats}

${color slate grey}Color of the day: ${color }
${execi 3600 myscript.sh color}

${color slate grey}Some other stuff: ${color }
${execi 3600 myscript.sh stuff}

This works fine, but I'm making 3 requests to the API every interval even though all the data I need is passed the first time.

The obvious solution is change the bash script to save the API response to a temp file with a timestamp on it. Wherever the script is run, first check the temp file's timestamp to see if it's out of date (or doesn't exist). If so, delete it and make a new curl request. If not, swap the curl statement with a

cat tempfile.xml | xmllint

But I don't like leave temp files all over the place or worrying about potential race conditions. Is there a way to return all the data I need from my script and give it to conky to store as conky variables and then print them in the right location? Or more broadly, how should I go about improving this?


Solution

  • You can modify your script to use a cache:

    #!/bin/sh
    
    CACHE_FILE=/var/cache/api.data
    
    check_missing_arg() {
        if [ -z "$1" ]; then
            echo "missing arguments"
            exit 0
        fi
    }
    
    if [ "$1" = --use-cache ] && [ -f "$CACHE_FILE" ]; then
        shift
        check_missing_arg "$@"
        xmllint --xpath "//${1}/text()" "$CACHE_FILE"
    elif [ "$1" = --store-cache ]; then
        shift
        check_missing_arg "$@"
        curl -s http://example.com/api.php > "$CACHE_FILE"
        xmllint --xpath "//${1}/text()" "$CACHE_FILE"
    else
        check_missing_arg "$@"
        curl -s http://example.com/api.php | xmllint --xpath "//${1}/text()" -
    fi
    

    And in your .conkyrc:

    ${color slate grey}Number of cats: ${color }
    ${execi 3600 myscript.sh --store-cache cats}
    
    ${color slate grey}Color of the day: ${color }
    ${execi 3600 myscript.sh --use-cache color}
    
    ${color slate grey}Some other stuff: ${color }
    ${execi 3600 myscript.sh --use-cache stuff}
    
    • It may be nice to write the cache on a tmpfs. Some distros have /dev/shm mounted by default as tmpfs.