aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.markdown5
-rwxr-xr-xbin/maybe79
-rwxr-xr-xbin/try95
-rw-r--r--man/man1/maybe.125
-rw-r--r--man/man1/try.121
5 files changed, 225 insertions, 0 deletions
diff --git a/README.markdown b/README.markdown
index b8086fe2..b03ae954 100644
--- a/README.markdown
+++ b/README.markdown
@@ -282,9 +282,14 @@ Scripts
* `han(1)` provides a `keywordprg` for Vim's Bash script filetype that will
look for `help` topics. You could use it from the shell too. It also has a
brief manual.
+* `maybe(1)` is like `true(1)` or `false(1)`; given a probability of success,
+ it exits with success or failure. Good for quick tests.
* `sue(8)` execs `sudoedit(8)` as the owner of all the file arguments given,
perhaps in cases where you may not necessarily have `root` `sudo(8)`
privileges.
+* `try(1)` repeats a command up to a given number of times until it succeeds,
+ only printing error output if all three attempts failed. Good for
+ tolerating blips or temporary failures in `cron(8)` scripts.
* `vis(1)` edits executable script files in `VISPATH`, defaulting to
`~/.local/bin`, for personal scripting snippets.
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"
+
diff --git a/man/man1/maybe.1 b/man/man1/maybe.1
new file mode 100644
index 00000000..ebd622b3
--- /dev/null
+++ b/man/man1/maybe.1
@@ -0,0 +1,25 @@
+.TH MAYBE 1 "November 2015" "Manual page for maybe"
+.SH NAME
+.B maybe
+\- possibly exit with success
+.SH USAGE
+.B maybe [-hv] [-d DENOMINATOR]
+.SH DESCRIPTION
+Like true(1) or false(1), but exits with success randomly with a given
+probability. Good for using in tests. Exits with 2 rather than 1 on usage
+errors.
+.P
+This just uses integer division with Bash's special RANDOM variable, so it's
+far from scientific precision.
+.P
+Option -h gives help, option -v turns on verbose output, option -d specifies
+the denominator for the probability; defaults to 2 (i.e. roughly equal chance
+of success or failure).
+.P
+ $ maybe
+ $ maybe -v -d3
+.SH SEE ALSO
+try(1)
+.SH AUTHOR
+Tom Ryder <tom@sanctum.geek.nz>
+
diff --git a/man/man1/try.1 b/man/man1/try.1
new file mode 100644
index 00000000..b21e69c3
--- /dev/null
+++ b/man/man1/try.1
@@ -0,0 +1,21 @@
+.TH TRY 1 "November 2015" "Manual page for try"
+.SH NAME
+.B try
+\- attempt a command up to a certain number of times until it succeeds
+.SH USAGE
+.B try [-hv] [-n ATTEMPTS] [--] COMMAND...'
+.SH DESCRIPTION
+Runs the given command up to a fixed number of times until it exits zero. If
+all attempts fail, writes buffered error output from all attempts to stderr.
+.P
+Option -h gives help, option -v turns on verbose output, option -n specifies
+the number of attempts; defaults to 3. Options may be terminated with --. The
+remaining arguments are the command to run.
+.P
+ $ try getmails
+ $ try -v -n3 maybe
+.SH SEE ALSO
+maybe(1)
+.SH AUTHOR
+Tom Ryder <tom@sanctum.geek.nz>
+