sub login_ssh { my $ip = shift; my $uname = shift; my $pword = shift; # I remapped the SIG handler for DIE elsewhere in my code. # If the SSH connection fails, it will be caught by # that handler, which I do not want. So remap it temporarily. my $old_sigdie = $SIG{__DIE__}; $SIG{__DIE__} = sub { mylog(MSG_NOTICE, "Caught SIG to DIE: $_[0]. Ignoring"); }; my $conn = Net::Appliance::Session->new( Host => $ip, Transport => 'SSH' ); eval { # eval {} probably not necessary in this particular case, # since we intercept SIG DIE $conn->connect(Name => $uname, Password => $pword); }; # The ssh procs are sticking around even after we fail to log in. # Get the child pid spawned by # Net::Appliance::Session::Transport::SSH so we can kill it explicitly my $sshpid = $conn->childpid(); if ($conn->logged_in()) { # return an open Net::Appliance::Session session return $conn; } else { if ($@) { process_error($@); } $SIG{__DIE__} = $old_sigdie; $conn->close(); if (kill(0, $sshpid) > 0) { mylog("Child SSH proc $sshpid is still running. Killing it"); my $rc = kill TERM => $sshpid; } if (kill(0, $sshpid) > 0) { mylog("Child SSH proc $sshpid is still running. Kill -9'ing it"); my $rc = kill 9 => $sshpid; } return; } }