/mqtt-shell

A shell like command line interface for mqtt written in go.

Primary LanguageGoMIT LicenseMIT

Go

mqtt-shell

A shell like command line interface for mqtt written in go. With it, you can easily subscribe and publish mqtt topics. It is also possible to pass through the incoming messages to external applications. Such like piping in shells!

Features:

  • Colored output
  • Subscribe (multiple) mqtt topics
  • Publish messages to mqtt topic
  • Pipe the incoming messages to external applications
  • Command history (such like other shells)
  • Configuration support via yaml-files
    • so you can use handle multiple environments easily
  • Macro support

Get the Binary

You can build it on your own (you will need golang installed):

go build -a -installsuffix cgo ./cmd/mqtt-shell/

Or you can download the release binaries: here

Or for Arch-Linux you cann install the AUR-Package mqtt-shell

yay -S mqtt-shell

Usage

To see all command options, simple type

./mqtt-shell -h

Usage of ./mqtt-shell:
  -b string
    	The broker URI. ex: tcp://127.0.0.1:1883
  -c string
    	The ClientID (default "mqtt-shell")
  -ca string
    	MQTT ca file path (if tls is used)
  -cb value
    	This color(s) will not be used
  -cmd value
    	The command(s) which should be executed at the beginning
  -cs
    	Indicating that no messages saved by the broker for this client should be delivered (default true)
  -e string
    	The environment which should be used
  -ed string
    	The environment directory (default "~/.mqtt-shell")
  -hf string
    	The history file path (default "~/.mqtt-shell/.history")
  -m value
    	The macro file(s) which should be loaded (default ~/.mqtt-shell/macros.yml)
  -ni
    	Should this shell be non interactive. Only useful in combination with 'cmd' option
  -p string
    	The password
  -pq int
    	The default Quality of Service for publishing 0,1,2 (default 1)
  -sp string
    	The prompt of the shell (default "\\033[36m»\\033[0m ")
  -sq int
    	The default Quality of Service for subscription 0,1,2
  -u string
    	The username

Setting files

All options can be written in separate environment files (one per environment) or for global settings in the .global.yml file. These files must be stores inside the shel-config directory (~/.mqtt-shell).

Environment configurations

You can create yaml files where you can configure predefined configuration. This can be helpful for different mqtt environments. This files must be stored in the environment directory (by default ~/.mqtt-shell/).

For example:

# example.yml

broker: tls://127.0.0.1:8883
ca: /tmp/my.ca
subscribe-qos: 1
publish-qos: 2
username: user
password:  secret
client-id: my-mqtt-shell
clean-session: true
commands: 
  - sub #
non-interactive: false
history-file: /home/user/.mqtt-shell/history
prompt: "\033[36mmsh>\033[0m "
macros:
  my-macro:
    description: Awesome description of my macro
    arguments:
      - message
    commands:
      - pub test $1
color-blacklist:
  - "38;5;237"
$ ./mqtt-shell -e example

multiline publishing

If you want to publish a multiline message to topic:

pub test/topic <<EOF
This is
a multiline
message
EOF

This is also useful if you don't want to handle argument escaping:

pub test/topic <<EOF
{"key": "value"}EOF

command chaining

One powerful feature of this shell is to chain incoming messages to external applications. It works like the other unix shells:

This will pass through all incoming messages in topic test/topic to grep

sub test/topic | grep "Message"

stderr forwarding

If you want to push stdout and stderr to the stdin of the next application:

sub test/topic | myExternalApplication |& grep "Message"

long term applications

Normally the external applications will be started on each incoming Message. If you want to stream all incoming messages to a single started application:

sub test/topic | grep "Message" &

file redirection

If you want to write all incoming messages into files:

sub test/topic >> /tmp/test.msg

only last incoming message

If you want to write only the latest incoming message to file:

sub test/topic > /tmp/last.msg

Macros

Macros can be a list of commands which should be executed. Or it can be a more complex but more powerful script. Macros can have their own arguments. They can be defined in the environment file (~/.mqtt-shell/my-env.yml), the global settings (~/.mqtt-shell/.global.yml) or the global macro file (~/.mqtt-shell/.macros.yml)

Macros - list of commands

# ~/.mqtt-shell/.macros.yml

my-macro:
  description: Awesome description of my macro
  arguments:
    - message
  varargs: true
  commands:
    - pub test $1

Then you can use it in the mqtt-shell:

> sub test
> my-macro "Message#1" "Message#2"
test | Message#1
test | Message#2

Macros - a complex script

The golang text templating is used for the scripts. The macro arguments can be read by Arg following by the number of the argument. So for the first argument: Arg1 and for the second Arg2 and so on.

Furthermore there are two custom functions available:

name argument description example
exec <cmdLine> Run the given command and return the result. You can also use pipes! exec "date | cut -d\ -f1"
log <format string> [<argument>, ...] Write the given content to the shell stdout. log "Argument#1: %s" .Arg1
# ~/.mqtt-shell/.macros.yml

my-macro:
  description: Awesome description of my macro
  arguments:
    - message
  varargs: true
  script: |-
    {{ log "Publish to topic" }}
    pub test {{ .Arg1 }} {{ exec "date" }}

Then you can use it in the mqtt-shell:

> sub test
> my-macro "Message#1" "Message#2"
test | Message#1 So 15. Aug 16:15:00 CEST 2021
test | Message#2 So 15. Aug 16:15:00 CEST 2021

Color output

This shell is able to write colored output. Each time a new subscription is made, the messages for that subscription will have a colored prefix. Each subscription (not topic!) should have an own color schema. Internally the shell will have a pool with color codes. Each time a new subscription was made, the next color will get from that pool. After the pool is exhausted, the color choosing will start again. The color pool can be shown with the color command in the shell.

If you want to disable some colors, you have to put them in your yaml config file(s). Or use the option -cb for the current session.

Why chained applications will not show any color?

Because the mqtt-shell itself will start the chained application, the application can not detect if it operates on a tty. So normally the applications will think that their stdin is no tty. Most of the application have an option to force print the color codes. For example grep:

sub test/topic | grep --color=always Message