Припинення виводу з програми, запущеної в сесії SSH ЗАРАЗ


18

Проблема

Я виконую команду, яка виводить багато інформації через SSH. Наприклад, я нерозумно додаю інформацію про налагодження всередині циклу, який виконується мільйон разів, або просто запускаю cat /dev/urandomдля ударів.

Термінал заповнений інформацією.

Приклад того, про що я говорю

Я хочу скасувати команду ASAP і виправити свою програму. Мені все одно, що це друкує. Тепер справа в тому, що я натискаю Ctrl+ CASAP (у прикладі вище я натискав її відразу після запуску команди), але це все ще потребує часу, щоб надрукувати всю інформацію, яка мені навіть не потрібна .

Що я спробував

Я намагався натиснути Ctrl+ Cнастільки сильно, що він мав смішні результати, коли термінал нарешті наздогнав:

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

Я також читав про Ctrl+, Sякий, мабуть , використовується для того, щоб сказати терміналу "зупинити вихід, мені потрібно наздогнати", але, мабуть, він нічого не робить.

Різні деталі

Я хотів би не змінювати команду, яку я запускаю, щоб я міг врятувати себе в будь-якій ситуації, навіть якщо я не пам’ятаю, що програма, яку я запускаю, може закінчитися так.

Мій клієнт SSH працює на Cygwin ( CYGWIN_NT-6.1-WOW64 luna 1.7.30(0.272/5/3) 2014-05-23 10:36 i686 Cygwin) у MinTTY із встановленим типом терміналу xterm-256color.

SSH-сервер працює на Debian ( Linux burza 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 i686 i686 GNU/Linux).


У якій системі ви запускаєте фактичні програми, які дають результат? Linux, Unix або Windows? Linux і UNIX повинні прийняти Ctrl-O, що означає "відкинути будь-який вихід, записаний на цей термінал".
Марк Плотнік

Сервер працює на Debian. Редагував питання. Здається, Ctrl-O також нічого не робить. Можливо, це справа клієнта?
rr-

Ви можете спробувати запустити xterm з -jопцією, щоб увімкнути прокрутку стрибків. Основна проблема полягає в тому, що пульт може надсилати дані швидше, ніж вікно терміналу може відображати їх - за замовчуванням, він повинен біттерти вміст вікна кожного разу, коли друкується новий рядок. Цілий ряд даних може бути завантажений до моменту, коли ваш Ctrl-C отримає віддалену систему, і ваша термінальна програма спробує відобразити все це.
Марк Плотнік

Просто ідея: якщо у вас є кілька точних команд, які ви, як правило, випадково виконуєте, і вони генерують велику кількість результатів, чому б просто не додати деякі псевдоніми до .bashrc?
psimon

Ви можете використовувати mosh замість ssh: mosh.mit.edu
gmatht

Відповіді:


5

Частина цього випуску буде буферною. Ви надсилаєте свій Ctrl+ Cна віддалений кінець, який перериває запущену програму. Програма існує, і оболонка надсилає символів, щоб знову показати вам підказку. Перед тим, як з'явиться підказка, на екрані спочатку з’являться всі дані, які були завантажені, і вже на шляху до вас.

Ви вимагаєте, щоб програма зупинилася, а дані в дорозі якось зникли. Це не може статися, оскільки це вже в дорозі.

Єдиний спосіб переконатися у тому, що ви не бачите цих даних, - це вийти з терміналу в кінці, а потім повторно підключитися до віддаленого пристрою - але це, мабуть, набагато більше зусиль, ніж очікування відображення даних, що завантажуються.


10

Зазвичай я запускаю висновок, lessщоб я міг його вбити lessзамість цього за допомогою qключа.

$ cmd | less

Приклад

$ cat /dev/urandom | less

   ss №2

Після натискання q+ Enterвін вийде і повернеться до нормального терміналу, залишаючи його приємним і чистим.

Чому це відбувається?

Проблема, з якою ви стикаєтесь, полягає в тому, що є буфери (для STDOUT), які ставлять у чергу з виходом вашого дисплея. Ці буфери заповнюються так швидко, що ви не можете перервати його досить швидко, щоб зупинити його.

                                    ss №1

