This is a slowly growing collection of hopefully useful and reusable shell functions and patterns. https://code.jan.io/jan/jans_shell_utils
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Jan Lehnardt e9e8944c18 feat: add canonical readlink 1 year ago
test feat: add canonical readlink 1 year ago
.gitignore init 1 year ago
LICENSE.md add license info 1 year ago
README.md feat: add canonical readlink 1 year ago
canonical_readlink.sh feat: add canonical readlink 1 year ago
lib.sh add license info 1 year ago
trap_error_example.sh add license info 1 year ago
trap_exit_example.sh add license info 1 year ago
wait_for_pid_exit.sh doc: add fancy code comment for multi-pip expression 1 year ago
wait_for_url.sh feat: exorcise bashisms 1 year ago

README.md

Jan’s Shell Utilities

I’m coming across having to write the same shell script bits occasionally, and I got tired of jumping backwards through my projects to find the latest version, so here is a repository.

This is a slowly growing collection of hopefully useful and reusable shell functions and patterns.

Currently tested in macOS only.

Copyright (c) 2022 Jan Lehnardt jan@apache.org, MIT licensed

Goals

  • Write once (here) and copypasta everywhere.
  • sh compatible if possible

Examples

This section shows example usages for common shell patterns.

Trap errors

trap_error_example.sh: If you run a script with -e that produces state that you want to clean up if anything goes wrong in your script.

trap_exit_example.sh: if you run a script that launches other processes, and you want to make sure those processes exit when your script exists.

Functions

This section documents reusable functions for your scripts.

wait_for_url $url $duration $iterations

Wait for a particular URL to be available using curl. Wait $duration seconds between attempts, try $iterations times. Defaults to 1 seconds and 3 times.

Signature:

wait_for_url url<string> [iterations<int>=1 duration<int>=1]

Usage:

. ./wait_for_url.sh

# try 3 times, 1s apart
wait_for_url http://127.0.0.1:5984

# try 5 times, 1s apart
wait_for_url http://127.0.0.1:5984 5 3

# try 5 times, 3s apart
wait_for_url http://127.0.0.1:5984 5 3

wait_for_pid_exit $pid $duration $iterations

Wait for a particular PID to exit. Wait $duration seconds between attempts, try $iterations times. Defaults to 1 seconds and 3 times.

Signature:

wait_for_pid_exit pid<int> [iterations<int>=3 duration<int>=1]

Usage:

. ./wait_for_pid_exit.sh

# try 3 times, 1s apart
wait_for_pid_exit 3618

# try 5 times, 1s apart
wait_for_pid_exit 3618 5 3

# try 5 times, 3s apart
wait_for_pid_exit 3618 5 3

error_and_exit $message

Prints an error message and then exits with exit code 1. The message defaults to error

Signature:

error_and_exit [message<string>=error]

Usage:

. ./lib

# print message, then exit
error_and_exit "this did not work"

TODO:

  • make exit code variable
    • probably as error_and_exit "msg" 17

assert_arg $arg

Assert if a particular argument has been passed to a function. Combine with && and || for error handling and setting of defaults for optional arguments.

Signature:

assert_arg arg<any>

Usage:

. ./lib.sh


# fail if arg is missing
my_fun () {
	assert_arg $1 && url=$1 || error_and_exit "error 'url' missing"
	# now $url is available
}

# set arg to default value if missing
my_fun () {
	assert_arg $1 && iterations=$1 || iterations=5
	# now $iterations is available
}

When you want to find out the directory the script you are currently running in, there are a number of UNIX filesystem indirections that are somewhat tricky to untangle. This function does that for you.

Signature:

canonical_readlink filepath<string>

Usage:

my_dir=`canonical_readlink "$0"`

Debugging

Set DEBUG=1 to get debugging output.