If you can use a separate connection only to forward port(s), i.e. possibly with
-N, then consider this workaround:
while echo; do sleep 1; done | ssh user@server 'exec bash -c "while read -t 5; do :; done"'
(Include port forwarding(s) on your own).
When newlines from
echo stop getting to the remote side,
read -t 5 will eventually fail and the entire remote loop will exit. The SSH server will notice its child process exited, it will terminate the connection and release the port(s).
read -t is not portable, the command explicitly calls
bash to handle it.
- If the command interpreter for
bash then there is no need for
exec bash; sole
"while read -t 5; do :; done" (instead of
'exec bash -c …') will work.
read -t 5 is quite straightforward. You can develop code that implements the concepts of
I tested this approach on my laptop, with actual remote port forwarding (
beep instead of
: to hear from the server. When I disconnected Wi-Fi, the beeping stopped. When I reconnected Wi-Fi quickly, the beeping caught up and continued. But when I reconnected few seconds too late, the local command exited because it learned the SSH server had terminated the connection as designed. Important things:
- There were other SSH connections to the same server, governed by
*AliveCountMax, and they survived. This means my special connection ended without assistance from these options. If I waited long enough with Wi-Fi turned off, then almost all connections would terminate because of the options, including the local half of the special connection. The exception would be the remote half; it would have been long gone anyway because
bash would had exited.
- I was able to connect again immediately, never got
remote port forwarding failed for listen port. Therefore I think my approach can be a valid solution to your problem.