Щоб вимкнути / обмежити цей ефект, ви можете вимкнути буферизацію STDOUT, яка повинна зробити речі трохи більш чуйними stdbuf, але, швидше за все, вам доведеться грати з цими налаштуваннями, щоб отримати речі так, як вам потрібно. Щоб розблокувати STDOUT, ви можете використовувати цю команду:

$ stdbuf -o0 <cmd>

Довідкова сторінка для stdbufдетальної інформації про ваші розпорядження:

    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.

Для приємного перегляду того, як працює буферизація, я настійно пропоную поглянути на цей Pixel Beat з назвою: буферизація в стандартних потоках . Він включає навіть приємні фотографії.

Список літератури


Це розумно до тих пір , як ви пам'ятаєте , щоб додати |lessдо cmd, який , до жаль , я часто цього не роблять. Якщо ви запускаєте cmd, потрібно ще почекати, поки не буде обчислено результати друку перед отриманням ^C.
rr-

1
Це насправді не пояснює, що відбувається. Зрештою, жодна труба не задіяна, тож про який буфер ви посилаєтесь?
Жил "ТАК - перестань бути злим"

@Gilles - вибачте, буфер був би буфером для екрана.
slm

Який буфер? У ядрі? У xterm?
Жил 'ТАК - перестань бути злим'

@Gilles - дай хвилинку, я шукаю деталі 8-)
slm

3

Існує кілька рівнів буферизації. Коли ви натискаєте клавішу Ctrl+ C, це зупиняє програму передавати дані до терміналу. Це не впливає на дані, які емулятор терміналу ще не відображався.

Коли ви показуєте дані з дуже високою швидкістю, термінал не може йти в ногу і буде відставати. Ось що тут відбувається: показ тексту набагато дорожче, ніж створення цих випадкових чисел. Так, навіть із шрифтом растрових зображень - отримання випадкових чисел із криптографічною якістю є брудом дешевим порівняно. (Я щойно спробував на своїй машині, і X процес насичував процесор, сxterm забираючи кілька відсотків і cat(на що зараховується генерація випадкових чисел), ледве досягаючи 1%. І це з шрифтом растрової карти.)

Якщо ви хочете, щоб це зараз просто припинилося, вбийте емулятор терміналу. Якщо ви не хочете цього робити, принаймні мінімізуйте вікно; інтелектуальні емулятори терміналів (наприклад, xterm) не будуть відображати вікно, що економить час процесора X, тому сміття закінчуватиме відображення швидше. Сервер X має високий пріоритет, тому це призведе до великої різниці у швидкості роботи Вашої машини, коли xterm обробляє дані у фоновому режимі.

Коли все це відбувається у віддаленій оболонці, відставання ще гірше, тому що дані, отримані, catповинні спочатку пройти через SSH-з'єднання. Ваше натискання кнопки Ctrl+ Cтакож має пройти через з'єднання SSH; він стає дещо вищим пріоритетом (він надсилається поза смугою), але це все ж потребує певного часу, протягом якого накопичується більше продукції. Немає можливості придушити дані в дорозі, не закриваючи з'єднання SSH (що можна зробити, натиснувши Enterпотім ~.).


Проблема пов'язана з SSH разом. Буфер STDOUT не повинен використовуватися в інтерактивному режимі, але SSH не може правильно працювати з інтерактивним режимом. Хоча багато транзакцій може зависати в транзакції, це SSH процес, який отримує Ctrl + C, тому він несе відповідальність за вбивство виводу, коли неможливо передати Ctrl + C у віддалений.
user4674453

@ user4674453 А? Ctrl + C не повинен вбивати локальний вихід. Це зовсім не його робота. Він повинен бути переданий у віддалений бік, що може або не може знищити віддалений процес.
Жил "ТАК - перестань бути злим"

"Це повинно бути передане у віддалений бік, що може або не може знищити віддалений процес." - це теж не передбачається. Сигнали KILL, Ctrl + C видає один з них, призначені лише для локального процесу. Якщо він не використовується для локального процесу, поняття "передбачається" взагалі не застосовується.
user4674453

@ user4674453 Ні. Ctrl + C не є сигналом вбивства. Це сигнал переривання. Її роль - повернутися до інтерактивного підказки. Це вбиває лише програми, які не мають інтерактивного підказки до якого можна повернутися.
Жил "ТАК - перестань бути злим"

