Zatrzymywanie wyjścia z programu uruchomionego w sesji SSH TERAZ

18

Problem

Wykonuję polecenie, które wysyła DUŻO informacji przez SSH. Na przykład głupio dodaję informacje debugowania w pętli, która wykonuje się milion razy, lub po prostu uruchamiam cat /dev/urandomkopnięcia.

Terminal jest zalany informacjami.

Przykład, o czym mówię

Chcę zakończyć polecenie jak najszybciej i naprawić mój program. Nie obchodzi mnie, co drukuje. Chodzi o to, że naciskam Ctrl+ CASAP (w powyższym przykładzie nacisnąłem go natychmiast po uruchomieniu polecenia), ale nadal zajmuje dużo czasu, aby wydrukować wszystkie informacje, których nawet nie potrzebuję .

Co próbowałem

Próbowałem naciskać Ctrl+ Ctak mocno, że przyniosło to dziwne rezultaty, gdy terminal w końcu dogonił:

OUTPUT HERE^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
^C^C

^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C

Przeczytałem również o Ctrl+, Sktóry najwyraźniej służy do powiedzenia terminalowi „zatrzymaj wyjście, muszę nadrobić zaległości”, ale najwyraźniej nic nie robi.

Różne szczegóły

Nie chciałbym zmieniać polecenia, które uruchamiam, aby w każdej sytuacji móc się uratować, nawet jeśli nie pamiętam, że uruchamiany przeze mnie program może tak się skończyć.

Mój klient SSH działa na Cygwin ( CYGWIN_NT-6.1-WOW64 luna 1.7.30(0.272/5/3) 2014-05-23 10:36 i686 Cygwin) w MinTTY z typem terminala ustawionym na xterm-256color.

Serwer SSH działa na Debian ( Linux burza 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 i686 i686 GNU/Linux).

rr
źródło
W jakim systemie uruchamiane są rzeczywiste programy generujące dane wyjściowe? Linux, Unix lub Windows? Linux i UNIX powinny zaakceptować Ctrl-O, co oznacza „odrzucić wszelkie dane wyjściowe zapisane na tym terminalu”.
Mark Plotnick
Serwer działa na Debianie. Edytowałem pytanie. Ctrl-O wydaje się również nic nie robić. Może to sprawa klienta?
rr-
Możesz spróbować uruchomić swój Xterm z -jopcją, aby włączyć przewijanie skoku. Podstawowym problemem jest to, że pilot może wysyłać dane szybciej niż okno terminalu może je wyświetlić - domyślnie musi bitbltować zawartość okna za każdym razem, gdy drukowany jest nowy wiersz. Do momentu odebrania Ctrl-C przez zdalny system można zbuforować dużo danych, a program terminalowy spróbuje wyświetlić je wszystkie.
Mark Plotnick
Pomysł: jeśli masz jakieś dokładne polecenia, które zwykle przypadkowo wykonujesz i generują one wiele wyników, dlaczego nie dołączyć do nich aliasów .bashrc?
psimon
Możesz użyć mosh zamiast ssh: mosh.mit.edu
gmatht

Odpowiedzi:

5

Niektóre z tych danych wyjściowych będą buforowane. Wysyłasz Ctrl+ Cdo zdalnego końca, który przerywa działający program. Program istnieje, a powłoka wysyła znaki, aby ponownie wyświetlić monit. Przed wyświetleniem monitu na ekranie zostaną wyświetlone wszystkie dane, które zostały buforowane i są już w drodze do Ciebie.

Pytasz, czy program się zatrzyma, a przesyłane dane jakoś znikną. To nie może się zdarzyć, ponieważ jest już w drodze.

Jedynym sposobem, aby upewnić się, że nie widzisz tych danych, jest wyjście z terminala na swoim końcu, a następnie ponowne połączenie się z pilotem - ale to prawdopodobnie znacznie więcej wysiłku niż czekanie na wyświetlenie buforowanych danych.

