Chạy lệnh cục bộ sau khi phiên ssh kết thúc


8

Tôi có một số thiết bị chuyển mạch HP mà tôi đăng nhập thông qua ssh. Các thiết bị chuyển mạch gửi một lệnh đầu cuối để vô hiệu hóa ngắt dòng ("rmam" theo cách nói của terminfo), nhưng sau đó không thể kích hoạt nó, điều này làm hỏng thiết bị đầu cuối của tôi sau khi tôi thoát phiên ssh. Tôi có thể sửa chữa thiết bị đầu cuối bằng cách chạy tput smam.

Có cách nào để ssh tự động chạy lệnh đó sau khi phiên ssh của tôi kết thúc không?

Nó sẽ không giết tôi để chạy nó như một trình tự động shell hoặc bí danh sshđể luôn chạy lệnh đó sau đó, nhưng tôi muốn giải quyết vấn đề thông qua ssh để tôi có thể giới hạn lệnh chỉ được chạy sau khi tôi kết nối với -bad chủ nhà.

Ứng dụng khách ssh của tôi là OpenSSH_6.2p2, nhưng tôi có thể thay đổi hoặc cập nhật nếu có một tính năng mới ở đâu đó.


Tôi chưa bao giờ tìm thấy một sửa chữa ... sử dụng telnet;) Hoặc chỉ sử dụng một cửa sổ đầu cuối riêng biệt.
ewwhite

Đối với một lần tắt sử dụng, luôn luôn có hai ký hiệu. ssh 1.2.3.4 && tput smam
Hennes

@ewwhite: Ý bạn là bạn chưa bao giờ tìm cách tự động hóa bản sửa lỗi? Nếu không, sửa chữa là có ngay trong câu hỏi. Ngoài ra, trong khi tôi biết bạn đang nói đùa, không giống như công tắc sẽ tránh được việc ngắt trên thiết bị đầu cuối của tôi chỉ vì kết nối không được mã hóa.
wfaulk

Câu trả lời:


8

OpenSSH có một tùy chọn được gọi là LocalCommandchạy một lệnh ở phía máy khách khi bạn thực hiện kết nối ssh. Thật không may, nó chạy lệnh trước khi phiên ssh được thiết lập, không phải sau đó. Nhưng điều đó đã cho tôi ý tưởng rằng bằng cách nào đó tôi có thể có được quy trình trước đó để chờ phiên ssh kết thúc. Mặc dù thực tế rằng quá trình ssh là PID chính của LocalCommand, nhưng hóa ra nó vẫn không dễ dàng như vậy.

Tuy nhiên, tôi đã tìm thấy thứ gì đó phù hợp với tôi trong MacOS X và phải hoạt động trên (các) BSD khác, nếu không phải là Linux. Tôi đã viết một chương trình C nhỏ sử dụng kqueue()giao diện để chờ ppid của chính nó và sau đó chạy lệnh được cung cấp khi quá trình đó thoát. (Danh sách mã nguồn dưới đây, cho những người quan tâm.)

Bây giờ tôi chỉ cần tham khảo chương trình này trong ~/.ssh/configtập tin của mình :

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

Và điều này dường như chỉ hoạt động tốt. Những người trong số bạn trên Linux, tôi đoán bạn có thể thử điều tương tự bằng cách bỏ phiếu cho LocalCommandppid và hy vọng rằng pid không được sử dụng lại. (Xem /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
Thông minh! Tôi đã sử dụng tập lệnh này trên Mac và thêm một lệnh gọi hệ thống khác để tôi có thể có một lệnh cục bộ chạy trả trước (mở đầu) và sau đó đợi lệnh thứ hai chạy sau phiên (đoạn kết).
Kevin Lee

1
Tôi lấy ý tưởng và cải thiện một chút mã. Bạn có thể tìm thấy công cụ trên GitHub
drinchev

4

Bạn có thể tạo trình bao ssh đơn giản cho việc này và trong đó chỉ định các lệnh sẽ được chạy sau ssh, vd

nox: ~ $ fssh foo
foo: ~ $ id
uid = 0 (root) gid = 0 (root) nhóm = 0 (root)
foo: ~ $ thoát
đăng xuất
Kết nối tới 1.2.3.4 đã đóng.
Ngày 30 tháng 10 19:01:35 CET 2014
nox: ~ $ mèo bin / fssh 
#! / bin / bash

eval ssh '$ @'
RC = $?
ngày
thoát "$ RC"

2
Vâng, tôi nói tôi có thể làm điều này. (Công bằng mà nói, tôi đoán tôi chỉ nói "bí danh" chứ không phải "kịch bản trình bao bọc".) Bất kể, tôi không chắc tại sao bạn muốn evalđiều đó. Nó vứt bỏ lợi ích của trích dẫn kép $@.
wfaulk

Hãy thử nó; bạn vẫn có thể sử dụng dấu ngoặc kép bình thường (cả dấu ngoặc đơn và dấu ngoặc kép) giống như bạn đang nói chuyện trực tiếp với SSH. Tôi đã sử dụng eval bởi vì tôi đã có những tình huống trong đó việc nắm bắt mã thoát thực sự của lệnh được xây dựng là không thể trừ khi tôi đã thực hiện toàn bộ câu lệnh được xây dựng.
Hrvoje Špoljar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.