Clean up the terminal and reconnect when SSH connections drop (#6661)
* Clean up the terminal and reconnect when SSH connections drop A remote tmux, herdr, or editor arms terminal modes over the SSH pipe (mouse tracking, focus reporting, the alternate screen) that only it can disarm. When the connection dies instead of exiting cleanly, those modes stay armed on the local terminal, and every mouse move floods the prompt with escape-sequence junk. Wrap ssh in a shell function that disarms those modes after every exit, and automatically reconnects when an established interactive session drops. Remote commands, configured RemoteCommands, and redirected stdin never reconnect, so their side effects cannot replay, and the retry loop runs in a subshell so Ctrl-C cancels both the in-flight attempt and the loop. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Detect dead SSH connections within a minute Without keepalives, ssh does not notice a dead peer until TCP gives up, which can take hours of sitting on a hung terminal with remote-armed terminal modes stuck on. Ship a client keepalive default so drops are detected in about 45 seconds, letting the shell's ssh wrapper clean up and reconnect. ~/.ssh/config is read first and wins, so per-host overrides still apply. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Fail closed when ssh -G cannot resolve the effective config An unresolvable configuration could hide a RemoteCommand, so treat it as non-interactive rather than reconnectable. Also strengthen the tests from Copilot review: assert the complete disarm sequence, and verify on a real interactive pty that Ctrl-C during a retry attempt kills the reconnect loop itself, not just the in-flight attempt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Tolerate the explicit RemoteCommand none when probing ssh -G The literal "none" is how ssh_config cancels a configured RemoteCommand, and some OpenSSH versions emit it even when unset, which would have silently disabled reconnecting entirely. Treat it as no remote command while still failing closed on real ones and unresolvable configs, and make the fake ssh -G emit the "none" form so the behavior tests cover it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
9d61915b2e
commit
6ddc39520d
@@ -0,0 +1,18 @@
|
||||
echo "Detect dropped SSH connections quickly instead of leaving terminals hung"
|
||||
|
||||
conf="/etc/ssh/ssh_config.d/20-omarchy-keepalive.conf"
|
||||
|
||||
if [[ ! -f $conf ]]; then
|
||||
sudo install -d -m 755 /etc/ssh/ssh_config.d
|
||||
# An explicit mode so a restrictive user umask cannot leave the root-owned
|
||||
# drop-in unreadable to the unprivileged ssh client.
|
||||
sudo tee "$conf" >/dev/null <<'EOF'
|
||||
# Omarchy: notice dropped connections quickly instead of hanging until TCP
|
||||
# times out. Settings in ~/.ssh/config take precedence over these defaults.
|
||||
Host *
|
||||
ServerAliveInterval 15
|
||||
ServerAliveCountMax 3
|
||||
ConnectTimeout 10
|
||||
EOF
|
||||
sudo chmod 644 "$conf"
|
||||
fi
|
||||
Reference in New Issue
Block a user