View on GitHub

bash-funk

bash-funk is a collection of useful commands for Bash 3.2 or higher.

Bash-Funk “random” module

The following commands are available when this module is loaded:

  1. -entropy-available
  2. -fill-entropy
  3. -random-number
  4. -random-string
  5. -test-all-random

License

SPDX-FileCopyrightText: © Vegard IT GmbH (https://vegardit.com)
SPDX-License-Identifier: Apache-2.0

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

-entropy-available

Usage: -entropy-available [OPTION]...

Determines if enough entropy bits are available perform a non-blocking read from /dev/random. Exit code 1 indicates entropy pool is not sufficiently filled.

Options:
    --help
        Prints this help.
    --tracecmd
        Enables bash debug mode (set -x).
    --selftest
        Performs a self-test.
    --
        Terminates the option list.

Examples:
$ -entropy-available 
/proc/sys/kernel/random/entropy_avail: 64
/proc/sys/kernel/random/read_wakeup_threshold: 2429

Implementation:

if [[ ! -e /proc/sys/kernel/random/read_wakeup_threshold ]]; then
   echo "-entropy-available: Warning: Kernel parameter /proc/sys/kernel/random/read_wakeup_threshold is not present, assuming sufficient entropy is available."
   return 0
fi

local avail=$(cat /proc/sys/kernel/random/entropy_avail)
local required=$(cat /proc/sys/kernel/random/read_wakeup_threshold)
echo "/proc/sys/kernel/random/entropy_avail: $avail"
echo "/proc/sys/kernel/random/read_wakeup_threshold: $required"
(( avail > required ))

-fill-entropy

Usage: -fill-entropy [OPTION]... [DURATION]

Fills /dev/random with pseudo-random values from /dev/urandom.

Requirements:
  + Command 'rngd' must be available.
  + Sudo 'rngd' is required.

Parameters:
  DURATION (default: '1', integer: 1-?)
      Number of seconds the entropy pool will be filled.

Options:
    --help
        Prints this help.
    --tracecmd
        Enables bash debug mode (set -x).
    --selftest
        Performs a self-test.
    --
        Terminates the option list.

Examples:
$ -fill-entropy 
Available entropy bits before: 1000
Generating for 1 second(s)...
Available entropy bits after: 1013
$ -fill-entropy 2
Available entropy bits before: 1013
Generating for 2 second(s)...
Available entropy bits after: 1039

Implementation:

echo -n "Available entropy bits before: "
cat /proc/sys/kernel/random/entropy_avail

echo "Generating for ${_DURATION} seconds..."
local timeoutCmd
if hash timeout 2>/dev/null; then
   timeoutCmd="timeout"
elif hash gtimeout 2>/dev/null; then
   timeoutCmd="gtimeout"
else
   timeoutCmd="perl -e 'alarm shift; exec @ARGV'"
fi
if rngd --help | grep -q -- --feed-interval; then
   # using timeoutCmd despite "--feed-interval" parameter because rngd in some environments randomly hangs (e.g. github actions with ubuntu 22)
   sudo $timeoutCmd $((_DURATION + 1)) rngd --foreground -r /dev/urandom -o /dev/random --feed-interval ${_DURATION}
elif rngd --help | grep -q -- --timeout; then
   # using timeoutCmd despite "--timeout" parameter because rngd in some environments randomly hangs (e.g. github actions with ubuntu 22)
   sudo $timeoutCmd $((_DURATION + 1)) rngd --foreground -r /dev/urandom -o /dev/random --timeout ${_DURATION}
else
   sudo $timeoutCmd ${_DURATION} rngd --foreground -r /dev/urandom -o /dev/random
fi

echo -n "Available entropy bits after: "
cat /proc/sys/kernel/random/entropy_avail

-random-number

Usage: -random-number [OPTION]... RANGE

Generates a random number of the given range. The range is inclusive.

Requirements:
  * Either:
    + Command 'shuf' must be available.
  * Or:
    + Command 'gshuf' must be available.

Parameters:
  RANGE (required, pattern: "[1-9][0-9]*-[1-9][0-9]*")
      The numeric range LOW-HIGH, e.g. 1-5.

Options:
    --help
        Prints this help.
    --tracecmd
        Enables bash debug mode (set -x).
    --selftest
        Performs a self-test.
    --
        Terminates the option list.

Examples:
$ -random-number 1-1
1
$ -random-number 1-5
4
$ -random-number 200-299
253

Implementation:

if hash gshuf &>/dev/null; then # MacOS
   gshuf -i ${_RANGE} -n 1
else
   shuf -i ${_RANGE} -n 1
fi

-random-string

Usage: -random-string [OPTION]... LENGTH [CHARS]

Prints a random string of the given length containing the given characters.

Parameters:
  LENGTH (required, integer: 1-?)
      Length of the string to generate.
  CHARS (default: '[:graph:]')
      String to choose random characters from.

Options:
    --help
        Prints this help.
    --tracecmd
        Enables bash debug mode (set -x).
    --selftest
        Performs a self-test.
    --
        Terminates the option list.

Examples:
$ -random-string 12 0-9
686026902293
$ -random-string 8 a-zA-Z
ECtQptCz
$ -random-string 10 [:alnum:]
w2TZ8fHaRw
$ -random-string 10 [:alnum:][:punct:]
4pH?+40D):

Implementation:

# "2> >(grep -v "write error" >&2)" and "|| true" to mitigate "tr: write error: Broken pipe" on e.g. GitHub Actions
env -i LC_CTYPE=C tr -dc "$_CHARS" </dev/urandom 2> >(grep -v "write error" >&2) | head -c ${_LENGTH} || true

-test-all-random

Usage: -test-all-random [OPTION]...

Performs a selftest of all functions of this module by executing each function with option '--selftest'.

Options:
    --help
        Prints this help.
    --tracecmd
        Enables bash debug mode (set -x).
    --selftest
        Performs a self-test.
    --
        Terminates the option list.

Implementation:

if [ -e /proc/sys/kernel/random/entropy_avail ]; then -entropy-available --selftest && echo || return 1; fi
if [ -e /proc/sys/kernel/random/entropy_avail ]; then -fill-entropy --selftest && echo || return 1; fi
-random-number --selftest && echo || return 1
if ! [[ $OSTYPE == 'darwin'* && $GITHUB_ACTIONS == 'true' ]]; then -random-string --selftest && echo || return 1; fi