Shell tidak menunjukkan perintah yang diketik, "reset" berfungsi, tetapi apa yang terjadi?

57

Masalah saya adalah bahwa Bash shell berhenti menampilkan karakter yang saya ketik di dalamnya. Itu membaca perintah sekalipun.

Saya telah menemukan masalah ini beberapa kali dan saya tidak mengerti apa penyebabnya. Saya tahu bagaimana menyelesaikannya, tapi saya benar-benar tidak suka ketika saya "voodooing" cara saya keluar dari masalah.

Saya akan menjelaskan dua cara saya menemukan masalah ini:

Saya sedang menjalankan proses tertentu, http://pythonpaste.org/script/ dan kadang-kadang ketika saya menghentikannya atau kontrol rusak diberikan kembali ke shell. Ketika saya kemudian pergi dan mengetik perintah ke shell, karakter yang saya ketik tidak muncul. Ketika saya tekan enter perintah yang disampaikan. Jadi misalnya:

  • Saya mengetik "ls"
  • Saya hanya melihat prompt kosong dan tidak lebih
  • Aku tekan enter dan aku diberi daftar dari file, dengan kata lain: perintah yang dieksekusi
  • ketika saya memberikan perintah "reset" shell mulai bekerja secara normal lagi

Cara kedua ini terjadi adalah ketika saya memberi perintah seperti ini:

$ grep foo * -l | xargs vim

Saya menggunakan grep untuk menemukan file yang memiliki pola tertentu dan kemudian saya ingin membuka semua file yang dihasilkan dari grep. Ini berfungsi seperti pesona (meskipun tidak secepat yang saya harapkan). Tetapi ketika saya keluar dari Vim, shell saya berhenti menunjukkan karakter yang saya ketik. Perintah reset menyelesaikan masalah.

Dugaan saya adalah bahwa kedua masalah memiliki alasan mendasar, tapi saya agak bingung bagaimana atau apa alasannya.

Mencari masalah ini sendiri bermasalah karena uraiannya agak kabur dan tidak memiliki istilah pencarian yang sulit untuk itu.

Sunting

Memberi

stty --all

perintah sesuai permintaan John S. Gruber memberikan output berikut (spasi putih diedit untuk dibaca)

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
Niels Bom
sumber
2
Ketika ini terjadi, silakan masukkan stty --alldan masukkan hasilnya dalam pertanyaan Anda. Echo adalah karakteristik tty yang dimatikan. Vim akan melakukan ini ketika sedang berjalan, dan itu akan menempatkan terminal dalam mode mentah juga. Ketika berhenti, seharusnya me-reset pengaturan terminal itu sendiri. Ketika vim sedang berjalan Anda tidak ingin mengulangi iperintah yang menempatkan editor ke mode penyisipan, misalnya. Pengaturan ini memberi tahu perangkat tty bagaimana seharusnya memproses apa yang Anda ketik. Sementara vim sedang berjalan, ia tetap memperhatikan apa yang harus digaungkan, dll.
John S Gruber
Saya memiliki gejala yang sama ketika saya menghentikan Zope (dengan CTRL + C) ketika sedang berjalan di latar depan dan saya dalam sesi debugging ipdb.
Mark van Lent
@ MarkvanLent Saya pikir saya juga punya masalah itu
Niels Bom
@ JohnSGruber Saya telah menambahkan output stty --allke pertanyaan saya. Terima kasih sebelumnya!
Niels Bom

Jawaban:

68

Saat menjalankan shell atau sebagian besar program di shell, apa pun yang Anda ketikkan akan kembali ke terminal pengguna oleh subsistem tty kernel. Ada penanganan khusus lainnya, juga untuk menghapus karakter, Ctrl + R, Ctrl + Z, dan sebagainya.

Program tertentu, (khususnya editor) yang dijalankan dari baris perintah tidak memerlukan atau menginginkan ini. Karena alasan ini mereka memberi sinyal kernel dengan panggilan IOCTL terhadap perangkat tty (terminal) yang tidak mereka inginkan perilaku ini. Mereka juga tidak ingin karakter khusus melakukan hal-hal khusus. Sebagai gantinya mereka meminta kernel untuk mode "mentah". Secara khusus, vim seperti editor mematikan berbagai "pengaturan gema". Semua ini berlaku untuk terminal tty nyata pada garis serial komputer, atau terminal virtual di Alt + Ctrl + F1, atau terminal benar-benar virtual yang Anda dapatkan ketika Anda menjalankan sesuatu seperti terminal gnome di bawah GUI.

