Esegui comando locale al termine della sessione ssh


8

Ho alcuni switch HP a cui accedo tramite ssh. Gli switch inviano un comando terminal per disabilitare il ritorno a capo ("rmam" in terminfo parlance), ma poi non riescono a riattivarlo, il che rovina il mio terminale dopo che ho chiuso la sessione ssh. Posso riparare il terminale correndo tput smam.

C'è un modo per ottenere ssh per eseguire automaticamente quel comando al termine della mia sessione ssh?

Non mi ucciderebbe eseguirlo come un autocommand di shell o alias sshper eseguire sempre quel comando in seguito, ma preferirei risolvere il problema tramite ssh in modo da poter limitare l'esecuzione del comando solo dopo essermi connesso a noto -bad host.

Il mio client SSH è OpenSSH_6.2p2, ma posso cambiare o aggiornare se c'è una nuova funzionalità da qualche parte.


Non ho mai trovato una soluzione ... usa telnet;) O semplicemente usa una finestra terminale separata.
ewwhite,

Per una volta fuori uso c'è sempre la doppia e commerciale. ssh 1.2.3.4 && tput smam
Hennes,

@ewwhite: Vuoi dire che non hai mai trovato un modo per automatizzare la correzione? In caso contrario, la correzione è proprio lì nella domanda. Inoltre, mentre so che stai scherzando, non è come se lo switch evitasse il crapping sul mio terminale solo perché la connessione non è crittografata.
wfaulk,

Risposte:


8

OpenSSH ha un'opzione chiamata LocalCommandche esegue un comando sul lato client quando si effettua una connessione ssh. Sfortunatamente, esegue il comando prima che venga stabilita la sessione ssh, non successivamente. Ma questo mi ha dato l'idea che avrei potuto in qualche modo riuscire a far sì che quel processo precedente attendesse il termine della sessione SSH. Nonostante il fatto che il processo ssh sia il PID padre del LocalCommand, si scopre che non è ancora così facile.

Tuttavia, ho trovato qualcosa che funziona per me su MacOS X e dovrebbe funzionare su (altri) BSD, se non su Linux. Ho scritto un piccolo programma C che utilizza l' kqueue()interfaccia per attendere sul proprio ppid e quindi eseguire un comando fornito una volta terminato il processo. (Elenco dei codici sorgente di seguito, per coloro che sono interessati.)

Ora devo solo fare riferimento a questo programma nel mio ~/.ssh/configfile:

host hp-switch*
 PermitLocalCommand yes
 LocalCommand ~/bin/wait4parent 'tput smam'

E questo sembra funzionare bene. Quelli di voi su Linux ... Immagino che possiate provare lo stesso genere di sondaggi per LocalCommandil PPID e spero che quel PID non venga riutilizzato. (Vedi /programming/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);
}

2
Eccellente! Ho usato questo script su Mac e ho aggiunto un'altra chiamata di sistema in modo da poter avere un comando locale eseguito in anticipo (prologo) e quindi attendere il secondo comando da eseguire dopo la sessione (epilogo).
Kevin Lee,

1
Ho preso l'idea e migliorato un po 'il codice. Puoi trovare lo strumento su GitHub
drinchev,

4

Potresti creare un semplice wrapper ssh per questo e in esso specificare i comandi da eseguire dopo ssh, ad es

nox: ~ $ fssh foo
pippo: ~ $ id
uid = 0 (root) gid = 0 (root) gruppi = 0 (root)
pippo: ~ $ esci
disconnettersi
Connessione a 1.2.3.4 chiusa.
Gio 30 Ott 19:01:35 CET 2014
nox: ~ $ cat bin / fssh 
#! / Bin / bash

eval ssh '$ @'
rc = $?
Data
uscita "$ rc"

2
Sì, ho detto che avrei potuto farlo. (Ad essere sinceri, immagino di aver detto solo "alias" e non "script wrapper".) Indipendentemente da ciò, non sono sicuro del motivo per cui lo desideri eval. Elimina il vantaggio della doppia citazione $@.
wfaulk,

Provalo; puoi comunque usare le virgolette normalmente (virgolette singole e doppie) come se stessi parlando direttamente con SSH. Ho usato eval perché ho avuto situazioni in cui catturare il vero codice di uscita del comando costruito non era possibile a meno che non avessi valutato l'intera istruzione costruita.
Hrvoje Špoljar,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.