Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I'd like to use ssh's ControlMaster feature to share connections for speed increases. I'm trying to script it so that I can start/restart/stop a number of connections to different hosts.

How can I determine whether any of these connections are in use? If I kill them when an ssh session is open, it gets closed

My restart script would ideally look like (pseudo-script) - the stop script would be equivalent without the ssh command at the bottom:

for HOST in $HOST_LIST
  do
    MASTER_PID=`find_master_pid $HOST`
    if $MASTER_PID
      then
        if `find_child_pid`
          echo Connection to $HOST in use: not terminating
        else
          kill -SIGHUP $MASTER_PID
        fi
    ssh -TMNf $HOST
share|improve this question

2 Answers 2

up vote 2 down vote accepted

You could simply use

ssh -o ControlPath=$socket -O check 

for each $socket you've open (easy if you keep them in a single directory).

This returns 255 if the check fails (connection not active anymore), an other value if it pass. You may need to specify the hostname too, but nothing that an awk on $socket won't give you :)

share|improve this answer
    
That's much simpler for seeing if the existing connection is open; it doesn't tell me if it is actually being used, but I guess that isn't so important... (and I have the method below) –  David Fraser Dec 10 '10 at 12:24

My current approach is to use lsof to find the Unix sockets. If I know the target filename specified by ControlPath I can search for the master process like this:

function find_master_pid() {
  lsof -a -U -u $USER -c ssh | grep $CM_DIR/$RUSER@$HOST | sed 's/^ssh *//' | cut -d' ' -f1 | sort -u
}

This will then give me the PID (unfortunately, giving the filename of the unix socket file directly to lsof doesn't work otherwise I could just ask it to output me the pid with -f; hence the sed and cut)

Searching for the child process is more tricky. The master process opens a new socket for each child process, connected to the standard file. The child process contains a socket simply marked socket. However, the inode returned by lsof is one less than the corresponding master process socket. So the following finds child processes that are connected to the master process (this needs the $MASTER_PID to check against)

function find_child_pid() {
  for CHILD_PID in `lsof -a -U -u $USER -c ssh | grep socket | sed 's/^ssh *//' | cut -d' ' -f1 | sort -u`
    do
      CHECK_PID=0
      for NODE in `lsof -a -U -u $USER -p $CHILD_PID -F i | grep ^i | sed 's/i//'`
        do
          MASTER_NODE=$((NODE+1))
          CHECK_PID=`lsof -a -U -u $USER -p $MASTER_PID | grep $MASTER_NODE | wc -l`
          [[ $CHECK_PID == 1 ]] && echo $CHILD_PID
        done
    done
}
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.