Skip to content

Latest commit

 

History

History
798 lines (567 loc) · 33.2 KB

File metadata and controls

798 lines (567 loc) · 33.2 KB

Configuration

Table of Contents


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 config.toml for a description of the toml file.

Tip

Some options allow an off value, which disables toml configuration for that field. For example, --console-log-command off will disable command logging, regardless of the toml settings.

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.

Core Functionality

Config

Arg: -c, --config (PATH | off)...

Description: Path(s) to TOML config file(s). This argument can be given multiple times, in which case all keys are merged. When there is a conflict, the right-most config wins. The legends are also merged, with the same right-bias for conflicting keys. The string off disables all config files to its left. Finally, we also search in specific locations automatically. These are:

  • <XDG_config>/shrun/config.toml
  • ./.shrun.toml
  • ./shrun.toml

These files are considered 'left' of any configs explicitly given with --config, hence disabed with off.

Examples can be found in examples.

Legend

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|0|1|3] 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).

Edges

Arg: --edges (EDGES_STR | && | || | ;; | off)

Description: Comma-separated list, specifying command dependencies, based on their order. There are three edge types:

  • and: cmd1 & cmd2, runs cmd2 iff cmd1 succeeds.
  • or: cmd1 | cmd2, runs cmd2 iff cmd1 fails.
  • any: cmd1 ; cmd2, runs cmd2 iff cmd1 finishes.

The literals are equivalent to placing edges between all commands e.g. && puts an and-edge between all commands.

Example:

# Normally, the 'sleep 1' command would start and finish first
$ shrun --init --edges '1 & 3, 2 & 3' "sleep 2" "sleep 2" "sleep 1" "sleep 3"
[Success][sleep 2] 2 seconds
[Success][sleep 2] 2 seconds
[Success][sleep 3] 3 seconds
[Success][sleep 1] 1 seconds
[Finished][0|0|0|4] 3 seconds

Tip

See the faq for more.

Init

Arg: -i,--init (STRING | off)

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|0|0|1] 0 seconds

vs.

$ shrun bash_function
[Error][bash_function] 0 seconds: /bin/sh: line 1: bash_function: command not found
[Finished][0|0|1|0] 0 seconds

Legend Keys Cache

Arg: --legend-keys-cache (add | clear | write | off)

Description: Shrun allows saving legend keys from the current config file so that we can get tab-completions on the next run.

  • add: The default. Combines keys from this run with the prior run(s).
  • clear: Deletes the keys file, if it exists.
  • write: Saves keys from this run only.

Example:

Config files:

# config1.toml
legend = [
  { key = 'short', val = 'same as config.toml' },
  { key = 'cfg1_key_1', val = 'val 1' },
  { key = 'cfg1_key_2', val = 'val 1' }
]

# config2.toml
legend = [
  { key = 'short', val = 'same as config.toml' },
  { key = 'cfg2_key_1', val = 'val 2' },
  { key = 'cfg2_key_2', val = 'val 2' }
]

add: saves keys from config1.toml:

$ shrun -c config1.toml --legend-keys-cache add "sleep 1"
[Success][sleep 1] 1 second
[Finished][0|0|0|1] 1 second
$ cat ~/.local/state/shrun/legend-keys.txt
cfg1_key_1
cfg1_key_2
short

add: Adds keys from config2.toml:

$ shrun -c config2.toml --legend-keys-cache add "sleep 1"
[Success][sleep 1] 1 second
[Finished][0|0|0|1] 1 second
$ cat ~/.local/state/shrun/legend-keys.txt
cfg1_key_1
cfg1_key_2
cfg2_key_1
cfg2_key_2
short

write: Overwrites keys with config2.toml:

$ shrun -c config2.toml --legend-keys-cache write "sleep 1"
[Success][sleep 1] 1 second
[Finished][0|0|0|1] 1 second
$ cat ~/.local/state/shrun/legend-keys.txt
cfg2_key_1
cfg2_key_2
short

off: Does nothing:

$ shrun -c config1.toml --legend-keys-cache off "sleep 1"
[Success][sleep 1] 1 second
[Finished][0|0|0|1] 1 second
$ cat ~/.local/state/shrun/legend-keys.txt
cfg2_key_1
cfg2_key_2
short

clear: Removes all keys:

