does OpenSSH or the alternatives have a way to automatically do this?
Yes, but there is an obstacle. The way is by ChannelTimeout
and UnusedConnectionTimeout
options for sshd
(the server). ChannelTimeout
option of for ssh
(the client) may be used instead of (or along with) the same option for sshd
to close inactive channels. See this answer of mine.
The obstacle is in the fact that any activity will reset the timer. This includes output of some long-running job that occasionally prints to the console, but also the clock in the status line of tmux. The user's inactivity is not enough. With small timeouts the options may kinda work, but in general our solution needs to start in tmux.
Tmux can run a command upon inactivity. Fortunately the user's inactivity is what matters here. The functionality was designed to lock the tmux client (e.g. with lock
), but it's possible to detach the client instead. This is an example snippet for ~/.tmux.conf
(on the SSH server, where you use tmux):
set -g lock-command '[ -n "$SSH_CONNECTION" ] && tmux detach -t "$(tty)"'set -g lock-after-time 30 # seconds; 0 = never
The point of testing $SSH_CONNECTION
it to make the code affect you, only if you have connected via SSH. If you ever use tmux directly on the server, your tmux client will not be detached automatically. I think this logic is quite sane.
From now on your tmux client run in an SSH session will detach automatically upon your inactivity. There are two possibilities what happens next:
If
tmux
is your login shell or if from your login shell youexec tmux
, or if you dotmux; exit
or so, then after the tmux client detaches and exits, there will be no shell left in the SSH session and the SSH connection will be terminated (like it does when one exits his or her remote login shell while not using tmux).Unless there are other channels, that is; they may be e.g. port forwardings in use or sessions using this very connection as their master connection. Now you may need to use the mentioned
*Timeout
options for SSH to deal with them (e.g.ChannelTimeout=*=2m
in~/.ssh/config
on the client).But if you straightforwardly use
ssh
only to get to remote tmux, then there should be no other channels and the timeout in tmux will be enough to make you happy.If there is a shell between
sshd
and the tmux client, and if the shell stays idle after the tmux client exits, then you need an additional timeout. The solution may be with*Timeout
options for SSH, as described just above (but note some shells can display a dynamic prompt with a clock or whatever, it will "break SSH inactivity" like the clock in tmux status line does); or the shell itself may provide a way to make it exit on inactivity.Personally I prefer having a shell between
sshd
andtmux
(so I can detach and easily do something on the server outside of tmux). My shell is Bash. I would put this snippet at the end of my~/.bashrc
:if [ -z "$TMUX" ]; then tmux attach || tmux [ -n "$SSH_CONNECTION" ] && TMOUT=20 # secondsfi
It is designed to work like this:
- If outside of tmux, the snippet tries to start a tmux client to attach to the last tmux session or (if this fails because there is no session) to start a new session. When the tmux client exits and if the user has connected with SSH, the shell timeout is set to 20 seconds.
- If inside tmux, the snippet does nothing (so shells in newly created panes will not try to run
tmux
, nor will they set the timeout for themselves).
This should work well. Shells inside tmux will be unaffected, but the outer interactive shell (if you have connected with SSH) will exit by itself after short inactivity.
So here you go: if you have connected with SSH then the tmux client will exit after 30 seconds of your inactivity, then the outer shell will exit after the next 20 seconds of inactivity; and then the SSH connection will end, unless there are other channels. Now the situation is like at the end of the previous numbered paragraph: you may need to use the mentioned
*Timeout
options to deal with the channels, but if you straightforwardly usessh
only to get to remote Bash+tmux, then there should be no other channels and the timeout in tmux plus the timeout in Bash will be enough to make you happy.