Оболочка не показывает набранные команды, «сброс» работает, но что случилось?

57

Моя проблема в том, что оболочка Bash перестает показывать символы, которые я в нее печатаю. Это действительно читает команды все же.

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

Я опишу два способа решения этой проблемы:

Я запускаю определенный процесс, http://pythonpaste.org/script/, и иногда, когда я останавливаю это или он нарушает управление, он возвращается обратно в оболочку. Когда я иду и набираю команды в оболочке, символы, которые я печатаю, не отображаются. Когда я нажимаю ввести команды будут представлены. Так, например:

  • Я набираю "ls"
  • Я вижу только пустую подсказку и больше ничего
  • Я нажимаю войти , и я дан список файлов, другими словами: команда будет выполнена
  • когда я даю команду «сбросить», оболочка снова начинает нормально работать

Второй способ это происходит, когда я даю такую ​​команду:

$ grep foo * -l | xargs vim

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

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

Поиск этой проблемы сам по себе проблематичен, потому что описание является довольно расплывчатым и не содержит жестких условий поиска.

редактировать

Давая

stty --all

команда согласно запросу Джона С. Грубера дала следующий вывод (пробел, отредактированный для удобства чтения)

speed 0 baud;
rows 53;
columns 186;
line = 0;
intr = <undef>;
quit = <undef>;
erase = <undef>;
kill = <undef>; 
eof = <undef>;
eol = <undef>; 
eol2 = <undef>; 
swtch = <undef>; 
start = <undef>; 
stop = <undef>; 
susp = <undef>;
rprnt = <undef>; 
werase = <undef>; 
lnext = <undef>; 
flush = <undef>; 
min = 0; 
time = 0;
-parenb 
-parodd cs8 
-hupcl 
-cstopb cread 
-clocal 
-crtscts
-ignbrk 
-brkint 
-ignpar 
-parmrk 
-inpck 
-istrip 
-inlcr 
-igncr 
-icrnl 
-ixon 
-ixoff 
-iuclc 
-ixany 
-imaxbel 
-iutf8
-opost 
-olcuc 
-ocrnl 
-onlcr 
-onocr 
-onlret 
-ofill 
-ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig 
-icanon 
-iexten 
-echo 
-echoe 
-echok 
-echonl 
-noflsh 
-xcase 
-tostop 
-echoprt 
-echoctl 
-echoke
Нильс Бом
источник
2
Когда это произойдет, пожалуйста, введите stty --allи укажите результаты в своем вопросе. Эхо - это tty характеристика, которая отключается. Vim сделает это во время работы и переведет терминал в сырой режим. Когда он выходит, он должен сам сбросить настройки терминала. Когда vim работает, вы не хотите выводить iкоманду, которая переводит редактор, например, в режим вставки. Эти настройки сообщают tty устройству, как оно должно обрабатывать то, что вы печатаете. Пока vim работает, он следит за тем, что должно быть отражено, и т. Д.
John S Gruber
У меня те же симптомы, когда я останавливаю Zope (с помощью CTRL + C), когда он работает на переднем плане, и я нахожусь в сеансе отладки ipdb.
Марк ван Лент
@MarkvanLent Я думаю, что у меня тоже есть эта проблема
Niels Bom
@JohnSGruber Я добавил вывод stty --allсвоего вопроса. Заранее спасибо!
Нильс Бом

Ответы:

68

При запуске оболочки или большинства программ в оболочке все, что вы вводите, возвращается в терминал пользователя подсистемой tty ядра. Есть и другая специальная обработка для стирания символов, Ctrl + R, Ctrl + Z и так далее.

Определенные программы (в частности, редакторы), которые запускаются из командной строки, не нуждаются или не хотят этого. По этой причине они сигнализируют ядру с вызовом IOCTL против tty (терминального) устройства, что они не хотят этого поведения. Они не хотят, чтобы специальные персонажи делали особые вещи. Вместо этого они просят ядро ​​для «сырого» режима. В частности, редактор вроде vim отключает различные «настройки эха». Все это относится к реальным терминалам tty на последовательных линиях компьютера, или к виртуальным терминалам Alt + Ctrl + F1, или к действительно виртуальным терминалам, которые вы получаете, когда запускаете что-то вроде gnome-терминала под GUI.