garethTheRed
źródło
10

Zwykle uruchamiam dane wyjściowe, lessaby móc je zabić za lesspomocą qklucza.

$ cmd | less

Przykład

$ cat /dev/urandom | less

   ss # 2

Po wciśnięciu q+ Enter, wyjdzie i wróci do normalnego terminala, pozostawiając ładnie i czysto.

Dlaczego tak się dzieje?

Problem, który napotykasz, polega na tym, że istnieją bufory (dla STDOUT), które są ustawione w kolejce z wyjściem twojego wyświetlacza. Bufory te zapełniają się tak szybko, że nie można przerwać ich wystarczająco szybko, aby je zatrzymać.

                                    ss # 1

Aby wyłączyć / ograniczyć ten efekt, możesz wyłączyć buforowanie STDOUT, co powinno sprawić, że będzie nieco bardziej responsywne stdbuf, ale prawdopodobnie będziesz musiał grać z tymi ustawieniami, aby uzyskać pożądany efekt . Aby cofnąć buforowanie polecenia STDOUT, możesz użyć tego polecenia:

$ stdbuf -o0 <cmd>

Strona stdbufpodręcznika ze szczegółowymi opcjami do dyspozycji:

    If MODE is 'L' the corresponding stream will be line buffered.  This 
    option is invalid with standard input.

    If MODE is '0' the corresponding stream will be unbuffered.

    Otherwise MODE is a number which may be followed by one of the 
    following: KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so
    on for G, T, P, E, Z, Y.  In this case the corresponding stream will be 
    fully buffered with the  buffer  size  set  to  MODE
    bytes.

Aby uzyskać dobre tło na temat działania buforowania, gorąco polecam przyjrzeć się temu artykułowi Pixel Beat zatytułowanemu: buforowanie w standardowych strumieniach . Zawiera nawet ładne zdjęcia.

Bibliografia

slm
źródło
To rozsądne, tak długo, jak pamiętam, aby dołączyć |lessdo cmd, co niestety często nie. Jeśli uruchomisz cmd, nadal musisz poczekać, aż zakończy się drukowanie wyników obliczonych przed otrzymaniem ^C.
rr
1
To tak naprawdę nie wyjaśnia, co się dzieje. W końcu nie ma tu żadnego potoku, więc do jakiego bufora się odwołujesz?
Gilles „SO- przestań być zły”,
@Gilles - przepraszam, bufor byłby buforem do ekranu.
slm
Jaki bufor? W jądrze? W Xterm?
Gilles „SO- przestań być zły”,
@Gilles - daj mi chwilę, szukam szczegółów 8-)
slm
3

Istnieje kilka poziomów buforowania. Naciśnięcie Ctrl+ Cpowoduje, że program nie emituje danych do terminala. Nie wpływa to na dane, których emulator terminala jeszcze nie wyświetlał.

Gdy wyświetlasz dane z bardzo dużą prędkością, terminal nie może nadążyć i będzie opóźniony. Oto, co się tutaj dzieje: wyświetlanie tekstu jest o wiele droższe niż tworzenie liczb losowych. Tak, nawet w przypadku czcionek bitmapowych - tworzenie liczb losowych o jakości kryptograficznej jest tanie w porównaniu z innymi. (Właśnie wypróbowałem na swoim komputerze, a proces X nasycił procesor, xtermbiorąc kilka% i cat(przy czym generowane są liczby losowe) ledwo osiągając 1%. I to z czcionką bitmapową.)

Jeśli chcesz to teraz zatrzymać, zabij emulator terminala. Jeśli nie chcesz tego robić, przynajmniej zminimalizuj okno; inteligentne emulatory terminali (takie jak xterm) nie odwzorowują okna, co oszczędza czas procesora X, więc śmieci zostaną szybciej wyświetlone. Serwer X ma wysoki priorytet, więc będzie to miało duży wpływ na szybkość reakcji twojego komputera, gdy xterm przetwarza dane w tle.

