- Core Functionality
- Logging
- Notifications
- Miscellaneous
shrun
can be configured by either CLI args or a toml
config file. Most arguments exist in both formats -- where they have the same name -- though some exist only as CLI args. The following describes the CLI args. See default.toml for a description of the toml
file.
Tip
In general, each option --foo
has a --no-foo
variant that disables CLI and toml configuration for that field. For example, the --no-console-log-command
option will instruct shrun
to ignore both CLI --console-log-command
and toml console-log.command
, ensuring the default behavior is used (i.e. no command logging).
Note
shrun
colors its logs, and the examples shown here should use these colors. Unfortunately github does not render them, so you will have to view this markdown file somewhere else to see them.
Arg: -c, --config PATH
Description: Path to TOML config file. If this argument is not given we automatically look in the XDG config directory e.g. ~/.config/shrun/config.toml
. The --no-config
option disables --config
and the automatic XDG lookup.
Examples can be found in examples.
In addition to providing an alternative to CLI args, the config file has a legend
section. This allows us to define aliases for commands. Each alias has a key and a value. The value can either be a single unit or a list of units, where a unit is either a command literal (e.g. bash expression) or a recursive reference to another alias.
Example: For instance, given the section
legend = [
{ key = 'cmd1', val = 'echo "command one"' },
{ key = 'cmd2', val = 'cmd1' },
{ key = 'cmd3', val = 'cmd2' },
{ key = 'cmd4', val = 'command four' },
{ key = 'all', val = ['cmd3', 'cmd4', 'echo hi'] },
]
Then the command
$ shrun --config=path/to/config all "echo cat"
Will run echo "command one"
, command four
, echo hi
and echo cat
concurrently. A picture is worth a thousand words:
$ shrun --config=examples/config.toml all "echo cat"
[Success][echo cat] 0 seconds
[Success][echo hi] 0 seconds
[Success][cmd1] 0 seconds
[Error][cmd4] 0 seconds: /bin/sh: line 1: four: command not found
[Finished] 0 seconds
Caution
Duplicate keys will cause a parse error to be thrown when loading. Cyclic keys are also disallowed, though these will only throw if you actually try to execute one (i.e. merely having cyclic definitions in the legend will not throw an error).
Arg: -i,--init STRING
Description: If given, init
is run before each command. That is, shrun --init "some logic" foo bar
is equivalent to shrun "some logic && foo" "some logic && bar"
.
Example:
$ shrun --init ". examples/bashrc" bash_function
[Success][bash_function] 0 seconds
[Finished] 0 seconds
vs.
$ shrun bash_function
[Error][bash_function] 0 seconds: /bin/sh: line 1: bash_function: command not found
[Finished] 0 seconds
Arg: -t, --timeout (NATURAL | STRING)
Description: The provided timeout must be either a raw integer (interpreted as seconds), or a "time string" e.g. 1d2m3h4s
, 3h20s
. All integers must be non-negative. If the timeout is reached, then all remaining commands will be cancelled.
Example:
$ shrun --timeout 4 "sleep 2" "sleep 6" "sleep 8"
[Success][sleep 2] 2 seconds
[Warn] Timed out, cancelling remaining commands: sleep 6, sleep 8
[Finished] 9 seconds
This is general logging config.
Arg: --common-log-key-hide
Description: By default, we display the key name from the legend file over the actual command that was run, if the former exists. This flag instead shows the literal command. Commands without keys are unaffected.
Example:
$ shrun --common-log-key-hide --config=examples/config.toml some-key
[Success][echo hi && sleep 2] 2 seconds
[Finished] 2 seconds
rather than the usual
$ shrun --config=examples/config.toml some-key
[Success][some-key] 2 seconds
[Finished] 2 seconds
Naturally, this does not affect commands that do not have a key (i.e. those not in a legend file). Also, if the commands are defined recursively, then the key name will be the final key.
Configuration for command logs, enabled by console-log.command
and/or file-logging
.
Arg: --command-log-buffer-length
Description: Max text length held by the log buffer, used in conjunction with --command-log-read-strategy block-line-buffer
. Defaults to 1,000 characters.
Example:
Note
In this example, the log 'hi' is printed even though it is not newline-terminated, because the --command-log-buffer-length 1
is exceeded (2 characters). On the other hand, the final log 'b' is not printed until the very end since it is within the buffer limit.
$ shrun --console-log-command --command-log-buffer-length 1 "printf hi && sleep 1 && printf b && sleep 2"
[Command][printf hi && sleep 1 && printf b && sleep 1] hi
[Timer] 1 second
Arg: --command-log-buffer-timeout
Description: Max time the log buffer will hold a log before flushing it, used in conjunction with --command-log-read-strategy block-line-buffer
. Defaults to 30 seconds.
Example:
Note
In this example, the logs 'hi' and 'b' are printed even though they are not newline-terminated, because the --command-log-buffer-timeout 1
is exceeded (1 second).
$ shrun --console-log-command --command-log-buffer-timeout 1 "printf hi && sleep 3 && printf b && sleep 1"
[Command][printf hi && sleep 3 && printf b && sleep 1] hi
[Timer] 1 second
$ shrun --console-log-command --command-log-buffer-timeout 1 "printf hi && sleep 3 && printf b && sleep 1"
[Command][printf hi && sleep 3 && printf b && sleep 1] b
[Timer] 3 seconds
Arg: --command-log-poll-interval NATURAL
Description: Non-negative integer that determines how quickly we poll commands for logs, in microseconds. A value of 0 is interpreted as infinite i.e. limited only by the CPU. Defaults to 10,000.
Warning
Note that lower values will increase CPU usage. In particular, 0 will max out a CPU thread.
Example:
$ shrun --command-log-poll-interval 100 --console-log-command "for i in {1..10}; do echo hi; sleep 1; done"
[Command][for i in {1..10}; do echo hi; sleep 1; done] hi
[Timer] 7 seconds
Arg: --command-log-read-size BYTES
Description: The max number of bytes in a single read when streaming command logs. Logs larger than --command-log-read-size
will be read in a subsequent read, hence broken across lines. The default is 16 kb
.
Example:
Note
In this example we also use --command-log-poll-interval 1_000_000
to slow down the reads, so that we can see acbde
and f
are indeed read separately. Ordinarily this would be too fast to see the difference.
$ shrun --console-log-command --command-log-read-size 5b --command-log-poll-interval 1_000_000 "echo abcdef && sleep 2"
[Command][echo abcdef && sleep 2] abcde
[Timer] 1 second
$ shrun --console-log-command --command-log-read-size 5b --command-log-poll-interval 1_000_000 "echo abcdef && sleep 2"
[Command][echo abcdef && sleep 2] f
[Timer] 2 seconds
Arg: --command-log-read-strategy (block | block-line-buffer)
Description: The block
strategy reads N
(--command-log-read-size
) bytes at a time, whereas block-line-buffer
also reads N
bytes at a time, but buffers newlines, for potentially nicer formatted file logs. By default, we only use block-line-buffer
when there is exactly one command. Otherwise we use block
. This option explicitly sets the strategy.
Warning
The block-line-buffer
strategy only makes sense when there is exactly one command. Otherwise we could easily mix up logs from different commands, leading to nonsense output.
Example:
Note
This is the previous example, but with --command-log-read-strategy block-line-buffer
enabled. Notice the entire 'abcdef' is printed, since 'abcd' is read first, buffered, then 'f\n' is read, and the buffer flushed.
$ shrun --console-log-command --command-log-read-size 5b --command-log-poll-interval 1_000_000 --command-log-read-strategy block-line-buffer "echo abcdef && sleep 2"
[Command][echo abcdef && sleep 2] abcdef
[Timer] 2 seconds
Config related to console logs.
Arg: --console-log-command
Description: The default behavior is to swallow logs for the commands themselves. This flag gives each command a console region in which its logs will be printed. Only the latest log per region is shown at a given time.
Note
When commands have complicated output, the logs can interfere with each other (indeed even overwrite themselves). We attempt to mitigate such situations: see Strip Control.
Example:
$ shrun --console-log-command "for i in {1..2}; do echo hi; sleep 1; done"
[Command][for i in {1..2}; do echo hi; sleep 1; done] hi
[Timer] 1 second
vs.
$ shrun "for i in {1..2}; do echo hi; sleep 1; done"
[Timer] 1 second
Note
Both the commands' stdout
and stderr
are treated the same, logged with the same formatting. This is because many shell programs perform redirection like echo ... >&2
(i.e. redirect stdout
to stderr
). Not only does this mean we need to take both if we do not want to skip any output, but it also means it does not make sense to try to differentiate the two anymore, as that information has been lost.
Practically speaking, this does not have much effect, just that if a command dies while --console-log-command
is enabled, then the final [Error] ...
output may not have the most relevant information. See --file-log
for details on investigating command failure.
Arg: --console-log-command-name-trunc NATURAL
Description: Non-negative integer that limits the length of commands/key-names in the console logs. Defaults to no truncation.
Example:
$ shrun --console-log-command-name-trunc 10 "for i in {1..3}; do echo hi; sleep 1; done"
[Success][for i i...] 3 seconds
[Finished] 3 seconds
Arg: --console-log-line-trunc (NATURAL | detect)
Description: Non-negative integer that limits the length of console logs. Can also be the string literal detect
, to detect the terminal size automatically. Defaults to no truncation.
Note
"log prefixes" (e.g. labels like [Success]
, timestamps) are counted towards total length, but are never truncated.
Example:
$ shrun --console-log-command --console-log-line-trunc 80 "echo 'some ridiculously long command i mean is this really necessary' && sleep 2"
[Command][echo 'some ridiculously long command i mean is this really necessary' && sleep 2] ...
[Timer] 1 second
Arg: --console-log-strip-control (all | smart | none)
Description: Control characters can wreak layout havoc, thus we include this option. all
strips all such chars. none
does nothing i.e. all chars are left untouched. The default smart
attempts to strip only the control chars that affect layout (e.g. cursor movements) and leaves others unaffected (e.g. colors). This has the potential to be the 'prettiest' as:
- Simple formatting is left intact.
- The layout should not be damaged.
Though it is possible to miss some chars. This option is experimental and subject to change.
Example:
Note: In the following examples, \033[35m
and \033[3D
are ansi escape codes. The former sets the text color to magenta, and the latter resets the cursor to the left by 3 places i.e. partially overwrites the previous characters. We also include the options --console-log-command --console-log-command-name-trunc 10
(show command logs and truncate command name to 10 chars) to make the output easier to read.
all
strips all control characters: \033
in this case. The means all special formatting / control will be omitted.
$ shrun --console-log-command --console-log-command-name-trunc 10 --console-log-strip-control all "echo -e ' foo \033[35m hello \033[3D bye '; sleep 2"
[Command][echo -e...] foo hello bye
[Timer] 1 second
none
leaves all control characters in place. In this case, we will apply both the text coloring (\033[35m
) and text overwriting (\033[3D
).
$ shrun --console-log-command --console-log-command-name-trunc 10 --console-log-strip-control none "echo -e ' foo \033[35m hello \033[3D bye '; sleep 2"
[Command][echo -e...] foo hel bye
[Timer] 1 second
smart
removes the control chars but leaves the text coloring, so we will have the magenta text but not overwriting.
$ shrun --console-log-command --console-log-command-name-trunc 10 --console-log-strip-control smart "echo -e ' foo \033[35m hello \033[3D bye '; sleep 2"
[Command][echo -e...] foo hello bye
[Timer] 1 second
Arg: --console-log-timer-format (digital_compact | digital_full | prose_compact | prose_full)
Description: How to format the timer. Defaults to prose_compact
e.g. 2 hours, 3 seconds
.
Example:
$ shrun --console-log-timer-format digital_compact "sleep 2"
[Timer] 01
$ shrun --console-log-timer-format digital_full "sleep 2"
[Timer] 00:00:00:01
$ shrun --console-log-timer-format prose_compact "sleep 2"
[Timer] 1 second
$ shrun --console-log-timer-format prose_full "sleep 2"
[Timer] 0 days, 0 hours, 0 minutes, 1 second
Config related to file logs.
Arg: -f, --file-log (default | PATH)
Description: If a path is supplied, all logs will additionally be written to the supplied file. Furthermore, command logs will be written to the file irrespective of --console-log-command
. Console logging is unaffected. This can be useful for investigating command failures. If the string default
is given, then we write to the XDG state directory e.g. ~/.local/state/shrun/shrun.log
.
Example:
$ shrun --file-log=out.log "sleep 2" "bad" "for i in {1..3}; do echo hi; sleep 1; done"
[Error][bad] 0 seconds: /bin/sh: line 1: bad: command not found
[Success][sleep 2] 2 seconds
[Success][for i in {1..3}; do echo hi; sleep 1; done] 3 seconds
[Finished] 3 seconds
$ cat out.log
[2022-12-12 23:17:55][Command][for i in {1..3}; do echo hi; sleep 1; done] hi
[2022-12-12 23:17:55][Command][bad] /bin/sh: line 1: bad: command not found
[2022-12-12 23:17:55][Error][bad] 0 seconds: /bin/sh: line 1: bad: command not found
[2022-12-12 23:17:56][Command][for i in {1..3}; do echo hi; sleep 1; done] hi
[2022-12-12 23:17:57][Success][sleep 2] 2 seconds
[2022-12-12 23:17:57][Command][for i in {1..3}; do echo hi; sleep 1; done] hi
[2022-12-12 23:17:58][Success][for i in {1..3}; do echo hi; sleep 1; done] 3 seconds
[2022-12-12 23:17:58][Finished] 3 seconds
Arg: --file-log-command-name-trunc NATURAL
Description: Like --console-log-command-name-trunc
, but for --file-logs
.
Example:
$ shrun --file-log out.log --file-log-command-name-trunc 10 "for i in {1..3}; do echo hi; sleep 1; done"
[Success][for i in {1..3}; do echo hi; sleep 1; done] 3 seconds
[Finished] 3 seconds
$ cat out.log
[2024-04-23 01:05:21][Command][for i i...] Starting...
[2024-04-23 01:05:21][Command][for i i...] hi
[2024-04-23 01:05:22][Command][for i i...] hi
[2024-04-23 01:05:23][Command][for i i...] hi
[2024-04-23 01:05:24][Success][for i i...] 3 seconds
[2024-04-23 01:05:24][Finished] 3 seconds
Arg: --file-log-delete-on-success
Description: If --file-log
is active, deletes the file on a successful exit. Does not delete the file if shrun exited via failure.
Example:
$ shrun --file-log del-on-success.log --file-log-delete-on-success "sleep 2"
[Success][sleep 2] 2 seconds
[Finished] 2 seconds
$ cat del-on-success.log
cat: del-on-success.log: No such file or directory
vs.
$ shrun --file-log del-on-success.log --file-log-delete-on-success bad "sleep 2"
[Error][bad] 0 seconds: /bin/sh: line 1: bad: command not found
[Success][sleep 2] 2 seconds
[Finished] 2 seconds
$ cat del-on-success.log
[2024-04-23 01:05:21][Command][bad] Starting...
[2024-04-23 01:05:21][Command][sleep 2] Starting...
[2024-04-23 01:05:21][Error][bad] 0 seconds: /bin/sh: line 1: bad: command not found
[2024-04-23 01:05:24][Success][sleep 2] 2 seconds
[2024-04-23 01:05:24][Finished] 2 seconds
Arg: --file-log-line-trunc
Description: Like --console-log-line-trunc
, but for file logs.
Example:
$ shrun --file-log line-trunc.log --file-log-line-trunc 120 "echo 'some ridiculously long command i mean is this really necessary' && sleep 2"
[Success][sleep 2] 2 seconds
[Finished] 2 seconds
$ cat line-trunc.log
[2024-04-23 01:05:21][Command][echo 'some ridiculously long command i mean is this really necessary' && sleep 2] Star...
[2024-04-23 01:05:22][Command][echo 'some ridiculously long command i mean is this really necessary' && sleep 2] som...
[2024-04-23 01:05:24][Success][echo 'some ridiculously long command i mean is this really necessary' && sleep 2] 2 se...
[2024-04-23 01:05:24][Finished] 2 seconds
Arg: --file-log-mode (append | rename | write)
Description: Mode in which to open the log file. Can be write
(the default), append
, or rename
. The rename
option will rename the requested log file if there is a collision e.g. -f shrun.log
will become shrun (1).log
.
Arg: --file-log-size-mode (warn BYTES | delete BYTES | nothing)
Description: Sets a threshold for the file log size, upon which we either print a warning or delete the file, if it is exceeded. The BYTES
should include the value and units e.g. warn 10 mb
, warn 5 gigabytes
, delete 20.5B
. Defaults to warning at 50 mb
. Can be disabled with "nothing".
Exmaple:
$ shrun --file-log size_mode_warn.log --file-log-size-mode "warn 1 b" "sleep 2"
Warning: log file 'size_mode_warn.log' has size: 11.00 b, but specified threshold is: 1.00 b.
[Success][sleep 2] 2 seconds
[Finished] 2 seconds
$ shrun --file-log size_mode_warn.log --file-log-size-mode nothing "sleep 2"
[Success][sleep 2] 2 seconds
[Finished] 2 seconds
Arg: --file-log-strip-control (all | smart | none)
Description: --console-log-strip-control
for file logs created with --file-log
. Defaults to all.
These options configure shrun
to send off desktop notifications for certain actions i.e. a command finishes or shrun itself finishes.
Arg: --notify-action (final | command | all)
Description: Sends notifications for various actions. final
sends off a notification when shrun
itself finishes whereas command
sends one off each time a command finishes. all
implies final
and command
.
Example:
$ shrun --notify-system dbus --notify-action final "sleep 5"
Arg: --notify-system (dbus | notify-send | apple-script)
Description: The system used for sending notifications. dbus
and notify-send
are available on linux, whereas apple-script
is available for osx.
Example:
$ shrun --notify-system dbus "sleep 5"
Arg: --notify-timeout (never | NAT)
Description: When to timeout success notifications. Defaults to 10 seconds.
Example:
$ shrun --notify-system dbus --notify-timeout never "sleep 5"
Note
Timeouts are subject to the whims of the underlying notification system e.g. some notification systems ignore the timeout entirely. Also, "error notifications" (i.e. shrun
or command failures) are sent with urgency = critical
where supported, thus may not timeout at all, per FDO's specification.
Arg: --default-config
Description: Writes a default configuration to stdout
.