Остановка вывода из программы, запущенной в сеансе SSH СЕЙЧАС


18

проблема

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

Терминал залит информацией.

Пример того, о чем я говорю

Я хочу завершить команду как можно скорее и исправить мою программу. Мне все равно, что это печатает. Дело в том, что я нажимаю Ctrl+ CКАК МОЖНО СКОРЕЕ (в приведенном выше примере я нажал ее сразу после запуска команды), но все равно требуется время для печати всей информации, которая мне даже не нужна .

Что я пробовал

Я пытался нажать 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?
Псимон

Вы можете использовать mosh вместо ssh: mosh.mit.edu
gmatht

Ответы:


5

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

То, что вы просите, чтобы программа остановилась и данные в пути как-то исчезли. Этого не может быть, потому что он уже в пути.

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


10

Я обычно запускаю вывод, lessчтобы lessвместо него можно было убить его, используя qключ.

$ cmd | less

пример

$ cat /dev/urandom | less

   сс # 2

После нажатия q+ Enterон выйдет и вернется к своему обычному терминалу, оставив его красивым и чистым.

Почему это происходит?

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

                                    сс # 1

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

$ stdbuf -o0 <cmd>

Страница man для 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
Это на самом деле не объясняет, что происходит. В конце концов, нет никакого вовлеченного канала, так на какой буфер вы ссылаетесь?
Жиль "ТАК - перестань быть злым"

@ Жиль - извините, буфер будет буфером для экрана.
СЛМ

Какой буфер? В ядре? В xterm?
Жиль "ТАК - перестань быть злым"

@ Жиль - дай мне минуту, я ищу детали 8-)
slm

3

Есть несколько уровней буферизации. Когда вы нажимаете Ctrl+ C, программа не передает данные в терминал. Это не влияет на данные, которые эмулятор терминала еще не отображал.

Когда вы отображаете данные на очень высокой скорости, терминал не может идти в ногу и будет зависать. Вот что здесь происходит: отображение текста обходится намного дороже, чем создание этих случайных чисел. Да, даже с использованием растрового шрифта - создание случайных чисел криптографического качества по сравнению с ним намного дешевле. (Я только что попробовал на своей машине, и процесс X насыщал процессор, xtermвзяв несколько% и cat(с учетом генерации случайных чисел) едва достигнув 1%. И это с растровым шрифтом.)

Если вы хотите, чтобы это прекратилось сейчас, убейте эмулятор терминала. Если вы не хотите этого делать, хотя бы сверните окно; интеллектуальные эмуляторы терминала (такие как xterm) не будут отображать окно, которое экономит время процессора 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 не является сигналом уничтожения. Это сигнал прерывания. Его роль заключается в возвращении к интерактивной подсказке. Он убивает только те программы, в которых нет интерактивного приглашения для возврата.
Жиль "ТАК - прекрати быть злым"

«Это сигнал прерывания». Это аргумент команды kill, следовательно, это сигнал уничтожения. Иногда это называется сигналом POSIX, если хотите. «Его роль - возврат к интерактивному приглашению. Он убивает только те программы, в которых нет интерактивного приглашения для возврата». Точно!!! И SSH не делает этого, как ожидалось.
user4674453

1

Это должно быть достаточно , чтобы найти путь к killв catкоманде.
Для следующих предложений вам может понадобиться второе открытое соединение ssh.

  • Редко CTRL+zможет быть более эффективным, чем CTRL+c: он может ответить быстрее. После этого вы приостанавливаете действие команды, которую можете убить, kill %1или любой другой номер задания.
    Это в надежде на то, что вы все еще можете прочитать что-нибудь с экрана (случайный двоичный текст может легко испортить ваш набор символов).
    Как вспомнил Жиль, если вы свернули окно, вероятно, система будет быстрее читать запрос на прерывание, чем вы, чтобы завершить процесс. Так что приостановить / прервать, минимизировать, немного подождать, максимизировать снова, тоже может быть решением.
    Конечно, через ssh-соединение я ожидаю, что вам нужно подождать некоторое время.

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

    пгреп кот | 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В отличие от других программ, выходной сигнал редко является проблемой. Автор использовал это только в качестве примера. Проблема, как правило, связана с другим программным обеспечением, которое может быть неочевидным, если оно желает производить много продукции. Использование какого-либо префиксного или постфиксного команд не является решением, так как для его ввода требуется время. Там не будет никакого выигрыша в результате.
user4674453

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.