shrun
was borne of frustration. Suppose we need to run several shell commands on a regular basis e.g. updates after pulling the latest code. These can be run manually in separate terminals:
cmd1
cmd2
cmd3
...
But this can be a lot of repetitive typing, especially when the commands are longer. Thus an alias is born:
alias run_commands="cmd1 && cmd2 && cmd3 ..."
All well and good, but this approach has several deficiencies:
-
There is no information about how long the commands have been running. If any of the commands are long-lived, how would we know when it has been "too long" and the commands should be cancelled? We could use a wall clock or a stopwatch, but that is imprecise and requires remembering every time the commands are run, which is certainly unsatisfying.
-
These commands are all run synchronously even though there may be no relation between them. For example, three commands that each take 5 minutes will combine to take 15 minutes. This is usually unnecessary.
-
Related to above, if any command fails then subsequent ones will not be run. This can be frustrating, especially when a quicker command in the beginning prevents a longer one at the end from even starting.
-
If the alias is tweaked to run all regardless (
cmd1; cmd2; cmd3 ...
), then it can be difficult to determine which, if any, failed. Additionally, understanding logs is much harder. -
It does not scale. Imagine we have variations of
cmd3
we want to run under different circumstances. We could create multiple aliases:alias run_commands_cmd3a="cmd1 && cmd2 && cmd3a" alias run_commands_cmd3b="cmd1 && cmd2 && cmd3b"
But this is messy and grows exponentially in the number of aliases for each variation.
shrun
purports to overcome these limitations.
In a nut-shell (😉), shrun
is a wrapper around running shell commands. For instance:
shrun "some long command" "another command"
Will run some long command
and another command
concurrently.
A running timer is provided, and stdout will be updated when a command finishes or crashes.
The releases page has binaries built for several platforms. If there are no binaries for your platform, it is possible to build shrun yourself.
If you have never built a haskell program before, Cabal is probably the best choice.
cabal 3.8+
- One of:
The easiest way to install these is generally ghcup
.
The current "blessed" version is ghc-9.8.2
.
Once you have cabal
and ghc
, shrun
can be built locally with cabal build
or installed globally (e.g. ~/.local/bin/shrun
) with cabal install
.
For further reproducibility, optional freeze files can be used e.g.
cabal build --project-file cabal.ghc982.project
Note
Freeze files are provided for only select compilers.
Like cabal
and ghc
, stack
can be installed with ghcup
.
Once you have stack
, shrun
can be built with stack build
or installed globally (i.e. ~/.local/bin/shrun
) with stack install
.
Building with nix
uses flakes. shrun
can be built with nix build
, which will compile and run the tests.
Because shrun
is a flake, it can be built as part of a nix expression. For instance, if you want to add shrun
to NixOS
, your flake.nix
should have:
# flake.nix
{
inputs.shrun.url = "github:tbidne/shrun/main";
}
Then include this in the systemPackages
:
# wherever your global packages are defined
{
environment.systemPackages = [
shrun.packages."${system}".default
];
}
See configuration.md for the available options.
See faq.md.