diff options
author | Tom Ryder <tom@sanctum.geek.nz> | 2016-02-12 16:53:20 +1300 |
---|---|---|
committer | Tom Ryder <tom@sanctum.geek.nz> | 2016-02-12 16:53:20 +1300 |
commit | cd3e8631255561d8ab21352b8cb691c05ca47fcb (patch) | |
tree | b90146674996b1efb79c06203b19a354b7eaacf9 /bin | |
parent | Update submodules (diff) | |
download | dotfiles-cd3e8631255561d8ab21352b8cb691c05ca47fcb.tar.gz dotfiles-cd3e8631255561d8ab21352b8cb691c05ca47fcb.zip |
Add try(1) and maybe(1)
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/maybe | 79 | ||||
-rwxr-xr-x | bin/try | 95 |
2 files changed, 174 insertions, 0 deletions
diff --git a/bin/maybe b/bin/maybe new file mode 100755 index 00000000..2110a959 --- /dev/null +++ b/bin/maybe @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + +# +# maybe(1) -- Like true(1) or false(1); exit with either success or failure +# randomly. Good for basic testing, but doesn't use precise probabilities, just +# fractions of RANDOM's limit. Exits with 2 on usage errors so you can tell the +# difference. +# +# -h gives help, -v gives you stdout specifying success or failure. +# +# Author: Tom Ryder <tom@sanctum.geek.nz> +# Copyright: 2016 +# +self=maybe + +# Print usage information +usage() { + printf '%s: usage: %s [-hv] [-d DENOMINATOR]\n' \ + "$self" "$self" +} + +# Flag for whether to print diagnostics to stdout or not +declare -i verbose +verbose=0 + +# Denominator of the probability fraction, e.g. 3 is a probability of 1/3; +# defaults to 2 +declare -i denom +denom=2 + +# Process options +while getopts 'hvd:' opt ; do + case $opt in + + # -h: Print help + h) + usage + exit 0 + ;; + + # -v: Print diagnostics to stdout + v) + verbose=1 + ;; + + # -d: Set the denominator of the probability fraction + d) + denom=$OPTARG + ;; + + # Unknown option + \?) + usage >&2 + exit 2 + ;; + esac +done +shift "$((OPTIND-1))" + +# If there are any non-option arguments or our denominator isn't a positive +# integer, we're being abused and we won't put up with it +if (($#)) || ! ((denom > 0)) ; then + usage >&2 + exit 2 +fi + +# Perform the test and print/exit appropriately +((verbose)) && printf '%s: Testing with probability 1/%u ... \n' \ + "$self" "$denom" +if ((RANDOM < 32767/denom)) ; then + ((verbose)) && printf '%s: %s\n' \ + "$self" 'Success!' + exit 0 +else + ((verbose)) && printf '%s: %s\n' \ + "$self" 'Failure!' + exit 1 +fi + diff --git a/bin/try b/bin/try new file mode 100755 index 00000000..ace12a14 --- /dev/null +++ b/bin/try @@ -0,0 +1,95 @@ +#!/usr/bin/env bash + +# +# try(1) -- Attempt a certain number of times to perform a task, stopping after +# the first success, and only print collected stderr if all the attempts +# failed. Designed for running from systems like cron(8) where blips and +# short-term failures can be ignored. +# +# -h gives help, -n sets the number of attempts (defaults to 3), -v gives you +# diagnostics on stdout. +# +self=try + +# Print usage information +usage() { + printf '%s: usage: %s [-hv] [-n ATTEMPTS] [--] COMMAND...\n' \ + "$self" "$self" +} + +# Flag for whether to print diagnostics to stdout or not +declare -i verbose +verbose=0 + +# Number of attempts +declare -i attc +attc=2 + +# Process options +while getopts 'hvn:' opt ; do + case $opt in + + # -h: Print help + h) + usage + exit 0 + ;; + + # -v: Print diagnostics to stdout + v) + verbose=1 + ;; + + # -n: Set the number of attempts + n) + attc=$OPTARG + ;; + + # Unknown option + \?) + usage >&2 + exit 2 + ;; + esac +done +shift "$((OPTIND-1))" + +# We need at least one more argument after shifting off the options +if ! (($#)) ; then + usage >&2 + exit 2 +fi + +# The command is all the remaining arguments +declare -a command +cmd=("$@") + +# Create a buffer file for the error output, and clean up the file when we exit +errbuf=$(mktemp) || exit +cleanup() { + rm -f -- "$errbuf" +} +trap cleanup EXIT + +# Keep trying the command, writing error output to the buffer file, and exit +# if we succeed on any of them +declare -i ret +for (( atti = 1 ; atti <= attc ; atti++ )) ; do + ((verbose)) && printf '%s: Attempt %u/%u to run `%s` ...\n' \ + "$self" "$atti" "$attc" "${cmd[*]}" + if "${cmd[@]}" 2>>"$errbuf" ; then + ((verbose)) && printf '%s: Success!\n' \ + "$self" + exit 0 + else + ret=$? + ((verbose)) && printf '%s: Failure!\n' \ + "$self" + fi +done + +# Attempts were exhausted, and all failed; print the error output from all of +# the failures and exit with the non-zero exit value of the most recent one +cat -- "$errbuf" >&2 +exit "$ret" + |