diff options
author | Tom Ryder <tom@sanctum.geek.nz> | 2016-12-09 10:16:05 +1300 |
---|---|---|
committer | Tom Ryder <tom@sanctum.geek.nz> | 2016-12-09 10:17:34 +1300 |
commit | a0acd17ec7a54b2e2fe48b1a98fc7f99cf0d0341 (patch) | |
tree | 41bb0d54b40c79ab3f79d4d927c4fd8dd07171c6 | |
parent | Add uts(1df) (diff) | |
download | dotfiles-a0acd17ec7a54b2e2fe48b1a98fc7f99cf0d0341.tar.gz dotfiles-a0acd17ec7a54b2e2fe48b1a98fc7f99cf0d0341.zip |
Add chc(1df)
-rw-r--r-- | README.markdown | 1 | ||||
-rwxr-xr-x | bin/chc | 31 | ||||
-rw-r--r-- | man/man1/chc.1df | 35 |
3 files changed, 67 insertions, 0 deletions
diff --git a/README.markdown b/README.markdown index 3c692ae5..fd86e656 100644 --- a/README.markdown +++ b/README.markdown @@ -419,6 +419,7 @@ Installed by the `install-bin` target: * `cf(1df)` prints a count of entries in a given directory. * `cfr(1df)` does the same as `cf(1df)`, but recurses into subdirectories as well. +* `chc(1df)` caches the output of a command * `clrd(1df)` sets up a per-line file read, clearing the screen first. * `clwr(1df)` sets up a per-line file write, clearing the screen before each line diff --git a/bin/chc b/bin/chc new file mode 100755 index 00000000..b1e4000d --- /dev/null +++ b/bin/chc @@ -0,0 +1,31 @@ +#!/bin/sh +# Cache the output of a command and emit it straight from the cache if not +# expired on each run + +# First argument is the cache path, second is the duration in seconds +cac=$1 dur=$2 +shift 2 + +# Get the current timestamp with uts(1df) +uts=$(uts) || exit + +# Function checks cache exists, is readable, and not expired +fresh() { + [ -f "$cac" ] || return + [ -r "$cac" ] || return + exp=$(sed 1q -- "$cac") || return + [ "$((exp > uts))" -eq 1 ] +} + +# Write runs the command and writes it to the cache +write() { + exp=$((uts + dur)) + printf '%u\n' "$exp" + "$@" +} + +# If the cache isn't fresh, try to write a new one, or bail out +fresh "$cac" || write "$@" > "$cac" || exit + +# Emit the content (exclude the first line, which is the timestamp) +sed 1d -- "$cac" diff --git a/man/man1/chc.1df b/man/man1/chc.1df new file mode 100644 index 00000000..e447d7a7 --- /dev/null +++ b/man/man1/chc.1df @@ -0,0 +1,35 @@ +.TH CHC 1df "December 2016" "Manual page for chc" +.SH NAME +.B chc +\- cache the output of a command to avoid running it too often +.SH USAGE +.B chc +CACHE_PATH DURATION COMMAND [ARG1...] +.SH SYNOPSIS +.B chc +/tmp/example.chc 20 curl http://www.example.com/ +.SH DESCRIPTION +.B chc +runs the command given in its third argument onwards, and saves the output in +the file with path given in the first argument, and on each subsequent request +before the duration in the second argument expires, it emits the content +directly, rather than running the command. If it's run after the expiry date, +it runs the command again, and refreshes the cache. +.P +This is intended as a quick way to just add three words in front of any given +expensive command to prevent it running too often. This might be particularly +useful if a script is called to get data far more often than it actually needs +to poll to get that data. +.P +No file locking is implemented. If you need it, you're probably already at the +point that you need to write a proper solution, but you could always use Linux +flock(1) or daemontool's setlock(1) in the command if you're stubborn: +.P + flock -x /var/lock/example.chc chc /var/cache/example.chc 20 curl http://www.example.com/ +.P +If you want to express the duration in human-readable terms, sec(1df) might be +useful too. +.SH SEE ALSO +sec(1df), uts(1df), flock(1), setlock(1) +.SH AUTHOR +Tom Ryder <tom@sanctum.geek.nz> |