-
-
Save arkku/df879fa93341b11106925d98791d67b2 to your computer and use it in GitHub Desktop.
| #!/bin/sh | |
| host="$1" | |
| [ -z "$host" ] && host=homeshell | |
| port="$2" | |
| [ -z "$port" ] && port=60001 | |
| slave="$3" | |
| [ -z "$slave" ] && slave=`hostname -s` # use a fixed string if needed | |
| main=$4 | |
| [ -z "$main" ] && main=0 | |
| session="${main}_${slave}" | |
| server="env MOSH_SERVER_SIGNAL_TMOUT=20 mosh-server" | |
| attempted_detach=0 | |
| while true; do | |
| if mosh --server="$server" -P "$port" "$host" -- bin/tmx prefix '^b' "$main" "$slave"; then | |
| exit 0 | |
| elif [ $attempted_detach = 1 ]; then | |
| exit 1 | |
| fi | |
| # Try to detach the existing client from holding up our port | |
| # (it will not detach if it is still live due to -P and | |
| # MOSH_SERVER_SIGNAL_TMOUT) | |
| echo "Attempting to detach session $session..." >&2 | |
| ssh "$host" -- tmux lsc -F '\#{client_pid}' -t "$session" \| \ | |
| xargs ps -o ppid= \| xargs kill -SIGUSR1 >&2 | |
| attempted_detach=1 | |
| done |
Basically this tries to solve the problem where mosh-server fails to listen, e.g., because there is already a session connected to the same port, e.g., when you only have one port passing through the firewall and it's occupied by a dead session (such as when you don't shut down the mosh client cleanly and the server can't know whether it will ever return online). Basically the solution is: if the first attempted mosh connection fails, we use regular ssh to try to send SIGUSR1 to any existing mosh-server tied to the same tmux session name. Due to the MOSH_SERVER_SIGNAL_TMOUT setting, it will only be killed by this if it has been idle for more than the 20 seconds timeout – this prevents killing a live connection. Then mosh is re-attempted, hopefully succeeding if the port is now available.
As shown, this is made only for certain types of tmux sessions with deterministic ids with the slave session id defaulting to the short hostname, but you can use a fixed string shared between multiple devices to ensure only one can have an active session at a time. If you are not using tmux in that way, course you can omit the bin/tmx and related stuff, and then change the ssh to use pkill to find the mosh-server having that port occupied.
(And yes, of course you could just unconditionally send SIGUSR1 to every mosh-server to kill all the idle ones, but that's not wanted here, since they may be legitimate sessions from other devices that are sleeping at the moment. And at the same time, I want to keep the idle threshold very short, i.e., shorter than the time it takes to reboot.)
The
bin/tmxcommand referenced by this is https://github.com/arkku/dotfiles/blob/master/bin/tmx