Reusing shell scripts is hard as packaging is often complicated by itself and therefore they live scattered all over our disks and when we need a specific one the search begins.
Module.sh is set to improve upon that situation. It can fetch the required script easily from the internet, either at runtime or it can build you a script which embeds all its script dependencies.
While that might sound like it has a few challenges by its own, Module.sh does so while caching fetched scripts and checking checksums before execution.
#!/bin/sh # yes, we aim to be POSIX compliant # loading module.sh, if curl+eval is a problem, there are ways to avoid them eval "$(curl -fsL "https://mdl.sh/latest")" # using module.sh to load the hello-world module module "helloWorld" "https://mdl.sh/misc/hello-world/hello-world-1.0.1.sh" "cksum-3769348439" # executing the loaded module helloWorld
If you don’t want to rely on an external service: you don’t have to. Actually, there are many reasons to host your scripts on your own server.
Fetch, Execute, Done
Supports multiple versions of the same module
You can always get the latest static version of Module.sh from:
Just download it and save it as
module.sh. To use Module.sh in
your script you have to
source it like that:
If you want to load it relative to your script and not relative to your current work directory you can use something like:
. "$(dirname "$(readlink -f "$0")")/module.sh"
If you want to let your script download the latest version of Module.sh during execution you can use the following snippet:
eval "$(curl -fsL "https://mdl.sh/latest")"
After that line, you can use the
module command. The upside of this
approach is the ease of use. The downside is that it will not work when
the server fails and under certain circumstance can lead to
executing some server error message (if curl doesn’t fail). So this
is nice for playing around, but should not be used in production.
Other good reasons to use Module.sh
When your scripts become larger you often struggle with the fact
that every variable name is part of the global scope (even the ones
within functions). An easy fix is to use the
local keyword. But
did you know that
local is not POSIX compliant?
Module.sh solves the issue by isolating every module within its own Sub-Shell. That way you can keep using global variable names, as global gets limited to your module.
Did you know that a simple statement like
echo "Error Message" >/dev/stderr
is not POSIX compliant? (/dev/stderr is not part of POSIX)