Gdy wszystko to dzieje się w zdalnej powłoce, opóźnienie jest jeszcze większe, ponieważ wytworzone dane catmuszą najpierw przejść przez połączenie SSH. Wciśnięcie Ctrl+ Cmusi również przejść przez połączenie SSH; ma nieco wyższy priorytet (jest wysyłany poza pasmem), ale nadal zajmuje to trochę czasu, podczas którego gromadzi się więcej mocy wyjściowej. Nie ma sposobu, aby ukryć przesyłane dane poza zamknięciem połączenia SSH (co można zrobić, naciskając Enterwtedy ~.).

Gilles „SO- przestań być zły”
źródło
Problem jest związany z SSH wzdłuż. Bufor STDOUT nie powinien być używany w trybie interaktywnym, ale SSH nie może poprawnie obsługiwać trybu interaktywnego. Chociaż w wyniku transakcji może się zawiesić wiele danych wyjściowych, to proces SSH odbiera Ctrl + C, więc jego obowiązkiem jest zabicie danych wyjściowych, gdy nie można przekazać Ctrl + C do pilota.
user4674453
@ user4674453 Uh? Ctrl + C nie powinien zabijać lokalnego wyjścia. To wcale nie jest jego praca. Powinien zostać przekazany do odległej strony, która może zabić zdalny proces.
Gilles „SO- przestań być zły”
„Powinien zostać przekazany na stronę zdalną, która może zabić proces zdalny”. - nie należy tego robić. Sygnały KILL, Ctrl + C wydaje jeden z nich, są tylko dla procesu lokalnego. Jeśli nie jest używany w procesie lokalnym, pojęcie „rzekomo” nie ma w ogóle zastosowania.
user4674453
@ user4674453 Nie. Ctrl + C nie jest sygnałem zabicia. To sygnał przerwania. Jego rolą jest powrót do interaktywnego monitu. Zabija tylko programy, które nie mają interaktywnego monitu, do którego można wrócić.
Gilles „SO- przestań być zły”
„To sygnał przerwania”. Jest to argument zabicia polecenia, a zatem sygnał zabicia. Czasami jest to nazywane sygnałem POSIX, jeśli chcesz. „Jego rolą jest powrót do interaktywnego monitu. Zabija tylko programy, które nie mają interaktywnego monitu.” Dokładnie!!! A SSH nie robi tego zgodnie z oczekiwaniami.
user4674453
1

Powinno wystarczyć, aby znaleźć drogę do killtej catkomendy.
W przypadku poniższych propozycji może być konieczne otwarcie drugiego połączenia ssh.

  • Rzadkość CTRL+zmoże być bardziej skuteczna niż CTRL+c: może odpowiadać szybciej. Następnie zawiesisz polecenie, za pomocą którego możesz go zabić kill %1lub pod jakimkolwiek numerem zadania.
    Ma to nadzieję, że nadal będziesz w stanie odczytać cokolwiek z ekranu (zalany losowy tekst binarny może łatwo zepsuć zestaw znaków).
    Jak zapamiętał Gilles, jeśli zminimalizujesz okno, prawdopodobnie system szybciej odczyta żądanie przerwania niż ty zabijesz proces. Więc zawieszenie / przerwa, zminimalizowanie, poczekaj chwilę, zmaksymalizuj ponownie, może być również rozwiązaniem.
    Oczywiście poprzez połączenie ssh oczekuję, że musisz jednak poczekać trochę czasu.

  • W innym terminalu / sesji możesz zapytać pgrep cat(czy polecenie cat zostało wywołane) i określić, czy proces cat używa więcej twojego procesora. Możesz go zidentyfikować bardziej precyzyjnie za pomocą pstree:

    pgrep cat | awk '{print "pstree -sp" $ 1}' | sh | grep sshd

    odpowiedz z wynikiem takim jak

    init (1) ───sshd (1062) ───sshd (22884) ───sshd (22951) ───bash (22957) ───cat (23131)

    W takim przypadku po zabiciu kota PID: zabij 23131

