Shell не показує команди, «скидання» працює, але що сталося?


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і поставте результати у своєму запитанні. Ехо - це ціла характеристика, яку вимкнено. Vim зробить це під час запуску, і він також переведе термінал в неочищений режим. Після завершення він повинен скинути налаштування терміналу. Коли vim працює, ви не хочете повторювати iкоманду, яка переводить редактор у режим вставки, наприклад. Ці налаштування вказують tty пристрою, як він повинен обробляти те, що ви вводите. Поки vim працює, він піклується про те, щоб повторити те, що має бути відлунне тощо.
Джон Ш Грубер

У мене такі ж симптоми, коли я зупиняю 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.

Такі програми повинні скинути будь-які режими, які вони змінюють, на віртуальну систему, яку вони використовують, перед тим, як вийти, або ввівши команду редактора виходу, або, наприклад, прийнявши сигнал (з Control + C).

Якщо вони не зможуть зробити це належним чином, tty залишиться у смішному стані, який ви виявили. Оскільки програми не можуть скинути термінал, resetкоманда була написана, щоб дозволити користувачеві відновитись.

Я припускаю, що переривання возиться з програмним забезпеченням python, яке ви працюєте. Я здогадуюсь, що ця програма не отримує шансу скинути термінал або просто не робить цього.

У випадку vim, коли я запускаю ваш приклад, я отримую таку ж поведінку, яку ви описуєте. Я також бачу повідомлення "Vim: Увага: введення не з терміналу" (воно зникає при скиданні). Це тому, що vim не запускається нормально з оболонки. Натомість команди "grep" та "xargs" використовували стандартний вхід, зазвичай зайнятий tty, для передачі імен файлів від greptto xargs.

У вашому опублікованому виході stty -aми можемо побачити "-ехо", що також підтверджує, що це проблема. Якби ви вбили 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- why-strange-terminal-behaviour .


Дякую за ретельне пояснення. Повна причина, чому це не працює, виглядає як досить глибокий кролик (tty, ioctl тощо), тому я не можу сказати, що розумію повністю, але це вже не вуду, тому ще раз дякую!
Нільс Бом

Щоб бути повноцінним, я можу виконати grep foo * -l | vim -без проблем. Тому я думаю, що проблема полягає не в grep і xargs, а лише у xargs. Чи погодились би ви?
Нільс Бом

1
Це не проблема з grep або xargs. Проблема в тому, що stdin більше не встановлений на tty. Це не вдається також "правда" vi / tmp / afile1. В одній із посилань згадується, що vim встановлює stdin на stdout (все ще tty), оскільки stdin у цих ситуаціях встановлено на / dev / null. Після цього vim може запам’ятати та скинути параметри ехо та інших налаштувань, але цього не зробити. Я думаю, це проблема з vim.
John S Gruber

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

1
Дякую! Нарешті з'ясував, як відновити на OS X bash після ctrl-c to git add -p!
Стів Янсен

0

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


Я додав нового користувача і перевірив це за допомогою grep foo * -l | xargs vimкоманди. Проблема все ще існує. Я не точно розумію, як мої настройки X11 можуть впливати на те, як мій термінал реагує на btw. Не могли б ви детальніше зупинитися на цьому? Дякую!
Нільс Бом
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.