Mate os clientes ssh antes de hibernar ou suspender.
No Ubuntu lúcido, os scripts de suspensão estão em /etc/pm/sleep.d
. A documentação está na página pm-action(8)
man. Adicione /etc/pm/sleep.d/20_dariusz_kill_ssh
contendo algo como
#!/bin/sh
case $1 in
suspend|hibernate) pkill -x ssh;;
esac
Eu não sei onde estão os scripts correspondentes no Gentoo. Você pode querer refinar para excluir ssh para localhost se você fizer isso.
Para o desligamento, você não precisa fazer nada, os scripts normais de desligamento já matam os clientes ssh de forma limpa (assim eles fecham a conexão).
Note que deixar a sessão aberta não é um grande problema. Tudo o que você ganha, matando-o cedo, é recuperar alguns recursos no servidor ssh e alguns firewalls no caminho. Então você pode matar os clientes no currículo, e somente se a conexão for perdida. Se você escolher essa abordagem, acho que o lugar certo está nos scripts de rede: registre sessões ssh ativas quando a rede cair e, possivelmente, as mate quando a rede voltar.
Aqui está uma prova de conceito (completamente não testada). Em /etc/network/if-down.d/ssh-sessions-record
(local do Ubuntu), registre o endereço IP associado à interface que está desaparecendo e o tempo que a interface caiu:
#!/bin/sh
{
echo OLD_IP=$(ifconfig "$IFACE" | sed -n 's/^ *inet addr:\([0-9.]\+\).*//p')
echo OLD_DATE=$(date +%s)
} >"/var/run/$IFACE.ssh-sessions-record"
Em /etc/network/if-up.d/ssh-sessions-record
, elimine as conexões ssh que passaram por essa interface de rede, mas apenas se o endereço IP foi alterado ou se decorreu tempo suficiente que o servidor pode ter expirado:
#!/bin/sh
if [ -e "/var/run/$IFACE.ssh-sessions-record" ]; then
. "/var/run/$IFACE.ssh-sessions-record"
NEW_IP=$(ifconfig "$IFACE" | sed -n 's/^ *inet addr:\([0-9.]\+\).*//p')
NEW_DATE=$(date +%s)
if [ "$NEW_IP" != "$OLD_IP" ] || [ $(($NEW_DATE-$OLD_DATE)) -ge 300 ]; then
## Kill all ssh processes that were connecting through $OLD_IP
for pid in $(lsof -Fp -n -i "tcp@$OLD_IP"); do
if [ "$(ps -$pid -o comm=)" = "ssh" ]; then
kill $pid
fi
done
fi