我的问题是 Bash shell 停止显示我输入的字符。但它确实读取命令。
我已经多次遇到过这个问题,但我不知道是什么原因造成的。我知道如何解决它,但我真的不喜欢用“巫术”的方式来解决问题。
我将描述遇到此问题的两种方式:
我正在运行某个进程,http://pythonpaste.org/script/有时当我停止或中断时,控制权会交还给 shell。当我在 shell 中输入命令时,我输入的字符不会显示出来。当我按下 Enter 键时,命令是已提交。例如:
- 我输入“ls”
- 我只看到一个空的提示,没有其他内容
- 我按下回车键,得到了文件列表,换句话说:命令是执行
- 当我给出“重置”命令时,shell 又开始正常工作
发生这种情况的第二种方式是当我给出如下命令时:
$ 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
答案1
当运行 shell 或 shell 中的大多数程序时,您输入的任何内容都会由内核的 tty 子系统回显到用户终端。对于擦除字符、、等,还有其他特殊Ctrl+R处理Ctrl+Z。
某些从命令行运行的程序(尤其是编辑器)不需要或不想要这个。因此,它们会向内核发出一个信号IOCTL 调用针对 tty(终端)设备,他们不希望出现这种行为。他们也不希望特殊字符执行特殊操作。相反,他们要求内核采用“原始”模式。特别是,像 vim 这样的编辑器会关闭各种“回显设置”。所有这些都适用于计算机串行线路上的真实 tty 终端,或 上的虚拟终端Alt+Ctrl+F4,或您在 GUI 下运行类似 gnome-terminal 的程序时获得的真正虚拟终端。
此类程序应该在退出之前重置它们在正在使用的虚拟 tty 上更改的任何模式,例如通过输入退出编辑器命令或获取信号(来自Ctrl+C)。
如果他们未能正确执行此操作,tty 将处于您发现的奇怪状态。由于程序可能无法重置终端,因此reset
编写该命令以允许用户恢复。
我猜想中断正在干扰您正在运行的 Python 软件。我猜想该程序没有机会重置终端,或者根本无法重置。
在 vim 的情况下,当我运行您的示例时,我得到了与您描述的相同的行为。我还看到一条消息“Vim:警告:输入不是来自终端”(重置后它会消失)。这是因为 vim 不是从 shell 正常启动的。相反,' grep
' 和 ' xargs
' 命令一直使用标准输入(通常由 tty 占用),以便将文件名从grep
tto传递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 设置。
reset
解决不清除屏幕问题的另一种方法是stty sane
。
更多参考这里,还有一个有趣的这里另一个有趣的解决方案是在https://stackoverflow.com/questions/8228831/why-does-locate-filename-xargs-vim-cause-strange-terminal-behaviour。
答案2
Shell 不显示输入的命令,我该如何修复它?
例如:如何使用reset
命令修复冻结或混乱的终端。
注意:我实际上并没有在这里回答 OP 的问题。相反,我回答的是“Shell 不显示输入的命令,我该怎么办?”这个问题,这是许多人在搜索并进入此页面时试图弄清楚的问题。
摘要:在终端中运行此命令,它将不再显示您输入的命令:
reset
您的终端将被清除并重置,您将能够再次看到输入的命令。请注意,在reset
上面输入时,您将看不到任何内容,因此在运行重置命令之前,按 + 键可能会很有用,以Ctrl清除任何现有命令或杂散字符。Creset
其他人的长答案:Shell 没有显示输入的命令,“重置”有效,但是发生了什么?
git
管道传输时不要使用寻呼机xargs
请参阅我的问题和@wjandrea 的回答:Git Grep 有时会导致终端停止显示输入的命令。
导致我们不得不输入这种奇怪状态的原因之一reset
是当您通过管道输入git
命令时,例如git grep
。 Git 使用分页器(less
查看器/分页器),它允许您上下滚动以查看长输出,例如来自git log
,但这在通过管道 ( ) 运算符将命令串联在一起时也会导致问题|
。因此,例如,在执行此命令时,请使用git --no-pager grep ...
而不是git grep ...
:
# wrong
time git branch -a --color=never | sed -e 's/[ \*]*//' \
| grep -v -e '\->' -e '^remotes' \
| xargs -n 1 -P "$(nproc)" git grep -I "STATIC_ASSERT"
# right (use git's `--no-pager` option)
time git branch -a --color=never | sed -e 's/[ \*]*//' \
| grep -v -e '\->' -e '^remotes' \
| xargs -n 1 -P "$(nproc)" git --no-pager grep -I "STATIC_ASSERT"
上面的“错误”命令运行并起作用,但随后捕获光标和文本并使我们进入无法看到正在输入的文本并且必须输入的状态reset
。
答案3
stty sane
“设置终端正常”
重新启用输入字符的回显,包括退格键等特殊字符
相比reset
,它保留了你的终端历史记录(回滚缓冲区)