เชลล์ไม่แสดงคำสั่งที่พิมพ์“ รีเซ็ต” ใช้งานได้ แต่เกิดอะไรขึ้น


57

ปัญหาของฉันคือเปลือก Bash หยุดแสดงอักขระที่ฉันพิมพ์ลงไป มันจะอ่านคำสั่งว่า

ฉันเจอปัญหานี้สองสามครั้งและฉันไม่เข้าใจว่าอะไรเป็นสาเหตุ ฉันรู้วิธีแก้ปัญหา แต่ฉันไม่ชอบจริง ๆ เมื่อฉัน "เก็บของ" วิธีการของฉันออกจากปัญหา

ฉันจะอธิบายสองวิธีที่ฉันเจอปัญหานี้:

ฉันใช้กระบวนการบางอย่างhttp://pythonpaste.org/script/และบางครั้งเมื่อฉันหยุดการทำงานหรือหยุดการควบคุมกลับไปที่เชลล์ เมื่อฉันไปแล้วพิมพ์คำสั่งลงในเชลล์อักขระที่ฉันพิมพ์จะไม่แสดงขึ้นมา เมื่อฉันกด Enter คำสั่งจะถูกส่ง ตัวอย่างเช่น:

  • ฉันพิมพ์ "ls"
  • ฉันเห็นข้อความแจ้งที่ว่างเปล่าและไม่มีอะไรเพิ่มเติม
  • ฉันกด Enter และฉันได้รับรายชื่อของไฟล์ในคำอื่น ๆ : คำสั่งจะถูกดำเนินการ
  • เมื่อฉันให้คำสั่ง "รีเซ็ต" เชลล์เริ่มทำงานตามปกติอีกครั้ง

วิธีที่สองเกิดขึ้นคือเมื่อฉันให้คำสั่งเช่นนี้:

$ grep foo * -l | xargs vim

ฉันใช้ grep เพื่อค้นหาไฟล์ที่มีรูปแบบที่แน่นอนแล้วฉันต้องการเปิดไฟล์ทั้งหมดที่เป็นผลมาจาก grep มันใช้งานได้อย่างมีเสน่ห์ (แม้ว่าจะไม่เร็วอย่างที่ฉันหวังไว้) แต่เมื่อฉันออกเป็นกลุ่มเปลือกของฉันหยุดแสดงตัวละครที่ฉันพิมพ์ลงไป คำสั่งรีเซ็ตช่วยแก้ไขปัญหา

ฉันเดาว่าปัญหาทั้งสองมีเหตุผลพื้นฐาน แต่ฉันก็นิ่งงันกับสาเหตุหรือเหตุผลนั้น

การค้นหาปัญหานี้เป็นปัญหาเนื่องจากคำอธิบายนั้นค่อนข้างคลุมเครือและไม่มีคำค้นหาที่ยากนัก

แก้ไข

ให้

stty --all

คำสั่งตามคำขอของ John S. Gruber ให้เอาต์พุตต่อไปนี้ (แก้ไขช่องว่างเพื่อให้สามารถอ่านได้)

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 กำลังรันคุณไม่ต้องการ echo iคำสั่งที่ทำให้เอดิเตอร์เข้าสู่โหมดแทรกตัวอย่างเช่น การตั้งค่าเหล่านี้บอกอุปกรณ์ tty ว่าควรประมวลผลสิ่งที่คุณพิมพ์อย่างไร ในขณะที่เสียงเรียกใช้มันจะคอยดูแลการสะท้อนสิ่งที่ควรจะเป็นเสียงสะท้อน ฯลฯ
John S Gruber

ฉันมีอาการแบบเดียวกันเมื่อฉันหยุด Zope (กับ CTRL + C) เมื่อมันทำงานในเบื้องหน้าและฉันอยู่ในเซสชันการดีบัก ipdb
Mark van Lent

@ MarkvanLent ฉันคิดว่าฉันมีปัญหาเช่นกัน
Niels Bom

@JohnSGruber ฉันได้เพิ่มผลลัพธ์ของstty --allคำถามของฉัน ขอบคุณล่วงหน้า!
Niels Bom

คำตอบ:


68

เมื่อรันเชลล์หรือโปรแกรมส่วนใหญ่ในเชลล์สิ่งที่คุณพิมพ์จะสะท้อนกลับไปที่เทอร์มินัลของผู้ใช้โดยระบบย่อย tty ของเคอร์เนล มีการจัดการพิเศษอื่น ๆ เช่นกันสำหรับการลบอักขระ Ctrl + R, Ctrl + Z และอื่น ๆ

บางโปรแกรม (โดยเฉพาะอย่างยิ่งโปรแกรมแก้ไข) ที่เรียกใช้จากบรรทัดคำสั่งไม่ต้องการหรือต้องการสิ่งนี้ ด้วยเหตุผลนี้พวกเขาส่งสัญญาณเคอร์เนลด้วยการเรียก IOCTL เทียบกับอุปกรณ์ tty (terminal) ที่พวกเขาไม่ต้องการพฤติกรรมนี้ พวกเขาไม่ต้องการให้ตัวละครพิเศษทำสิ่งพิเศษเช่นกัน แต่พวกเขาขอเคอร์เนลสำหรับโหมด "ดิบ" โดยเฉพาะอย่างยิ่งเครื่องมือแก้ไขเช่นเสียงเรียกเข้าจะปิด "การตั้งค่าเสียงสะท้อน" ต่างๆ ทั้งหมดนี้ใช้กับเทอร์มินัล tty จริงบนบรรทัดอนุกรมของคอมพิวเตอร์หรือเทอร์มินัลเสมือนที่ Alt + Ctrl + F1 หรือเทอร์มินัลเสมือนจริงที่คุณได้รับเมื่อคุณเรียกใช้บางอย่างเช่น gnome-terminal ภายใต้ GUI

