{"id":13567507,"url":"https://github.com/m10k/toolbox","last_synced_at":"2026-04-04T22:12:12.808Z","repository":{"id":49715271,"uuid":"450329956","full_name":"m10k/toolbox","owner":"m10k","description":"Module framework for Bash","archived":false,"fork":false,"pushed_at":"2023-08-12T05:51:47.000Z","size":396,"stargazers_count":73,"open_issues_count":1,"forks_count":5,"subscribers_count":4,"default_branch":"unstable","last_synced_at":"2025-04-01T15:56:44.968Z","etag":null,"topics":["bash","messaging","module","publish-subscribe","pubsub","shell","toolbox"],"latest_commit_sha":null,"homepage":"https://m10k.eu/toolbox.html","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/m10k.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-21T02:42:52.000Z","updated_at":"2025-01-30T09:51:46.000Z","dependencies_parsed_at":"2024-08-01T13:25:07.471Z","dependency_job_id":"3741deec-b2f6-4ba4-a191-cc53e798e4b6","html_url":"https://github.com/m10k/toolbox","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m10k%2Ftoolbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m10k%2Ftoolbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m10k%2Ftoolbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/m10k%2Ftoolbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/m10k","download_url":"https://codeload.github.com/m10k/toolbox/tar.gz/refs/heads/unstable","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247107816,"owners_count":20884793,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bash","messaging","module","publish-subscribe","pubsub","shell","toolbox"],"created_at":"2024-08-01T13:02:33.276Z","updated_at":"2026-04-04T22:12:12.764Z","avatar_url":"https://github.com/m10k.png","language":"Shell","funding_links":[],"categories":["Shell"],"sub_categories":[],"readme":"# toolbox - A module framework for Bash\n\nHave you ever written a shell script and found yourself thinking\n\"if only the Bash had an include mechanism\", while copy-pasting\nthe  command line parser you wrote for a different shell script?\nThen you should try toolbox for your next shell script!\n\n\n## What's toolbox?\n\nToolbox is a simple framework for Bash that lets you modularize\nyour scripts. At the heart of toolbox is the `include()` function,\nwhich works much like the `import` statement in Python. Once you\nsource *toolbox.sh*, you can use `include()` to load the modules\nthat ship with toolbox, or create your own ones.\n\n\n## How do I use it?\n\nAll you have to do is source *toolbox.sh* and you can start using\nthe `include()` function. For example, the following code is a\nminimal publisher using the *uipc* module.\n\n    . toolbox.sh\n    include \"uipc\"\n\n    endp=$(uipc_endpoint_open)\n    uipc_endpoint_publish \"$endp\" \"mytopic\" \"Hello world\"\n\nAnd this is the corresponding subscriber.\n\n    . toolbox.sh\n    include \"uipc\"\n\n    endp=$(uipc_endpoint_open)\n    uipc_endpoint_subscribe \"$endp\" \"mytopic\"\n\n    if msg=$(uipc_endpoint_recv \"$endp\"); then\n    \tdata=$(uipc_msg_get_data \"$msg\")\n\n    \techo \"Received message: $data\"\n    fi\n\n\n## What modules are there?\n\nToolbox comes with a number of modules that solve common problems.\nThe following is a list of the default modules and what they are\nused for.\n\n| Module | Purpose |\n|--------|---------|\n| array  | Comparing, searching, and sorting arrays |\n| conf   | Configuration handling |\n| git    | Interacting with git repositories |\n| inst   | Writing daemons |\n| ipc    | Message-based IPC (GPG-signed messages) |\n| is     | Checking the value of variables |\n| json   | Handling JSON data |\n| log    | Logging and debugging |\n| mutex  | Locks for protecting shared resources (similar to pthread mutexes) |\n| opt    | Command line parsing |\n| queue  | \"Thread\"-safe FIFOs |\n| sem    | Process synchronization (similar to POSIX semaphores) |\n| uipc   | Message-based IPC (unsigned messages) |\n| wmutex | Weak (owner-less) locks |\n\nModules are described in detail in the [module reference](docs/reference.md)\n\n\n## Installation\n\nThere are two ways to install toolbox: using apt or from the source.\n\n\n### Installation using apt\n\nIf you are using a Debian-based distribution, you can install toolbox through apt.\nFirst, import the GPG key used to sign packages in the repository and make sure you\nhave `apt-transport-https` installed.\n\n    # curl --get https://deb.m10k.eu/deb.m10k.eu.gpg \u003e /etc/apt/trusted.gpg.d/deb.m10k.eu.gpg\n    # apt-get install apt-transport-https\n\nThen add the following line to your `/etc/apt/sources.lst`.\n\n    deb https://deb.m10k.eu stable main\n\nIf you prefer a more recent (and maybe slightly more unstable version), use the\n`unstable` suite instead.\n\n    deb https://deb.m10k.eu unstable main\n\nNext, update your package index using the following command.\n\n    # apt-get update\n\nNow you can install and update toolbox as you're used to.\n\n    # apt-get install toolbox\n\nThe packages in the repository are automatically built from the stable and\nunstable branches, so the Debian packages are usually no more than a few minutes\nolder than the sources.\n\n\n### Installation from source\n\nTo install toolbox from git, check out the sources and run `make install`.\n\n    $ git clone https://github.com/m10k/toolbox\n    $ cd toolbox\n    $ sudo make install\n\nYou will also need to create the *toolbox* and *toolbox_ipc* groups and change\nownership on */var/lib/toolbox* and */var/lib/toolbox/ipc*.\n\n    # chown root:toolbox /var/lib/toolbox\n    # chown root:toolbox_ipc /var/lib/toolbox/ipc\n\n\n### Configuration\n\nTo use the ipc module, membership in *toolbox* and *toolbox_ipc* is necessary.\nYou can add a user to these groups with the following command.\n\n    # usermod -a -G toolbox,toolbox_ipc USERNAME\n\nThe ipc module uses GPG to sign and verify messages, so you also need to make\nsure that you have a keypair. You can generate one with the following command.\n\n    $ gpg --full-generate-key\n\n\n## How does this work?\n\nWhen toolbox is installed, `toolbox.sh` is placed in *PATH*, where it will\nbe picked up by the `source` (aka `.`) shell command, allowing you to load\ntoolbox without worrying about the path of any other files.\nWhen loading a module, `include()` will search the following paths (in\norder) for modules:\n\n 1. `$HOME/.toolbox/include`\n 2. `/usr/share/toolbox/include`\n\nThis allows you to place custom modules in your home directory, while the\ndefault modules are in a system-wide path.\n\n\n### And the modules?\n\nBash does not have a notion of modules, so toolbox tries its best to provide\nsomething that looks like a module, feels like a module, and tastes like a\nmodule, but is not actually a module. For this to work, modules have to\nfollow strict guidelines.\n\nA module is a single shell script with one or more of the following:\n\n| Element | Description |\n|---------|-------------|\n| Constructor | Module initialization function called by `include()` |\n| Public functions | Functions that may be called by users |\n| Private functions | Functions that users must not call |\n| Private variables | Variables that users must not use |\n\nIn shell, everything shares the same namespace. Thus, the most important\nthing about a module is that it does not declare functions or variables\noutside of its own namespace. The following table summarizes the naming\nconvention for modules.\n\n| Element | Naming convention | Example |\n|---------|-------------------|---------|\n| Module name | Lower-case letters | `example` |\n| Module file name | Module name + `.sh` | `example.sh` |\n| Constructor | `__init()` | `__init()` |\n| Public function | Module name + `_` + function name | `example_open()` |\n| Private function | `_` + module name + `_` + function name | `_example_write()` |\n| Private variable | `__` + module name + `_` + variable name | `__example_mode` |\n\nFunctions intended to be called by users are prefixed with the module name and an\nunderscore. Functions that users must not call because they might change between\nversions at the developers' whim (that is, private functions) are prefixed with an\nunderscore, the module name, and another underscore. Variables are prefixed with two\nunderscores, the module name, and another underscore. Variables declared by modules\nare always considered private and must not be used directly by users. Further,\nbecause users may execute functions in sub-shells, modules **must** export their\nvariables (`declare -x`). Module developers are also encouraged to declare their\nvariables as integers (`declare -i`), arrays (`declare -a`), or associative arrays\n(`declare -A`) when they are any of those types. Variables that are not expected to\nchange (i.e. constants) must be declared as such using `declare -r` or `readonly`.\nAll global variables must be declared in the module constructor, unless that is\nabsolutely not feasible. All variables used in module functions **must be declared\nusing local** unless they are intended to be global.\n\n\n#### Example module\n\nThe following code example illustrates the coding guidelines for modules.\n\n    #\n    # logrun.sh - Toolbox module for logging commands\n    #\n\n    __init() {\n    \tif ! include \"log\"; then\n    \t\treturn 1\n    \tfi\n\n    \tdeclare -gxr __logrun_timestamp_format=\"%Y-%m-%d %H:%M:%S\"\n\n    \treturn 0\n    }\n\n    _logrun_get_timestamp() {\n    \tif ! date +\"$__logrun_timestamp_format\"; then\n    \t\tlog_error \"Call to date failed. Out of memory?\"\n    \t\treturn 1\n    \tfi\n\n    \treturn 0\n    }\n\n    _logrun_write_line() {\n    \tlocal data=\"$1\"\n\n    \tlocal timestamp\n\n    \tif ! timestamp=$(_logrun_get_timestamp); then\n    \t\treturn 1\n    \tfi\n\n    \techo \"$timestamp $data\" 1\u003e\u00262\n    \treturn 0\n    }\n\n    _logrun_log() {\n    \tlocal data=\"$1\"\n\n    \tlocal line\n\n    \tif (( $# \u003c 1 )); then\n    \t\tdata=$(\u003c /dev/stdin)\n    \tfi\n\n    \twhile read -r line; do\n    \t\tif ! _logrun_write_line \"$line\"; then\n    \t\t\treturn 1\n    \t\tfi\n    \tdone \u003c\u003c\u003c \"$data\"\n\n    \treturn 0\n    }\n\n    logrun_exec() {\n    \tlocal cmd=\"$1\"\n    \tlocal args=(\"${@:2}\")\n\n    \tlocal stdout\n    \tlocal retval\n\n    \t_logrun_log \"Executing: $cmd ${args[*]}\"\n    \tstdout=$(\"$cmd\" \"${args[@]}\")\n    \tretval=\"$?\"\n\n    \t_logrun_log \"$cmd returned $retval\"\n    \t_logrun_log \"===== BEGIN stdout =====\"\n    \t_logrun_log \u003c\u003c\u003c \"$stdout\"\n    \t_logrun_log \"===== END stdout =====\"\n\n    \treturn \"$retval\"\n    }\n\n\n## Additional modules\n\nThere are additional modules in the following repositories. These modules have been\nremoved from this repository to reduce the dependencies of the toolbox package.\n\n| Repository | Purpose |\n|------------|---------|\n| [toolbox-goodies](https://github.com/m10k/toolbox-goodies) | Nice-to-have modules |\n| [toolbox-linux](https://github.com/m10k/toolbox-linux) | Linux-specific modules |\n| [toolbox-restapis](https://github.com/m10k/toolbox-restapis) | Modules for interacting with REST-ful APIs |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm10k%2Ftoolbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fm10k%2Ftoolbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fm10k%2Ftoolbox/lists"}