78

My SSH sessions seem to be dropping though that is not my major problem - the major problem is my previous sessions are still alive, worse yet one of them is running visudo preventing me from accessing it!

who shows a number of sessions all except my current one I know have disconnected, how can I terminate the old ones so the release their resources?

5
  • 2
    If you're alright with killing everything on a particular terminal you could do something like fuser -k /dev/pts/0 or whatever terminal's showing up in the who output. A little weird all those ignored SIGHUP, though. Were they running in a screen session or something?
    – Bratchley
    May 2, 2014 at 13:46
  • 1
    I get: Could not kill process 1031: No such process. nothing special just SSH'd in using PuTTY - I think my new router is aggressive in dropping inactive connections - though I would have thought the other end would have done something once the TCP conn terminates - perhaps it doesn't know (yet)?
    – markmnl
    May 2, 2014 at 13:48
  • 1
    UPDATE that command is working for the other users (0 not in who anymore), thanks!
    – markmnl
    May 2, 2014 at 13:54
  • "My SSH sessions seem to be dropping though...the major problem is my previous sessions are still alive" is a little contradictory. They've either been disconnected, or they are still connected. Maybe you should explain how you've reached this conclusion such that you've been disconnected then connect again and realize your old connection is still running.
    – goldilocks
    May 2, 2014 at 15:36
  • #!/bin/sh sudo killall -u YOURUSER -r sshd Nov 26, 2019 at 22:28

3 Answers 3

96

To solve the immediate problem, that the sudoers file is locked, you can simply delete the lock file. It will usually be `/etc/sudoers.tmp"; check the man page for visudo to verify. If you delete the lock file, you can run visudo again.

To delete all sessions which are still left hanging, first find out the pid of your own current session. Then, if your own pid is 12345, do

ps -ef | grep sshd | grep -v -e grep -e root -e 12345 | awk '{print "sudo kill -9", $2}' | sh 

You may want to do it without the final | sh first just to check the PIDs you're planning on killing.

If you're on Linux, you can instead use

pkill -o -u $USER sshd

to kill your oldest SSH session. Continue doing that until your current session is the only one left.

You might also want to set ServerAliveInterval 15 in your .ssh/config to send a keepalive message every 15 seconds when no data has been sent. man ssh_config for more information.

5
  • 1
    On CentOS - If you're SSH ing to root account, this answer won't work, try using the following: ps aux | grep ssh | grep -v /usr/sbin | awk '{ print $2 }' | xargs kill Jul 16, 2017 at 17:01
  • Thanks. This works. I am unclear about what purpose does grep -v 12345 part of the syntax serve? pass all that does not contain 12345?
    – Lord Loh.
    Oct 9, 2017 at 18:41
  • 1
    grep -v 12345 means "remove any line matching 12345 from the match". Hence, you should first identify the PID of your own session, and use that PID instead of 12345.
    – Jenny D
    Oct 10, 2017 at 7:05
  • 1
    After killing all such sessions and resign, commands who or top still shows old number of signed users, even it should show just 1. How can that be forced to being refreshed?
    – Ωmega
    Oct 22, 2018 at 19:42
  • 2
    doing pkill -o -u $USER sshd as a root is extremely dangerous! especially when you do not have physical access to a server. if you do it once more than you should you, will lose access to the server via ssh.
    – inemanja
    Jun 15, 2021 at 11:06
8

This will kill sessions hanging for 2+ days. It could be put as a cron.

for i in `w|awk '{print $2,$5}'|grep days|cut -d' ' -f1`; do fuser -k /dev/$i; done

This will kill all but your (last active session). Run this from terminal.

for i in `w|tail -n+3|awk '{print $2,$5}'|grep -v 0.00s|cut -d' ' -f1`; do fuser -k /dev/$i; done
1
  • I get error: -bash: fuser: command not found Jan 25, 2023 at 15:27
3

If you list processes so that you see their command and arguments (like e.g. ps -f from procps does), you should see then sshd processes called e.g.:

sshd: user@pts/7

The terminal (pts/7) is the key part here - if you compare it with your current terminal (tty), you can see which is your active session. There are of course other ways to do that (like looking at the PID of the currently running shell and locating that one in the process tree), but this is likely the easiest one. You can then use something along these lines:

# current tty name
TTY=$(tty | cut -f3- -d/)
# PIDs of other sshd processes
ps -o pid= -o command= -C sshd \
    | grep sshd:.*@ \
    | grep -v "@$TTY" \
    | sed "s/ sshd.*//"

You can then feed the PIDs to kill with xargs but always make sure you do not kill the main sshd process which handles new connections.

On a related note, be advised that quite generally parsing ps output is error-prone (especially across various systems) due to the variability of its output formats (here mitigated to large extent by the use of -o pid= -o command=).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .