Skip to content

Instantly share code, notes, and snippets.

@cweagans
Last active March 12, 2020 03:58
Show Gist options
  • Save cweagans/2f78c906d081532efbc9606009545e0f to your computer and use it in GitHub Desktop.
Save cweagans/2f78c906d081532efbc9606009545e0f to your computer and use it in GitHub Desktop.
Cache the output of any CLI tool

cache.sh

Caches the output of any other CLI tool in a simple filesystem-backed cache.

Installation

Put the file in your $PATH somewhere. I called mine cache instead of cache.sh, so that's what's reflected in the examples below.

Use

If you have a program that takes a long time to run, but returns more-or-less consistent results over the period of 3 hours, you can simply prefix the command with cache and the output will be stored for 3 hours (hardcoded value, sorry).

For example, I have a command like this that I run to get a list of sites from my web hosting provider:

terminus site:list --format=list

Their API is pretty slow and that takes around 20 seconds to compelte.

If I preface the command with cache like so:

cache terminus site:list --format=list

it takes 20 seconds the first time, but then subsequent runs take 0.05 seconds.

If you want to force cache to re-execute the command in question (even if there's a currently valid cache entry), you can set the $CACHE_FORCE_EXEC environment variable to "true" like this:

CACHE_FORCE_EXEC=true cache terminus site:list --format=list
#!/usr/bin/env bash
# Get the name of the command that we're running and shift it off of the args list.
cmd=$1
shift 1
# Make sure we have a place to store the data.
[ -d "/tmp/cache_store" ] || mkdir /tmp/cache_store
[ -d "/tmp/cache_store/${cmd}" ] || mkdir /tmp/cache_store/${cmd}
# Delete cache files older than 3 hours.
find /tmp/cache_store -mindepth 1 -mmin +180 -delete
# Generate a cache filename.
filename=$(echo -n "$cmd $@" | shasum | awk '{print $1}')
# If the file doesn't exist, run the requested command to generate a new cache entry.
if [ ! -f "/tmp/cache_store/${cmd}/${filename}" ] || [ "$CACHE_FORCE_EXEC" == "true" ]; then
eval "${cmd} $@" > /tmp/cache_store/${cmd}/${filename}
# If the command wasn't successful, delete the cache entry and exit with the
# same exit code.
exitcode="$?"
if [ "$exitcode" != 0 ]; then
rm /tmp/cache_store/${cmd}/${filename}
exit $exitcode
fi
fi
# Either way, the contents of the cache file are now valid.
cat /tmp/cache_store/${cmd}/${filename}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment