Shell không hiển thị các lệnh đã nhập, các cài đặt lại, cài đặt lại, nhưng điều gì đã xảy ra?


57

Vấn đề của tôi là shell Bash dừng hiển thị các ký tự tôi nhập vào nó. Nó không đọc các lệnh mặc dù.

Tôi đã gặp vấn đề này khá nhiều lần và tôi không hiểu nguyên nhân của nó. Tôi biết làm thế nào để giải quyết nó, nhưng tôi thực sự không thích nó khi tôi "giải quyết" cách giải quyết vấn đề của mình.

Tôi sẽ mô tả hai cách tôi gặp phải vấn đề này:

Tôi đang chạy một quy trình nhất định, http://pythonpaste.org/script/ và đôi khi khi tôi dừng điều đó hoặc nó phá vỡ sự kiểm soát được đưa trở lại vỏ. Khi tôi đi và nhập lệnh vào trình bao, các ký tự tôi nhập không hiển thị. Khi tôi nhấn enter, các lệnh được gửi. Ví dụ:

  • Tôi gõ "ls"
  • Tôi chỉ thấy một dấu nhắc trống và không có gì nữa
  • Tôi nhấn enter và tôi được cung cấp một danh sách các tập tin, nói cách khác: lệnh được thực thi
  • Khi tôi đưa ra lệnh "reset", shell bắt đầu hoạt động bình thường trở lại

Cách thứ hai xảy ra là khi tôi đưa ra một lệnh như thế này:

$ grep foo * -l | xargs vim

Tôi sử dụng grep để tìm các tệp có một mẫu nhất định và sau đó tôi muốn mở tất cả các tệp kết quả từ grep. Điều này hoạt động như một sự quyến rũ (mặc dù không nhanh như tôi mong đợi). Nhưng khi tôi thoát Vim, vỏ của tôi dừng hiển thị các ký tự tôi nhập vào. Một lệnh thiết lập lại giải quyết vấn đề.

Tôi đoán là cả hai vấn đề đều có một lý do tiềm ẩn, nhưng tôi hơi bối rối về lý do đó hoặc lý do đó là gì.

Tìm kiếm cho vấn đề này tự nó có vấn đề vì mô tả là mơ hồ và không có thuật ngữ tìm kiếm khó khăn cho nó.

Biên tập

Tặng

stty --all

lệnh theo yêu cầu của John S. Gruber đã cho đầu ra sau (khoảng trắng được chỉnh sửa để dễ đọc)

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
Khi điều này xảy ra, vui lòng nhập stty --allvà đặt kết quả trong câu hỏi của bạn. Echo là một đặc tính tty đang được tắt. Vim sẽ làm điều này trong khi nó đang chạy, và nó cũng sẽ đặt thiết bị đầu cuối ở chế độ thô. Khi nó thoát, nó sẽ thiết lập lại các thiết lập đầu cuối. Khi vim đang chạy, bạn không muốn lặp lại ilệnh đưa trình soạn thảo vào chế độ chèn chẳng hạn. Các cài đặt này cho thiết bị tty biết cách xử lý những gì bạn nhập. Trong khi vim đang chạy, nó quan tâm đến việc lặp lại những gì nên được lặp lại, v.v.
John S Gruber

Tôi có các triệu chứng tương tự khi tôi dừng Zope (với CTRL + C) khi nó chạy ở nền trước và tôi đang ở trong phiên gỡ lỗi ipdb.
Mark van Chay

@MarkvanLent Tôi nghĩ tôi cũng gặp vấn đề đó
Niels Bom

@JohnSGruber Tôi đã thêm đầu ra stty --allcho câu hỏi của mình. Cảm ơn trước!
Niels Bom

Câu trả lời:


68

Khi chạy shell hoặc hầu hết các chương trình trong shell, bất cứ thứ gì bạn gõ đều được đưa trở lại thiết bị đầu cuối của người dùng bởi hệ thống con tty của kernel. Ngoài ra còn có cách xử lý đặc biệt khác để xóa các ký tự, Ctrl + R, Ctrl + Z, v.v.

Một số chương trình, (cụ thể là trình soạn thảo) chạy từ một dòng lệnh không cần hoặc không muốn điều này. Vì lý do này, họ báo hiệu hạt nhân bằng một cuộc gọi IOCTL đối với thiết bị tty (thiết bị đầu cuối) mà họ không muốn hành vi này. Họ cũng không muốn những nhân vật đặc biệt làm những điều đặc biệt. Thay vào đó, họ yêu cầu kernel cho chế độ "thô". Cụ thể, vim của trình soạn thảo sẽ tắt nhiều "cài đặt tiếng vang" khác nhau. Tất cả điều này áp dụng cho các thiết bị đầu cuối tty thực trên các dòng nối tiếp của máy tính hoặc các thiết bị đầu cuối ảo tại Alt + Ctrl + F1 hoặc các thiết bị đầu cuối ảo thực sự bạn có được khi bạn chạy một cái gì đó như thiết bị đầu cuối gnome trong GUI.

