From 95e070fdaf630c8cf7fb17826bb6a431acac6d24 Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Tue, 1 Feb 2022 02:01:07 +0900 Subject: [PATCH] Add README file The repository does not have a README file, making it hard for users to understand what toolbox is, how it works, and what modules there are. This commit adds a README that explains what toolbox is, how it can be installed, and what modules there are. --- README.md | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..c171fee --- /dev/null +++ b/README.md @@ -0,0 +1,248 @@ +# toolbox - A module framework for Bash + +Have you ever written a shell script and found yourself thinking +"if only the Bash had an include mechanism", while copy-pasting +the command line parser you wrote for a different shell script? +Then you should try toolbox for your next shell script! + + +## What's toolbox? + +Toolbox is a simple framework for Bash that lets you modularize +your scripts. At the heart of toolbox is the `include()` function, +which works much like the `import` statement in Python. Once you +source *toolbox.sh*, you can use `include()` to load the modules +that ship with toolbox, or create your own ones. + + +## What modules are there? + +Toolbox comes with a number of modules that solve common problems. +The following is a list of the default modules and what they are +used for. + +| Module | Purpose | +|--------|---------| +| array | Comparing, searching, and sorting arrays | +| conf | Configuration handling | +| git | Interacting with git repositories | +| inst | Writing daemons | +| ipc | Message-based IPC | +| is | Checking the value of variables | +| json | Handling JSON data | +| log | Logging and debugging | +| mutex | Locks for protecting shared resources (similar to pthread mutexes) | +| opt | Command line parsing | +| queue | "Thread"-safe FIFOs | +| sem | Process synchronization (similar to POSIX semaphores) | +| wmutex | Weak (owner-less) locks | + + +## Installation + +There are two ways to install toolbox: using apt or from the source. + + +### Installation using apt + +If you are using a Debian-based distribution, you can install toolbox through apt. +First, import the GPG key used to sign packages in the repository and make sure you +have `apt-transport-https` installed. + + # wget -O - -- https://deb.m10k.eu/deb.m10k.eu.gpg.key | apt-key add - + # apt-get install apt-transport-https + +Then add the following line to your `/etc/apt/sources.lst`. + + deb https://deb.m10k.eu stable main + +If you prefer a more recent (and maybe slightly more unstable version), use the +`unstable` suite instead. + + deb https://deb.m10k.eu unstable main + +Next, update your package index using the following command. + + # apt-get update + +Now you can install and update toolbox as you're used to. + + # apt-get install toolbox + +The packages in the repository are automatically built from the stable and +unstable branches, so the Debian packages are usually no more than a few minutes +older than the sources. + + +### Installation from source + +To install toolbox from git, check out the sources and run `make install`. + + $ git clone https://github.com/m10k/toolbox + $ cd toolbox + $ sudo make install + +You will also need to create the *toolbox* and *toolbox_ipc* groups and change +ownership on */var/lib/toolbox* and */var/lib/toolbox/ipc*. + + # chown root.toolbox /var/lib/toolbox + # chown root.toolbox_ipc /var/lib/toolbox/ipc + + +### Configuration + +To use the ipc module, membership in *toolbox* and *toolbox_ipc* is necessary. +You can add a user to these groups with the following command. + + # usermod -a -G toolbox,toolbox_ipc USERNAME + + +## How does this work? + +When toolbox is installed, `toolbox.sh` is placed in *PATH*, where it will +be picked up by the `source` (aka `.`) shell command, allowing you to load +toolbox without worrying about the path of any other files. +When loading a module, `include()` will search the following paths (in +order) for modules: + + 1. `$HOME/.toolbox/include` + 2. `/usr/share/toolbox/include` + +This allows you to place custom modules in your home directory, while the +default modules are in a system-wide path. + + +### And the modules? + +Bash does not have a notion of modules, so toolbox tries its best to provide +something that looks like a module, feels like a module, and tastes like a +module, but is not actually a module. For this to work, modules have to +follow strict guidelines. + +A module is a single shell script with one or more of the following: + +| Element | Description | +|---------|-------------| +| Constructor | Module initialization function called by `include()` | +| Public functions | Functions that may be called by users | +| Private functions | Functions that users must not call | +| Private variables | Variables that users must not use | + +In shell, everything shares the same namespace. Thus, the most important +thing about a module is that it does not declare functions or variables +outside of its own namespace. The following table summarizes the naming +convention for modules. + +| Element | Naming convention | Example | +|---------|-------------------|---------| +| Module name | Lower-case letters | `example` | +| Module file name | Module name + `.sh` | `example.sh` | +| Constructor | `__init()` | `__init()` | +| Public function | Module name + `_` + function name | `example_open()` | +| Private function | `_` + module name + `_` + function name | `_example_write()` | +| Private variable | `__` + module name + `_` + variable name | `__example_mode` | + +Functions intended to be called by users are prefixed with the module name and an +underscore. Functions that users must not call because they might change between +versions at the developers' whim (that is, private functions) are prefixed with an +underscore, the module name, and another underscore. Variables are prefixed with two +underscores, the module name, and another underscore. Variables declared by modules +are always considered private and must not be used directly by users. Further, +because users may execute functions in sub-shells, modules **must** export their +variables (`declare -x`). Module developers are also encouraged to declare their +variables as integers (`declare -i`), arrays (`declare -a`), or associative arrays +(`declare -A`) when they are any of those types. Variables that are not expected to +change (i.e. constants) must be declared as such using `declare -r` or `readonly`. +All global variables must be declared in the module constructor, unless that is +absolutely not feasible. All variables used in module functions **must be declared +using local** unless they are intended to be global. + + +#### Example module + +The following code example illustrates the coding guidelines for modules. + + # + # logrun.sh - Toolbox module for logging commands + # + + __init() { + if ! include "log"; then + return 1 + fi + + declare -gxr __logrun_timestamp_format="%Y-%m-%d %H:%M:%S" + + return 0 + } + + _logrun_get_timestamp() { + if ! date +"$__logrun_timestamp_format"; then + log_error "Call to date failed. Out of memory?" + return 1 + fi + + return 0 + } + + _logrun_write_line() { + local data="$1" + + local timestamp + + if ! timestamp=$(_logrun_get_timestamp); then + return 1 + fi + + echo "$timestamp $data" 1>&2 + return 0 + } + + _logrun_log() { + local data="$1" + + local line + + if (( $# < 1 )); then + data=$(< /dev/stdin) + fi + + while read -r line; do + if ! _logrun_write_line "$line"; then + return 1 + fi + done <<< "$data" + + return 0 + } + + logrun_exec() { + local cmd="$1" + local args=("${@:2}") + + local stdout + local retval + + _logrun_log "Executing: $cmd ${args[*]}" + stdout=$("$cmd" "${args[@]}") + retval="$?" + + _logrun_log "$cmd returned $retval" + _logrun_log "===== BEGIN stdout =====" + _logrun_log <<< "$stdout" + _logrun_log "===== END stdout =====" + + return "$retval" + } + + +## Additional modules + +There are additional modules in the following repositories. These modules have been +removed from this repository to reduce the dependencies of the toolbox package. + +| Repository | Purpose | +|------------|---------| +| [toolbox-goodies](https://github.com/m10k/toolbox-goodies) | Nice-to-have modules | +| [toolbox-linux](https://github.com/m10k/toolbox-linux) | Linux-specific modules | +| [toolbox-restapis](https://github.com/m10k/toolbox-restapis) | Modules for interacting with REST-ful APIs | -- 2.47.3