$ shrun -c config1.toml --legend-keys-cache clear "sleep 1"
[Success][sleep 1] 1 second
[Finished][0|0|0|1] 1 second
$ cat ~/.local/state/shrun/legend-keys.txt
cat: legend-keys.txt: No such file or directory

Timeout

Arg: -t, --timeout (NATURAL | STRING | off)

Description: Non-negative integer setting a timeout. Can either be a raw number (interpreted as seconds), or a "time string" e.g. 1d2h3m4s or 2h3s. Defaults to no timeout.

Example:

$ shrun --timeout 4 "sleep 2" "sleep 6" "sleep 8"
[Success][sleep 2] 2 seconds
[Warn] Timed out
[Warn] Attempting to cancel:
  - sleep 6
  - sleep 8
[Finished][0|2|0|1] 5 seconds

Logging

Common Logging

This is general logging config.

Debug

Arg: --common-log-debug (on | off)

Description: Enables additional debug logs.

Example:

$ shrun --common-log-debug "sleep 2"
[Debug][sleep 2] Command: 'ShellCommand "sleep 2"'
[Success][sleep 2] 2 seconds
[Finished][0|0|0|1] 2 seconds

Key Hide

Arg: --common-log-key-hide (on | off)

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][0|0|0|1] 2 seconds

rather than the usual

$ shrun --config=examples/config.toml some-key
[Success][some-key] 2 seconds
[Finished][0|0|0|1] 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.

Command Logging

Configuration for command logs, enabled by console-log.command and/or file-logging.

Buffer Length

Arg: --command-log-buffer-length NATURAL

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 --command-log-buffer-length 1 "printf hi && sleep 1 && printf b && sleep 2"
[Command][printf hi && sleep 1 && printf b && sleep 1] hi
[Status][0|1|0|0] 1 second

Buffer Timeout

Arg: --command-log-buffer-timeout (NATURAL | STRING)

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 --command-log-buffer-timeout 1 "printf hi && sleep 3 && printf b && sleep 1"
[Command][printf hi && sleep 3 && printf b && sleep 1] hi
[Status][0|1|0|0] 1 second
$ shrun --command-log-buffer-timeout 1 "printf hi && sleep 3 && printf b && sleep 1"
[Command][printf hi && sleep 3 && printf b && sleep 1] b
[Status][0|1|0|0] 3 seconds

Poll Interval

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 "for i in {1..10}; do echo hi; sleep 1; done"
[Command][for i in {1..10}; do echo hi; sleep 1; done] hi
[Status][0|1|0|0] 7 seconds

Read Size

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 --command-log-read-size 5b --command-log-poll-interval 1_000_000 "echo abcdef && sleep 2" 
[Command][echo abcdef && sleep 2] abcde
[Status][0|1|0|0] 1 second
$ shrun --command-log-read-size 5b --command-log-poll-interval 1_000_000 "echo abcdef && sleep 2" 
[Command][echo abcdef && sleep 2] f
[Status][0|1|0|0] 2 seconds

Read Strategy

Arg: --command-log-read-strategy (block | block-line-buffer)

Description: Strategy for reading command logs. block-line-buffer is allowed (and the default) as long as we do not have multiple commands with file logging. In that scenario, we use block.

  • block: Reads N (--command-log-read-size) bytes at a time.
  • block-line-buffer: Also reads N bytes at a time, but buffers newlines, for potentially nicer formatted logs.

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 --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
[Status][0|1|0|0] 2 seconds

Console Logging

Config related to console logs.

Command Log

Arg: --console-log-command (on | off)

Description: This flag gives each command a console region in which its logs will be printed, as opposed to swallowing command logs. Only the latest log per region is shown at a given time. Defaults to on.

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 "for i in {1..2}; do echo hi; sleep 1; done"
[Command][for i in {1..2}; do echo hi; sleep 1; done] hi
[Status][0|1|0|0] 1 second

vs.

$ shrun --console-log-command off "for i in {1..2}; do echo hi; sleep 1; done"
[Status][0|1|0|0] 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.

Command Name Truncation

Arg: --console-log-command-name-trunc (NATURAL | off)

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][0|0|0|1] 3 seconds

Line Truncation

Arg: --console-log-line-trunc (NATURAL | detect | off)

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 detect if --console-log-command is on.

Note

"log prefixes" (e.g. labels like [Success], timestamps) are counted towards total length, but are never truncated.

