OpenSSH has an option called LocalCommand
that runs a command on the client side when you make an ssh connection. Unfortunately, it runs the command before the ssh session is established, not afterwards. But that gave me the idea that I might somehow be able to get that preceding process to wait for the ssh session to end. Despite the fact that the ssh process is the parent PID of the LocalCommand, it turns out that it's still not all that easy.
However, I did find something that works for me under MacOS X, and ought to work on (other) BSDs, if not Linux. I wrote a small C program that uses the kqueue()
interface to wait on its own ppid and then run a supplied command once that process exits. (Source code listing below, for those who are interested.)
Now I just have to reference this program in my ~/.ssh/config
file:
host hp-switch*
PermitLocalCommand yes
LocalCommand ~/bin/wait4parent 'tput smam'
And this seems to work just fine. Those of you on Linux … I guess you can try the same sort of thing by polling for LocalCommand
's ppid and hope that that pid doesn't get reused. (See https://stackoverflow.com/questions/1157700/how-to-wait-for-exit-of-non-children-processes)
wait4parent.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
int main(int argc, char **argv) {
pid_t ppid, fpid;
struct kevent kev;
int kq;
int kret;
struct timespec timeout;
if ( argc > 2 ) {
fprintf(stderr, "Please quote the command you want to run\n");
exit(-1);
}
ppid = getppid();
fpid = fork();
if ( fpid == -1 ) {
perror("fork");
exit(-1);
}
if ( fpid != 0 ) {
exit(0);
}
EV_SET(&kev, ppid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, 0);
kq = kqueue();
if ( kq == -1 ) {
perror("kqueue");
exit(-1);
}
kret = kevent(kq, &kev, 1, NULL, 0, NULL);
if ( kret == -1 ) {
perror("kevent");
exit(-1);
}
timeout.tv_sec = ( 8 /*hours*/ * 60 /*minutes per hour*/ * 60 /*seconds per minute*/ );
timeout.tv_nsec = 0;
kret = kevent(kq, NULL, 0, &kev, 1, &timeout);
if ( kret == -1 ) {
perror("kevent");
exit(-1);
}
if ( kret > 0 ) {
system(argv[1]);
}
/* ( kret == 0 ) means timeout; don't do anything */
exit(0);
}
ssh 1.2.3.4 && tput smam