Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I often found to close laptop to fast, with few remote ssh sessions opened. And after wakeup i found few dead-shells, witch has not been closed :/

How i can force clean exit of remote ssh-sessions on hibernate/suspend/shutdown?

PS On gentoo and ubuntu

share|improve this question

2 Answers 2

up vote 1 down vote accepted

Kill the ssh clients before hibernating or suspending.

On Ubuntu lucid, the suspend scripts are in /etc/pm/sleep.d. The documentation is in the pm-action(8) man page. Add /etc/pm/sleep.d/20_dariusz_kill_ssh containing something like

#!/bin/sh
case $1 in
  suspend|hibernate) pkill -x ssh;;
esac

I don't know where the corresponding scripts are on Gentoo. You might want to refine to exclude ssh to localhost if you ever do that.

For shutdown, you don't need to do anything, the normal shutdown scripts already kill the ssh clients cleanly (so they'll close the connection).

Note that leaving the session open is not a big problem. All you gain by killing it early is getting back some resources on the ssh server and some firewalls in the way. So you might kill the clients upon resume instead, and only if the connection is lost. If you choose this approach, I think the right place is in network scripts: record active ssh sessions when the network goes down, and possibly kill them when the network comes back up.

Here's a proof-of-concept (completely untested). In /etc/network/if-down.d/ssh-sessions-record (Ubuntu location), record the IP address associated with the disappearing interface and the time the interface went down:

#!/bin/sh
{
  echo OLD_IP=$(ifconfig "$IFACE" | sed -n 's/^ *inet addr:\([0-9.]\+\).*/\1/p')
  echo OLD_DATE=$(date +%s)
} >"/var/run/$IFACE.ssh-sessions-record"

In /etc/network/if-up.d/ssh-sessions-record, kill ssh connections that went through this network interface, but only if the IP address has changed or enough time has elapsed that the server may have timed out:

#!/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.]\+\).*/\1/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
share|improve this answer

Since no-one else has taken a stab at this one, I'll have a go at it. If nothing else, maybe it'll spur someone else on.

I don't have a laptop or a current Gentoo handy, so maybe Ubuntu will suffice. My current desktop is Ubuntu 10.04... you didn't mention your version - hopefully it's close.

Anyway, I'd look at the Upstart configuration (or /etc/inittab if you aren't using Upstart). Verify you are running upstart by:

# dpkg --list | grep upstart
ii  upstart          0.6.5-7     event-based init daemon

Obviously, if you don't see something similar, you are likely using init. Both tools (upstart and init) are designed to do things on startup, shutdown, etc (ie, events).

In the case of Upstart, cd to your /etc/init directory and have a peek at the files there. Since I'm not on a laptop, I don't have a "hibernate or suspend" function, but I'd bet you do. Try some greps therein to see:

/etc/init# egrep -i "suspend|hibernate" *

However, my control-alt-delete.conf file strikes me as something interesting. If I peek at it, I see:

/etc/init# cat control-alt-delete.conf 
# control-alt-delete - emergency keypress handling
#
# This task is run whenever the Control-Alt-Delete key combination is
# pressed, and performs a safe reboot of the machine.

description     "emergency keypress handling"
author          "Scott James Remnant <scott@netsplit.com>"

start on control-alt-delete

task
exec shutdown -r now "Control-Alt-Delete pressed"

I'd be willing to bet you could customize that last line to script some SSH logouts, or just about anything you like. You'd want to update (or create) the proper config file. I'm guessing a laptop install will have something specific for hibernate/suspend/etc. Looking at some of the other files (like apport.conf) I see that the configuration files actually support scripts embedded within them.

If you are dealing with init, instead of upstart, try looking at the /etc/inittab lines like:

# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop
...
# What to do when CTRL-ALT-DEL is pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now

Once you'd located the ideal spot, based on your config, it wouldn't be too difficult to throw together a bash script that could kill them off or the like.

Simple example:

#!/bin/bash
kill -9 `ps -ef | grep "[s]sh " | awk '{print $2}'`

I hope this at least gives you a starting point. Maybe there's an easier way, but I don't use laptops enough to know.

Almost forgot: Assuming you do any of that, you'd likely need to bounce init for it to take effect:

# kill -HUP 1
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.