/dev/posts/

Terminal read-only live sharing

Published:

Updated:

Live sharing a terminal session to another (shared) host over SSH in read-only mode.

Update: 2017-05-06 add broadcastting over the web with node-webterm

TLDR

#!/bin/sh

host="$1"

file=script.log
touch "$file"
tail -f $file | ssh $host 'cat > script.log' &
script -f "$file"
kill %1
ssh $host "rm $file"
rm "$file"

Using screen

screen can save the content of the screen session on a file. This is enabled with the following screen commands:

logfile screen.log
logfile flush 0
log on

The logfile flush 0 command removes the buffering delay in screen in order to reduce the latency.

We can watch the session locally (from another terminal) with:

tail -f screen.log

This might produce some garbage if the original and target terminals are not compatible (echo $TERM is different) or if the terminal sizes are different:

Instead of watching it locally, we want to send the content to another (shared) host over SSH:

tail -f screen.log | ssh $server 'cat > /tmp/logfile'

Other users can now watch the session on the remote host with:

tail -f screen.log

Using xterm

You can create a log file from xterm:

xterm -l -lf xterm.log

The rest of the technique applies the same.

Best viewed from a xterm-compatible terminal.

Using script

script can be used to create a log file as well:

script -f script.log

Downsides

The downside is that a log file is created on both the local and server-side. This file might grow (especially if you broadcast nyancat 😺 for a long time) and might need to be cleaned up afterwards.

A FIFO might be used instead of a log file with some programs. It works with screen and script but not with xterm. However, I experienced quite a few broken pipes (and associated brokeness) when trying to use this method. Moreover, using a FIFO can probably stall some terminals if the consumer does not consume the data fast enough.

Broadcast service

In order to avoid the remote log file, a solution is to setup a terminal broadcast service. A local terminal broadcast service can be set up with:

socat UNIX-LISTEN:script.socket,fork SYSTEM:'tail -f script.log'

And we can watch it with:

socat STDIO UNIX-CONNECT:script.socket

We can expose this service to a remote host over SSH:

ssh $server -R script.socket:script.socket -N

The downside of this approach is that the content is transfered over SSH once per viewer instead of only once.

Web broadcast

node-webterm can be used to broadcast the log over HTTP:

{
	"login": "tail -f script.log",
	"port": 3000,
	"interface": "127.0.0.1",
	"input": true
}

This displays the terminal in the browser using terminal.js, a JavaScript xterm-compatible terminal emulator (executing client-side). The default terminal size is the same as the default xterm size. It can be configured in index.html.

Alternatives