The terminal subsystem provides interactive shell sessions tunneled over MQTT. Each session spawns a bash PTY (pseudo-terminal) on the agent host, and bidirectional I/O is carried in SenML messages. This enables remote terminal access from Magistrala.
The agent maintains a map of active terminal sessions. Each session:
- Spawns a
bashprocess attached to a PTY - Reads PTY output and publishes it to the agent's response topic under
term/<uuid> - Accepts input bytes via MQTT and writes them to the PTY
- Has an idle timeout — if no input or output occurs within the timeout, the session closes automatically
open char (write) char (write) timeout / close
──────► ─────────────────► ─────────────────► ─────────────────►
spawn write to PTY, write to PTY, session removed,
bash read PTY output, read PTY output, PTY closed
publish to MQTT publish to MQTT
All terminal commands use the term subsystem. The vs field is base64-encoded and contains a comma-separated payload: <command>[,<arg>].
Base64 payload: open
Request:
[{ "bn": "<uuid>:", "n": "term", "vs": "b3Blbg==" }](b3Blbg== = base64 of open)
Base64 payload: char,<input-bytes>
Request:
[{ "bn": "<uuid>:", "n": "term", "vs": "Y2hhcixscw==" }](Y2hhcixscw== = base64 of char,ls)
Base64 payload: close
Request:
[{ "bn": "<uuid>:", "n": "term", "vs": "Y2xvc2U=" }](Y2xvc2U= = base64 of close)
Output from the PTY is published as SenML on the control response topic under term/<uuid>:
[{ "bn": "<uuid>:", "n": "term", "vs": "<output-text>", "t": ... }]| Variable | Default | Description |
|---|---|---|
MG_AGENT_TERMINAL_SESSION_TIMEOUT |
60s |
Idle timeout for terminal sessions. After this duration with no I/O, the session closes automatically. |
mosquitto_pub \
-h <mqtt-host> -p 1883 \
-u <gateway-id> -P <gateway-secret> --id "cfg-$(date +%s)" \
-t "m/<tenant-id>/c/<commands-channel-id>/req" \
-m '[{"bn":"req-1:", "n":"config", "vs":"set,terminal_session_timeout,120s"}]'| Direction | Topic | QoS | Description |
|---|---|---|---|
| Cloud → Agent | m/<tenant-id>/c/<ctrl-chan>/req |
1 | Terminal commands (term subsystem) |
| Agent → Cloud | m/<tenant-id>/c/<ctrl-chan>/res/term/<uuid> |
1 | PTY output for a specific session |
Open a separate terminal to watch session output:
mosquitto_sub \
-h <mqtt-host> -p 1883 \
-u <gateway-id> -P <gateway-secret> \
-t "m/<tenant-id>/c/<commands-channel-id>/res/term/#" \
-vExpected output:
m/<tenant-id>/c/<commands-channel-id>/res/term/term-1781257973 [{"bn":"term-1781257973","n":"term","t":1781257978.7125685,"vs":"/ # \u001b[6n"}]
UUID="term-$(date +%s)"
# "open" → base64 = b3Blbg==
mosquitto_pub \
-h <mqtt-host> -p 1883 \
-u <gateway-id> -P <gateway-secret> --id "$UUID" \
-t "m/<tenant-id>/c/<commands-channel-id>/req" \
-m "[{\"bn\":\"$UUID:\", \"n\":\"term\", \"vs\":\"b3Blbg==\"}]"UUID="term-1781257973"
# "char,ls\n" → base64 = Y2hhcixscwo=
mosquitto_pub \
-h <mqtt-host> -p 1883 \
-u <gateway-id> -P <gateway-secret> --id "$UUID" \
-t "m/<tenant-id>/c/<commands-channel-id>/req" \
-m "[{\"bn\":\"$UUID:\", \"n\":\"term\", \"vs\":\"Y2hhcixscwo=\"}]"The subscriber terminal will show the ls output followed by a new shell prompt.
UUID="term-1749552000"
# "char,uname -a\n"
echo -n "char,uname -a" | base64
# Y2hhcix1bmFtZSAtYQ==
mosquitto_pub \
-h <mqtt-host> -p 1883 \
-u <gateway-id> -P <gateway-secret> --id "$UUID" \
-t "m/<tenant-id>/c/<commands-channel-id>/req" \
-m "[{\"bn\":\"$UUID:\", \"n\":\"term\", \"vs\":\"Y2hhcix1bmFtZSAtYQo=\"}]"UUID="term-1749552000"
# "close" → base64 = Y2xvc2U=
mosquitto_pub \
-h <mqtt-host> -p 1883 \
-u <gateway-id> -P <gateway-secret> --id "$UUID" \
-t "m/<tenant-id>/c/<commands-channel-id>/req" \
-m "[{\"bn\":\"$UUID:\", \"n\":\"term\", \"vs\":\"Y2xvc2U=\"}]"# Encode a shell command for the terminal subsystem
echo -n "char,ls -la" | base64
# Y2hhcixscyAtbGE=
# Encode with newline (to actually execute the command)
printf "char,ls -la\n" | base64
# Y2hhcixscyAtbGEKOpen http://localhost:9999, navigate to the Terminal page, and start an interactive shell session. The web-based terminal provides a full-featured VT100/VT220/xterm emulator with proper ANSI escape sequence rendering, native text selection, copy/paste, and browser find. The terminal automatically reconnects if the connection drops.