Shell不显示键入的命令,“重置”有效,但是发生了什么?


57

我的问题是Bash shell停止显示我键入的字符。它确实会读取命令。

我已经多次遇到此问题,但我不知道是什么原因引起的。我知道如何解决它,但是当我“伏案”解决问题的方式时,我真的不喜欢它。

我将描述遇到这个问题的两种方式:

我正在运行一个特定的进程,http://pythonpaste.org/script/,有时当我停止该进程或该进程中断时,控制权将交还给Shell。然后,当我在外壳中键入命令时,我键入的字符不会显示。当我按Enter键时,命令提交。因此,例如:

  • 我输入“ ls”
  • 我只看到一个空的提示,仅此而已
  • 我按Enter键,然后得到文件列表,换句话说:该命令执行
  • 当我发出“重置”命令时,外壳再次开始正常工作

发生这种情况的第二种方式是当我给出如下命令时:

$ grep foo * -l | xargs vim

我使用grep查找具有特定模式的文件,然后我想打开grep生成的所有文件。这就像一种魅力(尽管没有我希望的那样快)。但是当我退出Vim时,我的shell停止显示我键入的字符。重置命令可以解决此问题。

我的猜测是,这两个问题都有根本原因,但我对这个原因的方式或原因感到困惑。

搜索这个问题本身就是有问题的,因为描述有点含糊,没有硬性的搜索条件。

编辑

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将在运行时执行此操作,并且也会将终端置于原始模式。退出时,应自行重置终端设置。例如,在vim运行时,您不希望回显i使编辑器进入插入模式的命令。这些设置告诉tty设备应该如何处理您键入的内容。在运行Vim需要呼应应该怎样回应,等护理
约翰·格鲁伯小号

当Zope在前台运行且处于ipdb调试会话时,我停止Zope(使用CTRL + C)时,我有相同的症状。
Mark van Lent 2012年

@MarkvanLent我想我也遇到了这个问题
Niels Bom

@JohnSGruber我已将输出添加stty --all到我的问题中。提前致谢!
Niels Bom 2012年

Answers:


68

当运行外壳程序或外壳程序中的大多数程序时,您键入的任何内容都会被内核的tty子系统回显到用户终端。对于擦除字符,Ctrl + R,Ctrl + Z等,还有其他特殊处理。

从命令行运行的某些程序(尤其是编辑器)不需要或不需要它。因此,他们通过对tty(终端)设备的IOCTL调用向内核发出信号,表示他们不希望这种行为。他们也不希望特殊角色做特殊的事情。相反,他们向内核请求“原始”模式。特别是,像vim这样的编辑器会关闭各种“回声设置”。所有这些都适用于计算机串行线路上的真实tty终端,或Alt + Ctrl + F1处的虚拟终端,或在GUI下运行诸如gnome-terminal之类的操作时获得的真实虚拟终端。

此类程序应该在退出之前重置它们正在使用的虚拟tty上更改的任何模式,例如,通过输入退出编辑器命令或获取信号(来自Control + C)。

如果他们不能正确执行此操作,则tty会处于您发现的有趣状态。由于程序可能无法重置终端,reset因此编写了该命令以允许用户恢复。

我认为该中断使您正在运行的python软件陷入混乱。我猜该程序没有机会重置终端,或者只是没有这样做。

在vim的情况下,当我运行您的示例时,我得到的行为与您描述的相同。我还看到一条消息“ Vim:警告:输入不是来自终端”(重置后消失)。这是因为vim不能从shell正常启动。取而代之的是,'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)

这里的文件列表是由shell构造的,就像xargs一样,但是shell调用的是vim,它直接连接到tty。有一条警告消息发送到错误输出文件,并且vim正确设置并重置了tty设置。

更多的引用在这里,另一个有趣的一个位置。另一个有趣的解决方案是对https://stackoverflow.com/questions/8228831/why-does-locate-filename-xargs-vim-cause-strange-terminal-behaviour的回答。


感谢您的详尽解释。不能执行此操作的完整原因看起来像是一个很深的兔子洞(tty,ioctl等),因此我不能说我完全理解,但现在不再是巫毒教了,所以再次感谢!
Niels Bom 2012年

完整来说,我可以grep foo * -l | vim -毫无问题地执行。所以我认为问题不在于grep和xargs,而在于xargs。你同意吗?
Niels Bom 2012年

1
grep或xargs都不是问题。stdin不再设置为tty这是一个问题。这同样会失败`true | vi / tmp / afile1。参考文献之一提到vim将stdin设置为stdout(仍然是tty),因为在这些情况下stdin已设置为/ dev / null。这样做时,vim可以记住并重置回显和其他设置,但是不可以。我认为这是vim的问题。
约翰·格鲁伯

这对我很有帮助,因为我碰到了这一点。感觉是随机的,但是我敢打赌,总是在我尝试用vi进行某些操作时会干净退出或使用管道的情况。
Michael Mathews 2014年

1
谢谢!终于弄清楚了如何在ctrl-c到git add -p!之后在OS X bash上恢复!
史蒂夫·詹森

0

我将在系统上启动一个新用户(我的意思是创建一个新的干净用户并在那里登录),然后查看问题是否在那里。如果不是,则为您的终端或X11设置。


我添加了一个新用户,并使用grep foo * -l | xargs vim命令对其进行了测试。问题仍然存在。我不太了解X11的设置如何影响终端的反应。您能详细说明一下吗?谢谢!
Niels Bom 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.