Build a minimal serial console server. The goals are:
minimal resource requirements: runnable on a Raspberry Pi Zero
reduce the number and size of dependencies
server: sredird, daemontools, unixexec, xmppipe
client: picocom
Note: the examples below install extra tools for logging.
proxy serial ioctl requests over ssh using RFC2217
controlled using XMPP
apt install daemontools
Create the service directory structure for daemontools:
service/
├── consolebot
│ └── run
├── console@host1
│ ├── log
│ │ └── run
│ └── run
├── console@host2
│ ├── log
│ │ └── run
│ └── run
└── xmpp
└── run
Each serial console runs as a daemontools managed Unix process.
svscan /home/console/service
├─supervise console@host1
│ └─unixexec /tmp/sredird/console@host1 hexlog none sredird -t 900 5 ...
├─supervise log
│ └─tscat -o 3 console@host1
├─supervise console@host2
│ └─unixexec /tmp/sredird/console@host2 hexlog none sredird -t 900 5...
├─supervise log
│ └─tscat -o 3 console@host2
├─supervise xmpp
│ └─xmppipe -o [email protected]
└─supervise consolebot
└─run ./run
#!/bin/bash
umask 077
mkdir -p /tmp/sredird
exec 2>&1
exec unixexec /tmp/sredird/console@getpid \
hexlog none \
sredird -t 900 5 /dev/console@getpid
#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail
if [ ! -p "/tmp/sredird/monitor/stdin" ] || [ ! -p "/tmp/sredird/monitor/stdout" ]; then
exit 1
fi
SERVICE="$(basename $(dirname $PWD))"
exec >/tmp/sredird/monitor/stdin
exec tscat -o 3 "$SERVICE"
#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail
shopt -s nullglob
umask 077
export XMPPIPE_PASSWORD="password"
export XMPPIPE_USERNAME="[email protected]"
TMPDIR="/tmp/sredird/monitor"
mkdir -p "$TMPDIR"
in="$TMPDIR/stdin"
out="$TMPDIR/stdout"
mkfifo "$in" 2>/dev/null || true
mkfifo "$out" 2>/dev/null || true
exec <"$in"
exec >"$out"
exec xmppipe -o [email protected]
#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail
shopt -s nullglob
umask 077
export SERVICE="$HOME/service"
TMPDIR="/tmp/sredird/monitor"
in="$TMPDIR/stdin"
out="$TMPDIR/stdout"
if [ ! -p "$in" ] || [ ! -p "$out" ]; then
exit 0
fi
exec <"$out"
exec >"$in"
decode() {
printf '%b' "${1//%/\\x}"
}
CODE='```'
export DEBUG=0
while IFS=: read stanza type from to body; do
case "$stanza" in
m) ;;
*) continue ;;
esac
USER="$(decode "${from#*/}")"
MSG="$(decode "$body")"
case $MSG in
h) ;&
help)
cat <<EOF
_Usage_
i *console* : display console session information
m *console* : monitor console session
status : display status of all consoles
t : terminate all consoles
t *console* : terminate console
EOF
;;
t)
lsof -t /dev/console@* | xargs --no-run-if-empty kill
;;
't '[a-z]*)
DEV="${MSG##* }"
if [ ! -S "/tmp/sredird/console@${DEV}" ]; then
echo "Invalid console: $DEV"
continue
fi
lsof -t "/dev/console@${DEV}" | xargs --no-run-if-empty kill
;;
'm '[a-z]*)
DEV="${MSG##* }"
if [ ! -S "/tmp/sredird/console@${DEV}" ]; then
echo "Invalid console: ${DEV}"
continue
fi
lsof -t "/dev/console@${DEV}" |
xargs --no-run-if-empty xargs ps -o ppid= |
xargs --no-run-if-empty kill -USR2
;;
status)
cat <<EOF
**Services**
$CODE
$(cd $SERVICE && svstat console@*)
$CODE
EOF
;&
i) ;&
I)
cat <<'EOF'
**Consoles**
EOF
for c in /dev/console@*; do
cat <<EOF
*$c*
$CODE
$(lsof "$c" || echo "no user")
$CODE
EOF
done
;;
'I '[a-z]*) ;&
'i '[0-9]*)
DEV="${MSG##* }"
if [ ! -S "/tmp/sredird/console@${DEV}" ]; then
echo "Invalid console: ${DEV}"
continue
fi
cat <<EOF
$CODE
$(lsof "/dev/console@${DEV}")
$CODE
EOF
;;
exit)
echo "exiting ..."
exit 0
;;
*)
if [[ $MSG =~ ^[[:space:]]*$ ]]; then
continue
fi
echo "Unknown command: $MSG" ;;
esac
done
Patch the Makefile to enable RFC2217 support:
git clone https://github.com/npat-efault/picocom.git
git checkout -t origin/rfc2217
patch -p1 < Makefile.patch
make
diff --git a/Makefile b/Makefile
index 75f3fdb..234386d 100644
--- a/Makefile
+++ b/Makefile
@@ -46,9 +46,9 @@ linenoise-1.0/linenoise.o : linenoise-1.0/linenoise.c linenoise-1.0/linenoise.h
#CPPFLAGS += -DNO_CUSTOM_BAUD
## Comment these in to enable RFC2217 support
-#CPPFLAGS += -DUSE_RFC2217
-#OBJS += tn2217.o
-#tn2217.o : tn2217.c tn2217.h tncomport.h fdio.h termint.h term.h
+CPPFLAGS += -DUSE_RFC2217
+OBJS += tn2217.o
+tn2217.o : tn2217.c tn2217.h tncomport.h fdio.h termint.h term.h
## Comment this IN to remove help strings (saves ~ 4-6 Kb).
#CPPFLAGS += -DNO_HELP
Host consoleserver
RequestTTY no
ExitOnForwardFailure yes
# /dev/console@host1
LocalForward 127.123.1.1:10023 /tmp/sredird/console@host1
# /dev/console@host2
LocalForward 127.123.2.1:10023 /tmp/sredird/console@host2
ssh -fNT consoleserver
alias c-host1="picocom --telnet --baud 38400 127.123.1.1,10023"
alias c-host2="picocom --telnet --baud 38400 127.123.2.1,10023"
(markdown)