"Це сигнал переривання". Це аргумент команди убивати, отже, це сигнал вбивства. Іноді його викликають як сигнал POSIX, якщо ви хочете. "Його роль полягає у поверненні до інтерактивного підказки. Він вбиває лише програми, у яких немає інтерактивного підказки для повернення." Саме !!! І SSH не робить цього, як очікувалося.
user4674453

1

Це повинно бути досить , щоб знайти шлях до killв catкоманді.
Для наступних пропозицій вам може знадобитися відкрити друге ssh-з'єднання.

  • Рідко CTRL+zможе бути ефективніше, ніж CTRL+c: вона може відповісти швидше. Після цього ви призупиняєте команду, ви можете її вбити, kill %1або будь-який її номер завдання.
    Це в надії, що ви все ще можете прочитати що-небудь з екрану (затоплений випадковий бінарний текст може легко зіпсувати ваш набір символів).
    Як пам'ятає Гілль, якщо ви мінімізуєте вікно, ймовірно, система швидше прочитає запит на переривання, ніж ви, щоб вбити процес. Тож зупиніть / перервіть, мінімізуйте, трохи почекайте, знову максимізуйте, може бути і рішенням.
    Звичайно, через ssh-з'єднання я думаю, що вам потрібно зачекати деякий час.

  • В іншому терміналі / сеансі ви можете запитати pgrep cat(якщо кот викликав команду) і визначити, що процес кішки використовує більше вашого процесора. Ви можете визначити це з більшою точністю за допомогою pstree:

    pgrep кішка | awk '{print "pstree -sp" $ 1}' | ш | grep sshd

    відповідь, як вихід

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

    У цьому випадку після того, як вам доведеться лише вбити кота PID: убийте 23131

Примітка:


1

У мене була така ж проблема, і я не був задоволений відповідями тут, тому я заглибився глибше. Інші вже згадували, що ваша команда виводить дані швидше, ніж може взяти ваш ssh, тому буфери даних та буфери не можуть бути зупинені.

Щоб виправити це, уникайте буферизації, заглушивши вихід команди до максимальної швидкості, яку може прийняти ваш сеанс ssh, для цього вже існують команди.

Налаштуйте, спочатку дізнайтеся максимальну швидкість сеансів:

# 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

Нарешті, відповідно придушіть свої реальні команди.

<YOUR_COMMAND> | pv -qL <RATE>

Приклад:

/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

Ви можете трохи знизити ЦІН у випадку, якщо швидкість з'єднання час від часу трохи зменшується. Якщо вона провалиться, поведінка повернеться до проблеми, що не реагує на ctrl-c.

Необов’язковий псевдонім котячого кота:

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

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

# usage: tcat <FILENAME>

Тепер ctrl-c працює, як очікувалося, негайно вбиваючи вихід, оскільки дуже мало буферизовано.


catвихід рідко є проблемою, на відміну від іншого програмного забезпечення. Автор використав це лише як приклад. Проблема, як правило, пов’язана з іншим програмним забезпеченням, яке може бути не очевидним, якщо воно готове давати багато результатів. Використання будь-якого типу префікса або команди постфікса не є рішенням, оскільки для його введення потрібен час. У результаті не буде жодної вигоди.
користувач4674453

0

В Linux є програмне забезпечення, яке вирішує саме цю проблему (ще пару речей). Ви також можете викликати його з емулятора терміналу в Windows (начебто ви використовуєте Windows?).

Спробуйте mosh , заміни двійкового файлу SSH. Він працює точно так само, як SSH (ви можете зробити mosh user@hostnameзамість цього, ssh user@hostnameі він буде працювати точно так, як ви очікуєте, навіть буде робити автентифікацію приватних ключів і т.д.

В основному він виконує окремий процес на сервері, який буферизує пакети. Отже, коли ви натиснете Ctrl + C на mosh, він передасть це на віддалений сервер, який потім перестане надсилати додаткову інформацію. Крім того, він також передбачить результат натискання клавіш, заощаджуючи вам пару мілісекунд щоразу, коли ви натискаєте клавішу.

Знизу: Наразі неможливо прокрутити історію під час використання mosh.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.