Example:

$ shrun --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] ...
[Status][0|1|0|0] 1 second

Strip Control

Arg: --console-log-strip-control (all | smart | off)

Description: Control characters can wreak layout havoc, hence this option for stripping such characters.

  • all: Strips all such chars.
  • smart: The default. 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' though it is possible to miss some chars.

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-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
[Status][0|1|0|0] 1 second

off 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-name-trunc 10 --console-log-strip-control off "echo -e ' foo \033[35m hello \033[3D bye '; sleep 2"
[Command][echo -e...] foo  hel bye
[Status][0|1|0|0] 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-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
[Status][0|1|0|0] 1 second

Timer Format

Arg: --console-log-timer-format TIME_FMT

Description: How to format the timer. Options:

  • digital_compact: e.g. 02:00:03.
  • digital_full: e.g. 00:02:00:03.
  • prose_compact: The default e.g. 2 hours, 3 seconds.
  • prose_full: e.g. 0 days, 2 hours, 0 minutes, 3 seconds.

Example:

$ shrun --console-log-timer-format digital_compact "sleep 2"
[Status][0|1|0|0] 01
$ shrun --console-log-timer-format digital_full "sleep 2"
[Status][0|1|0|0] 00:00:00:01
$ shrun --console-log-timer-format prose_compact "sleep 2"
[Status][0|1|0|0] 1 second
$ shrun --console-log-timer-format prose_full "sleep 2"
[Status][0|1|0|0] 0 days, 0 hours, 0 minutes, 1 second

File Logging

Config related to file logs.

File Log

Arg: -f, --file-log (default | PATH | off)

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][0|0|1|2] 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][0|0|1|2] 3 seconds

File Command Name Truncation

Arg: --file-log-command-name-trunc (NATURAL | off)

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][0|0|0|1] 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][0|0|0|1] 3 seconds

File Delete On Success

Arg: --file-log-delete-on-success (on | off)

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 on "sleep 2"
[Success][sleep 2] 2 seconds
[Finished][0|0|0|1] 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 on bad "sleep 2"
[Error][bad] 0 seconds: /bin/sh: line 1: bad: command not found
[Success][sleep 2] 2 seconds
[Finished][0|0|1|1] 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][0|0|1|1] 2 seconds

Tip

This option allows for a nice workflow with automatic file logging i.e. setting the config:

[file-log]
path = "shrun.log"
delete-on-success = "on"

If the command succeeds we do not leave any log files around, but if it fails, we have an easy way to investigate.

File Line Truncation

Arg: --file-log-line-trunc (NATURAL | detect | off)

Description: Like --console-log-line-trunc, but for file logs. Defaults to off.

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][0|0|0|1] 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][0|0|0|1] 2 seconds

File Log Mode

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.

File Log Size Mode

Arg: --file-log-size-mode (delete BYTES | warn BYTES | off)

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.

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][0|0|0|1] 2 seconds
$ shrun --file-log size_mode_warn.log --file-log-size-mode off "sleep 2"
[Success][sleep 2] 2 seconds
[Finished][0|0|0|1] 2 seconds

File Log Strip Control

Arg: --file-log-strip-control (all | smart | off)

Description: --console-log-strip-control for file logs created with --file-log. Defaults to all.

Notifications

These options configure shrun to send off desktop notifications for certain actions i.e. a command finishes or shrun itself finishes.

Notify Action Complete

Arg: --notify-action-complete (all | command | final | off)

Description: Sends notifications for 'complete' actions.

  • all: Implies final and command.
  • command: Sends off a notification for each command that finishes.
  • final: Sends off a single notification when shrun itself finishes.

Example:

$ shrun --notify-system dbus --notify-action-complete final "sleep 5"

Notify Action Start

Arg: --notify-action-start (on | off)

Description: Sends notifications for 'start' actions.

Example:

$ shrun --notify-system dbus --notify-action-start on "sleep 5"

Notify System

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"

Notify Timeout

Arg: --notify-timeout (NATURAL | off)

Description: When to timeout success notifications. Defaults to 10 seconds.

Example:

$ shrun --notify-system dbus --notify-timeout off "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.

Miscellaneous

Default Config

Arg: --default-config

Description: Writes a default configuration to stdout.

Dry Run

Arg: --dry-run

Description: Prints the configuration and commands that would be run to stdout, then exits.