ssh 세션 종료 후 로컬 명령 실행


9

ssh를 통해 로그인하는 일부 HP 스위치가 있습니다. 스위치는 터미널 명령을 보내 줄 바꿈 (terminfo 용어에서 "rmam")을 비활성화하지만 다시 활성화하지 못하여 ssh 세션을 종료 한 후 터미널을 망칩니다. 를 실행하여 터미널을 수정할 수 있습니다 tput smam.

내 ssh 세션이 끝난 후 ssh가 자동으로 해당 명령을 실행하도록하는 방법이 있습니까?

셸 자동 ssh명령으로 실행 하거나 별칭 을 나중에 항상 실행하도록 별칭 을 죽일 수는 없지만 ssh를 통해 문제를 해결하여 알려진 연결에 명령이 실행되도록 제한 할 수 있습니다. -나쁜 호스트.

내 ssh 클라이언트는 OpenSSH_6.2p2이지만 어딘가에 새로운 기능이 있으면 변경하거나 업데이트 할 수 있습니다.


나는 해결책을 찾지 못했습니다 ... telnet 사용;) 또는 별도의 터미널 창을 사용하십시오.
ewwhite

한번만 사용하면 항상 이중 앰퍼샌드가 있습니다. ssh 1.2.3.4 && tput smam
Hennes

@ewwhite : 당신은 당신이 수정을 자동화하는 방법을 찾지 못했다는 것을 의미합니까? 그렇지 않은 경우 수정 사항이 바로 질문에 있습니다. 또한, 나는 당신이 농담한다는 것을 알고 있지만, 연결이 암호화되지 않았기 때문에 스위치가 터미널에서 크 래핑을 피하는 것과는 다릅니다.
wfaulk

답변:


8

OpenSSH에는 LocalCommandssh 연결을 작성할 때 클라이언트 측에서 명령을 실행 하는 옵션이 있습니다. 불행히도 ssh 세션이 설정 되기 전에 명령이 실행됩니다 . 그러나 그것은 나에게 어떻게 든 ssh 세션이 끝나기를 기다리는 이전 프로세스를 얻을 수 있다는 아이디어를주었습니다. ssh 프로세스가 LocalCommand의 상위 PID라는 사실에도 불구하고 여전히 쉽지는 않습니다.

그러나 MacOS X에서 나에게 맞는 것을 발견했으며 Linux가 아닌 경우 (다른) BSD에서 작동해야합니다. kqueue()인터페이스를 사용하여 자체 ppid를 기다린 다음 프로세스가 종료되면 제공된 명령을 실행 하는 작은 C 프로그램을 작성했습니다 . (아래 관심있는 사람들을위한 소스 코드 목록)

이제 ~/.ssh/config파일 에서이 프로그램을 참조하면 됩니다.

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

그리고 이것은 잘 작동하는 것 같습니다. 리눅스에서 당신의 사람들 ... 나는 당신이 같은 LocalCommand바보 를 조사하여 같은 종류의 것을 시도 할 수 있다고 생각합니다. 그리고 그 pid가 재사용되지 않기를 바랍니다. ( /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
우수한! Mac에서이 스크립트를 사용하고 다른 시스템 호출을 추가하여 로컬 명령을 미리 실행 (프롤로그) 한 다음 두 번째 명령이 세션 (에필로그) 후에 실행될 때까지 기다릴 수있었습니다.
Kevin Lee

1
나는 아이디어를 가져 와서 약간의 코드를 개선했다. GitHub
drinchev

4

이를 위해 간단한 ssh 래퍼를 만들 수 있으며 ssh 후에 실행될 명령을 지정합니다.

nox : ~ $ fssh foo
foo : ~ $ id
uid = 0 (루트) gid = 0 (루트) 그룹 = 0 (루트)
foo : ~ $ 이탈
로그 아웃
1.2.3.4 연결이 닫혔습니다.
2014 년 10 월 30 일 19:01:35 CET 2014
nox : ~ $ 고양이 상자 / fssh 
#! / bin / bash

eval ssh '$ @'
rc = $?
데이트
"$ rc"종료

2
그래, 내가 할 수 있다고 말했다. (공평하게 말하면, "래퍼 스크립트"가 아닌 "별칭"만 말한 것 같습니다.) 어쨌든, 당신이 왜 그것을 원하는지 잘 모르겠습니다 eval. 큰 따옴표의 이점을 버립니다 $@.
wfaulk

사용해보십시오. SSH와 직접 대화하는 것처럼 여전히 따옴표 (작은 따옴표와 큰 따옴표)를 사용할 수 있습니다. 전체 구문을 평가하지 않으면 생성 된 명령의 실제 종료 코드를 캡처 할 수없는 상황이 있었기 때문에 eval을 사용했습니다.
Hrvoje Špoljar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.