Предполагается, что такие программы сбрасывают любые режимы, которые они изменяют в виртуальном tty, который они используют, перед тем как выйти, либо путем ввода команды редактора выхода, либо, например, путем приема сигнала (из Control + C).

Если они не могут сделать это должным образом, tty остается в забавном состоянии, которое вы обнаружили. Так как программы могут не выполнить сброс терминала, resetкоманда была написана, чтобы позволить пользователю выполнить восстановление.

Я предполагаю, что прерывание портит программное обеспечение Python, которое вы используете. Я предполагаю, что у этой программы нет возможности перезагрузить терминал или она просто не может это сделать.

В случае vim, когда я запускаю ваш пример, я получаю то же поведение, которое вы описали. Я также вижу сообщение "Vim: Предупреждение: вход не от терминала" (он сбрасывается при сбросе). Это потому, что vim обычно не запускается из оболочки. Вместо этого команды 'grep' и 'xargs' использовали стандартный ввод, обычно занятый tty, для передачи имен файлов из greptto xargs.

В опубликованном вами сообщении stty -aмы видим «-echo», также подтверждающее, что это проблема. Если вы убьете vim таким образом, что он не сможет корректно обработать сигнал, вы, вероятно, увидите ту же проблему.

Проблема описана в другом месте на https://stackoverflow.com/questions/3852616/xargs-with-command-that-open-editor-leaves-shell-in-weird-state .

Решение для случая vim - избегать xargs и использовать вместо этого:

 vim $(grep foo * -l)

Здесь список файлов создается оболочкой, как это было с xargs, но оболочка вызывает vim, которая напрямую связана с tty. В файл вывода ошибок отправлено предупреждающее сообщение, и vim корректно устанавливает и сбрасывает настройки tty.

Больше ссылок здесь и еще один интересный здесь . Другое интересное решение дано в ответе на https://stackoverflow.com/questions/8228831/why-does-locate-filename-xargs-vim-cause-strange-terminal-behaviour .

Джон С. Грубер
источник
Спасибо за подробное объяснение. Полная причина, по которой это не работает, выглядит как довольно глубокая кроличья нора (tty, ioctl и т. Д.), Поэтому я не могу сказать, что полностью понимаю, но это больше не вуду, поэтому еще раз спасибо!
Нильс Бом
Чтобы быть полным я могу выполнить grep foo * -l | vim -без проблем. Так что я думаю, что проблема не в grep и xargs, а просто в xargs. Вы бы согласились?
Нильс Бом
1
Это не проблема с grep или xargs. Это проблема с тем фактом, что stdin больше не установлен на tty. Это также не удается `true | vi / tmp / afile1. В одной из ссылок упоминается, что vim устанавливает для stdin значение stdout (все еще tty), поскольку в этих ситуациях для stdin было установлено значение / dev / null. Когда это происходит, vim может запоминать и сбрасывать эхо и другие настройки, но это не так. Я думаю, что это проблема с vim.
Джон С. Грубер
Это было очень полезно, так как я столкнулся с этим. Это казалось случайным, но я держал пари, что это всегда было, когда я пытался сделать что-то с vi, которое не выходило чисто или использовало трубу.
Майкл Мэтьюз
1
Спасибо! Наконец-то разобрался, как восстановить на OS X bash после ctrl-c to git add -p!
Стив Янсен
0

Я бы начал нового пользователя в системе (я имею в виду сделать нового чистого пользователя и войти в систему там), и посмотреть, есть ли проблема. Если нет - то это либо настройки терминала, либо настройки вашего X11.

саман
источник
Я добавил нового пользователя и проверил это с помощью grep foo * -l | xargs vimкоманды. Проблема все еще существует. Я не совсем понимаю, как мои настройки X11 могли повлиять на реакцию моего терминала, между прочим. Не могли бы вы уточнить это? Спасибо!
Нильс Бом