Các chương trình như vậy được cho là để thiết lập lại bất kỳ chế độ nào chúng thay đổi trên tty ảo mà chúng đang sử dụng trước khi thoát, bằng cách nhập lệnh thoát khỏi trình soạn thảo hoặc bằng cách lấy tín hiệu (từ Control + C) chẳng hạn.

Nếu họ không làm điều này đúng cách, tty sẽ bị bỏ lại trong trạng thái buồn cười mà bạn đã phát hiện ra. Vì các chương trình có thể không thiết lập lại thiết bị đầu cuối, resetlệnh đã được viết để cho phép người dùng khôi phục.

Tôi giả sử rằng ngắt đang gây rối với phần mềm python bạn đang chạy. Tôi đoán rằng chương trình đó không có cơ hội để thiết lập lại thiết bị đầu cuối, hoặc đơn giản là không làm như vậy.

Trong trường hợp vim, khi tôi chạy ví dụ của bạn, tôi nhận được cùng một hành vi mà bạn mô tả. Tôi cũng thấy một thông báo "Vim: Cảnh báo: Đầu vào không phải từ thiết bị đầu cuối" (Nó sẽ biến mất khi bạn đặt lại). Điều này là do vim không bắt đầu bình thường từ vỏ. Thay vào đó, các lệnh 'grep' và 'xargs' đã được sử dụng đầu vào tiêu chuẩn, thường được sử dụng bởi tty, cho mục đích chuyển tên tệp từ greptto xargs.

Trong đầu ra được đăng của bạn từ stty -achúng tôi có thể thấy "-echo", cũng xác nhận rằng đây là vấn đề. Nếu bạn giết vim theo cách không thể xử lý tín hiệu một cách duyên dáng thì có lẽ bạn sẽ gặp vấn đề tương tự.

Vấn đề được mô tả ở nơi khác tại https://stackoverflow.com/questions/3852616/xargs-with-command-that-open-editor-leaves-shell-in-weird-state .

Một giải pháp cho trường hợp vim là tránh xargs và sử dụng thay thế:

 vim $(grep foo * -l)

Ở đây, danh sách các tệp được tạo bởi shell, như đã có bởi xargs, nhưng shell đang gọi vim, được kết nối trực tiếp với tty. Có thông báo cảnh báo được gửi đến tệp đầu ra lỗi, vim đặt và đặt lại chính xác các cài đặt tty.

Thêm tài liệu tham khảo ở đây , và một trong những thú vị khác ở đây . Một giải pháp thú vị khác được đưa ra trong câu trả lời cho https://stackoverflow.com/questions/8228831/why-does-locate-filename-xargs-vim-cause-strange-terminal-behaviour .


Cảm ơn đã giải thích cặn kẽ. Lý do hoàn toàn tại sao điều này không hoạt động trông giống như một con thỏ khá sâu (tty, ioctl, v.v.) vì vậy tôi không thể nói tôi hiểu hoàn toàn, nhưng nó không còn tốt nữa, vì vậy xin cảm ơn một lần nữa!
Niels Bom

Để được hoàn thành tôi có thể thực hiện grep foo * -l | vim -mà không có vấn đề. Vì vậy, tôi nghĩ rằng vấn đề không nằm ở grep và xargs, mà chỉ với xargs. Bạn có đồng ý không
Niels Bom

1
Đó không phải là vấn đề với grep hoặc xargs. Đó là một vấn đề với thực tế là stdin không còn được đặt thành tty. Điều này cũng thất bại `đúng | vi / tmp / afile1. Một trong những tài liệu tham khảo đề cập rằng vim đặt stdin thành stdout (vẫn là tty) vì stdin đã được đặt thành / dev / null trong các sơ đồ này. Khi đó, vim có thể nhớ và đặt lại tiếng vang và các cài đặt khác nhưng không. Tôi nghĩ rằng đây là một vấn đề với vim.
John S Gruber

Điều này rất hữu ích khi tôi gặp phải vấn đề này. Nó cảm thấy ngẫu nhiên, nhưng tôi cá rằng đó luôn là khi tôi cố gắng làm điều gì đó với vi không thoát ra một cách sạch sẽ hoặc sử dụng một đường ống.
Michael Mathews

1
Cảm ơn bạn! Cuối cùng đã tìm ra cách phục hồi trên bash OS X sau khi ctrl-c tới git add -p!
Steve Jansen

0

Tôi sẽ bắt đầu một người dùng mới trên hệ thống (ý tôi là tạo một người dùng sạch mới và đăng nhập vào đó) và xem vấn đề có ở đó không. Nếu không - thì đó là thiết bị đầu cuối của bạn hoặc cài đặt X11 của bạn.


Tôi đã thêm một người dùng mới và kiểm tra điều này bằng grep foo * -l | xargs vimlệnh. Vấn đề vẫn còn tồn tại. Tôi không hiểu chính xác làm thế nào các cài đặt X11 của tôi có thể ảnh hưởng đến cách thiết bị đầu cuối của tôi phản ứng btw. Bạn có thể giải thích về điều đó? Cảm ơn!
Niels Bom
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.