Uwaga:

Hastur
źródło
1

Miałem ten sam problem i nie byłem zadowolony z odpowiedzi tutaj, więc zagłębiłem się głębiej. Inni wspominali już, że twoje polecenie wysyła dane szybciej niż ssh może zająć, więc buforów danych i buforów nie można zatrzymać.

Aby rozwiązać ten problem, unikając buforowania, ograniczając wydajność polecenia do maksymalnej prędkości, jaką może przyjąć sesja ssh, istnieją już takie polecenia.

Skonfiguruj, najpierw sprawdź maksymalną stawkę sesji:

# Get transfer <TIME> of a large file (>10MB preferable)
/usr/bin/time -f "%e" cat <FILENAME>

# Get file <SIZE> in bytes
stat --printf="%s\n" <FILENAME>

# Calculate <RATE>
echo "<SIZE> / <TIME>" | bc

Na koniec odpowiednio dudź swoje prawdziwe polecenia.

<YOUR_COMMAND> | pv -qL <RATE>

Przykład:

/usr/bin/time -f "%e" cat large_reference_file.txt
31.26

stat --printf="%s\n" cat large_reference_file.txt
17302734

echo "17302734 / 31.26" | bc
553510

# Throttle my command to 553510B/s
cat some_other_file.txt | pv -qL 553510

Możesz nieco zmniejszyć RATE, na wypadek, gdyby twoja prędkość połączenia nieco spadała od czasu do czasu. Jeśli spadnie, zachowanie powróci do wydania, niereagującego ctrl-c.

Opcjonalny alias kota z przepustnicą:

# bash
alias tcat='tcat(){ cat $@ | pv -qL 400k ; }; tcat'

# tcsh
alias tcat 'cat \!* | pv -qL 400k'

# usage: tcat <FILENAME>

Teraz ctrl-c działa zgodnie z oczekiwaniami, natychmiast zabijając dane wyjściowe, ponieważ bardzo mało, jeśli w ogóle, jest buforowane.

Eric
źródło
catwyjście rzadko stanowi problem, w przeciwieństwie do innych programów. Autor wykorzystał to tylko jako przykład. Problem jest zwykle spowodowany przez inne oprogramowanie, które może nie być oczywiste, jeśli jest skłonny do wytworzenia dużej ilości danych wyjściowych. Użycie dowolnego rodzaju prefiksu lub komendy postfix nie jest rozwiązaniem, ponieważ jego wpisanie zajmuje trochę czasu. Wynik nie przyniesie żadnego zysku.
user4674453
0

W systemie Linux jest oprogramowanie, które rozwiązuje dokładnie ten problem (kilka innych rzeczy). Możesz także wywołać go z emulatora terminali w systemie Windows (wydaje się, że używasz systemu Windows?).

Wypróbuj mosh , zamiennik pliku binarnego SSH. Działa dokładnie tak, jak SSH (możesz to zrobić mosh user@hostnamezamiast ssh user@hostnamei działałoby dokładnie tak, jak się spodziewasz, będzie nawet przeprowadzać uwierzytelnianie klucza prywatnego itp.

Zasadniczo uruchamia oddzielny proces na serwerze, który buforuje pakiety. Więc kiedy naciśniesz Ctrl + C na mosh, przekaże to do zdalnego serwera, który następnie przestanie wysyłać dodatkowe informacje. Ponadto będzie również przewidywać wynik naciśnięć klawiszy, co pozwoli zaoszczędzić kilka milisekund za każdym razem, gdy naciśniesz klawisz.

Wada: Obecnie nie można przewijać historii w górę podczas używania mosh.

Saksham Sharma
źródło