Chcę mieć możliwość wysyłania sygnałów (najważniejszy jest SIGINT) przez ssh.
To polecenie:
ssh server "sleep 1000;echo f" > foo
rozpocznie tryb uśpienia na serwerze i po 1000 sekundach umieści „f \ n” w pliku foo na moim komputerze lokalnym. Jeśli nacisnę CTRL-C (tj. Wyślę SIGINT do ssh), to zabije ssh, ale nie zabije snu na zdalnym serwerze. Chcę, żeby zabiło sen na zdalnym serwerze.
Więc próbowałem:
ssh server -t "sleep 1000;echo f" > foo
Ale jeśli stdin nie jest terminalem, pojawia się ten błąd:
Pseudo-terminal will not be allocated because stdin is not a terminal.
a następnie SIGINT nadal nie jest przekazywany.
Więc próbowałem:
ssh server -t -t "sleep 1000;echo f" > output
Ale wtedy wyjście w foo nie jest „f \ n”, ale zamiast „f \ r \ n”, co jest katastrofalne w mojej sytuacji (ponieważ moje dane wyjściowe to dane binarne).
W powyższym przykładzie używam „sleep 1000; echo f”, ale w rzeczywistości jest on dostarczany przez użytkownika, więc może zawierać wszystko. Jeśli jednak uda nam się sprawić, że będzie działał dla „snu 1000; echo f”, najprawdopodobniej sprawimy, że będzie działał we wszystkich realistycznych sytuacjach.
Naprawdę nie dbam o to, aby uzyskać pseudo-terminal na drugim końcu, ale nie byłem w stanie znaleźć żadnego innego sposobu na uzyskanie ssh do przekazania mojego SIGINT.
Czy jest inny sposób?
Edytować:
Użytkownik może wydawać polecenia odczytujące dane binarne ze standardowego wejścia, takie jak:
seq 1000 | gzip | ssh server "zcat|bzip2; sleep 1000" | bzcat > foo
Użytkownik może wydawać polecenia wymagające dużej mocy obliczeniowej, takie jak:
ssh server "timeout 1000 burnP6"
Edycja2:
Wydaje mi się, że wersja działa:
your_preprocessing |
uuencode a | ssh -tt -oLogLevel=quiet server "stty isig -echoctl -echo ; uudecode -o - |
your_command |
uuencode a" | uudecode -o - |
your_postprocessing
Dzięki digital_infinity za wskazanie mi właściwego kierunku.
ssh
musi być bardziej skomplikowane niż to, co pokazujesz jako przykłady, ponieważ możesz uzyskać pożądane zachowanie za pomocą prostej rearanżacji:sleep 1000 && ssh server "echo f" > foo
(Musi być&&
, nie;
, aby zabijaniesleep
uniemożliwiało uruchomieniessh
polecenia). Jeśli ja mam rację, proszę, aby przykłady były bardziej reprezentatywne dla faktycznego wykorzystania, aby można było podać lepszą odpowiedź.Odpowiedzi:
Krótka odpowiedź:
i zatrzymaj program CTRL + N.
Długie wyjaśnienie:
stty
opcji,intr
aby zmienić serwer lub lokalny znak przerwania, aby nie kolidowały ze sobą. W powyższym poleceniu zmieniłem znak przerwania serwera na CTRL + N. Możesz zmienić lokalny charakter przerwań i pozostawić serwer bez zmian.stty -echoctl
.stty isig
SIGINT
sygnał zatrap '/bin/true' SIGINT
pomocą pustej instrukcji. Bez pułapki nie będziesz mieć żadnego standardowego sygnału po sygnale SIGINT na swoim końcu.źródło
seq 1000 | gzip | ssh -tt dell-test "zcat|bzip2" | bzcat > foo
też nie działa. Aby to polecenie działało, musimy je usunąć-tt
. Przydział pseudo terminala prawdopodobnie wymaga pewnej ilości danych wejściowych ze standardowego wejścia(sleep 1; seq 1000 ) | gzip | uuencode bin | ssh -tt dell-test "stty isig intr ^N -echoctl -echo ; trap '/bin/true' SIGINT; sleep 1; uudecode -o /dev/stdout | zcat |bzip2 | uuencode bin2 " | uudecode -o /dev/stdout | bzcat >foo
. Chociaż znak przerwania nie działa - potrzebujemy metody transmisji dla znaku przerwania, gdy standardowe wejście jest zajęte .Wypróbowałem wszystkie rozwiązania i było to najlepsze:
/programming/3235180/starting-a-process-over-ssh-using-bash-and-then-killing-it-on-sigint/25882610#25882610
źródło
sleep
procesu w przypadku utraty połączenia.sleep
, prawda? Dodałem kilkadate >> /tmp/killed
pocat
, ale nie zostało uruchomione. Czy jest jakiś limit czasu? Używam Zsh normalnie, ale przetestowałem go również za pomocą bash jako zdalnej powłoki logowania.-o ServerAliveInterval=3 -o ServerAliveCountMax=2
pozwala to szybko wykryć, ale czy jest coś po stronie serwera?Myślę, że możesz znaleźć PID procesu uruchomionego na serwerze i wysłać sygnał za pomocą innego
ssh
polecenia (takiego jak tossh server "kill -2 PID"
:).Używam tej metody do wysyłania sygnałów rekonfiguracyjnych do aplikacji działających na innym komputerze (moje aplikacje łapią SIGUSR1 i czytają plik konfiguracyjny). W moim przypadku znalezienie PID jest łatwe, ponieważ mam unikalne nazwy procesów i mogę znaleźć PID, wysyłając
ps
żądanie za pośrednictwemssh
.źródło
Rozwiązanie rozwinęło się w http://www.gnu.org/software/parallel/parallel_design.html#Remote-Ctrl-C-and-standard-error-stderr
źródło
----- polecenie.sh
----- na lokalnym terminalu
źródło