Program semacam itu seharusnya mengatur ulang mode apa pun yang mereka ubah pada virtual tty yang mereka gunakan sebelum berhenti, baik dengan memasukkan perintah editor berhenti atau dengan mengambil sinyal (dari Kontrol + C) misalnya.

Jika mereka gagal melakukan ini dengan benar tty dibiarkan dalam keadaan lucu yang telah Anda temukan. Karena program dapat gagal untuk mereset terminal, resetperintah ditulis untuk memungkinkan pengguna untuk pulih.

Saya berasumsi interruptnya mengacaukan perangkat lunak python yang sedang Anda jalankan. Saya kira program itu tidak mendapatkan kesempatan untuk mengatur ulang terminal, atau gagal melakukannya.

Dalam kasus vim, ketika saya menjalankan contoh Anda, saya mendapatkan perilaku yang sama seperti yang Anda gambarkan. Saya juga melihat pesan "Vim: Peringatan: Input bukan dari terminal" (Itu hilang saat Anda mereset). Ini karena vim tidak dimulai secara normal dari shell. Alih-alih perintah 'grep' dan 'xargs' telah menggunakan input standar, biasanya ditempati oleh tty, untuk keperluan menyampaikan nama file dari greptto xargs.

Dalam output yang Anda posting dari stty -akita dapat melihat "-echo", juga mengkonfirmasi bahwa ini adalah masalahnya. Jika Anda membunuh vim sedemikian rupa sehingga tidak bisa menangani sinyal dengan anggun Anda mungkin akan melihat masalah yang sama.

Masalahnya dijelaskan di tempat lain di https://stackoverflow.com/questions/3852616/xargs-with-command-that-open-editor-leaves-shell-in-weird-state .

Solusi untuk vim case adalah menghindari xargs dan gunakan sebagai gantinya:

 vim $(grep foo * -l)

Di sini daftar file dibangun oleh shell, seperti yang dilakukan oleh xargs, tetapi shell memanggil vim, yang langsung terhubung ke tty. Ada pesan peringatan yang dikirim ke file output kesalahan, dan vim menetapkan dan mengatur ulang pengaturan tty dengan benar.

Lebih banyak referensi di sini , dan satu lagi yang menarik di sini . Solusi lain yang menarik diberikan dalam jawaban untuk https://stackoverflow.com/questions/8228831/why-does-locate-filename-xargs-vim-cause-strange-terminal-behaviour .

John S Gruber
sumber
Terima kasih atas penjelasannya. Alasan lengkap mengapa ini tidak bekerja terlihat seperti rabbithole yang cukup dalam (tty, ioctl, dll) jadi saya tidak bisa mengatakan saya mengerti sepenuhnya, tapi itu bukan voodoo lagi, jadi terima kasih lagi!
Niels Bom
Agar lengkap saya bisa menjalankannya grep foo * -l | vim -tanpa masalah. Jadi saya pikir masalahnya bukan dengan grep dan xargs, tetapi hanya dengan xargs. Apakah kamu setuju?
Niels Bom
1
Ini bukan masalah dengan grep atau xargs. Ini masalah dengan fakta bahwa stdin tidak lagi diatur ke tty. Ini juga gagal `benar | vi / tmp / afile1. Salah satu referensi menyebutkan bahwa vim menyetel stdin ke stdout (masih tty) karena stdin telah disetel ke / dev / null dalam situtations ini. Ketika itu berhasil, vim dapat mengingat dan mengatur ulang gema dan pengaturan lainnya tetapi tidak. Saya pikir ini masalah dengan vim.
John S Gruber
Ini sangat membantu karena saya mengalami ini. Rasanya acak, tetapi saya bertaruh itu selalu ketika saya mencoba melakukan sesuatu dengan vi yang tidak keluar dengan bersih atau menggunakan pipa.
Michael Mathews
1
Terima kasih! Akhirnya menemukan cara memulihkan pada bash OS X setelah ctrl-c ke git add -p!
Steve Jansen
0

Saya akan memulai pengguna baru di sistem (maksud saya membuat pengguna bersih baru dan login di sana), dan melihat apakah masalahnya ada di sana. Jika tidak - maka itu adalah terminal Anda atau pengaturan X11 Anda.

Adobe
sumber
Saya telah menambahkan pengguna baru dan menguji ini dengan grep foo * -l | xargs vimperintah. Masalahnya masih ada. Saya tidak mengerti persis bagaimana pengaturan X11 saya dapat mempengaruhi bagaimana terminal saya bereaksi btw. Bisakah Anda menguraikan itu? Terima kasih!
Niels Bom