โปรแกรมดังกล่าวควรจะรีเซ็ตโหมดใด ๆ ที่พวกเขาเปลี่ยนแปลงบน tty เสมือนที่พวกเขาใช้ก่อนที่พวกเขาจะออกจากโปรแกรมโดยการป้อนคำสั่งออกจาก editor editor หรือโดยการรับสัญญาณ (จาก Control + C) เป็นต้น

หากพวกเขาไม่สามารถทำสิ่งนี้ได้อย่างถูกต้อง tty จะอยู่ในสถานะตลกที่คุณค้นพบ เนื่องจากโปรแกรมสามารถรีเซ็ตเทอร์มินัลไม่ได้resetคำสั่งจึงถูกเขียนขึ้นเพื่อให้ผู้ใช้สามารถกู้คืนได้

ฉันคิดว่าการอินเตอร์รัปต์ยุ่งกับซอฟต์แวร์ไพ ธ อนที่คุณใช้งานอยู่ ฉันเดาว่าโปรแกรมนั้นจะไม่ได้รับโอกาสรีเซ็ตเทอร์มินัลหรือไม่สามารถทำได้

ในกรณีที่เป็นกลุ่มเมื่อฉันเรียกใช้ตัวอย่างของคุณฉันได้รับพฤติกรรมเดียวกันกับที่คุณอธิบาย ฉันยังเห็นข้อความ "เสียงเรียกเข้า: คำเตือน: อินพุตไม่ได้มาจากเทอร์มินัล" (หายไปเมื่อคุณรีเซ็ต) นี่เป็นเพราะเสียงเรียกเข้าไม่ปกติจากเปลือก แทน 'grep' และคำสั่ง 'xargs' ได้ใช้เข้ามาตรฐานครอบครองตามปกติโดย TTY เพื่อวัตถุประสงค์ของการส่งผ่านชื่อไฟล์จากTTOgrepxargs

ในผลลัพธ์ที่คุณโพสต์จากstty -aเราจะเห็น "-echo" นอกจากนี้ยังยืนยันว่านี่เป็นปัญหา หากคุณต้องฆ่ากลุ่มในแบบที่มันไม่สามารถจัดการสัญญาณได้อย่างสง่างามคุณอาจจะเห็นปัญหาเดียวกัน

ปัญหาคือการอธิบายอื่นที่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 และอื่น ๆ ) ดังนั้นฉันจึงไม่สามารถพูดได้ว่าฉันเข้าใจอย่างถ่องแท้ แต่มันไม่ใช่วูดูอีกต่อไปขอบคุณอีกครั้ง!
Niels Bom

ให้เสร็จสมบูรณ์ฉันสามารถดำเนินการได้grep foo * -l | vim -โดยไม่มีปัญหา ดังนั้นฉันคิดว่าปัญหาไม่ได้อยู่ที่ grep และ xargs แต่มีแค่ xargs คุณเห็นด้วยไหม
Niels Bom

1
มันไม่ใช่ปัญหาของ grep หรือ xargs มันเป็นปัญหากับความจริงที่ว่า stdin ไม่ได้ถูกตั้งค่าเป็น tty อีกต่อไป สิ่งนี้ล้มเหลวเช่นกัน vi / tmp / afile1 หนึ่งในข้อมูลอ้างอิงที่กล่าวถึงเป็นกลุ่มตั้ง stdin เป็น stdout (ยังคงเป็น tty) เนื่องจาก stdin ถูกตั้งค่าเป็น / dev / null ใน situtations เหล่านี้ เมื่อเป็นเช่นนั้นกลุ่มสามารถจำและรีเซ็ตเสียงสะท้อนและการตั้งค่าอื่น ๆ แต่ไม่ได้ ฉันคิดว่านี่เป็นปัญหากับกลุ่ม
John S Gruber

สิ่งนี้มีประโยชน์มากเพราะฉันเจอสิ่งนี้ มันรู้สึกสุ่ม แต่ฉันคิดว่ามันเป็นเสมอเมื่อฉันพยายามทำบางสิ่งกับ vi ที่ไม่ได้ออกอย่างหมดจดหรือใช้ท่อ
Michael Mathews

1
ขอขอบคุณ! ในที่สุดก็หาวิธีการกู้คืนบน OS X bash หลังจาก ctrl-c ถึงgit add -p!
Steve Jansen

0

ฉันจะเริ่มผู้ใช้ใหม่ในระบบ (ฉันหมายถึงการสร้างผู้ใช้ใหม่และเข้าสู่ระบบที่นั่น) และดูว่าปัญหามี หากไม่ใช่ - แสดงว่าเป็นการตั้งค่าเทอร์มินัลหรือ X11 ของคุณ


ฉันได้เพิ่มผู้ใช้ใหม่และทดสอบด้วยgrep foo * -l | xargs vimคำสั่ง ปัญหายังคงมีอยู่ ฉันไม่เข้าใจว่าการตั้งค่า X11 ของฉันมีผลต่อวิธีการที่เทอร์มินัลของฉันตอบสนอง btw อย่างไร คุณช่วยอธิบายเรื่องนี้ให้ละเอียดหน่อยได้ไหม? ขอบคุณ!
Niels Bom
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.