106

My problem is that the Bash shell stops showing the characters I type into it. It does read the commands though.

I've come across this problem quite a few times and I don't understand what causes it. I know how to solve it, but I really don't like it when I'm "voodooing" my way of out of problems.

I'll describe the two ways I've come across this problem:

I'm running a certain process, http://pythonpaste.org/script/ and sometimes when I stop that or it breaks control is given back to the shell. When I then go and type commands into the shell, the characters I type don't show up. When I press enter the commands are submitted. So for example:

  • I type "ls"
  • I only see an empty prompt and nothing more
  • I press enter and I'm given a listing of the files, in other words: the command is executed
  • when I give the "reset" command the shell starts working normally again

The second way this happens is when I give a command like this:

$ grep foo * -l | xargs vim

I use grep to find files that have a certain pattern and then I want to open all the files that result from the grep. This works like a charm (although not as fast as I'd hoped). But when I exit Vim my shell stops showing the characters I type into it. A reset command resolves the problem.

My guess is that both problems have an underlying reason, but I'm kind of stumped on how or what that reason is.

Searching for this problem is itself problematic because the description is kind of vague and has no hard search-terms for it.

Edit

Giving the

stty --all

command as per John S. Gruber's request gave the following output (whitespace edited for readability)

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
7
  • I'd start a new user on the system (I mean make a new clean user and login there), and see if the problem is there. If it's not - then it's either Your terminal or Your X11 settings.
    – Adobe
    Aug 3, 2012 at 14:43
  • 2
    When this happens please enter stty --all and put the results in your question. Echo is a tty characteristic that is being turned off. Vim will do this while it is running, and it will put the terminal in raw mode, too. When it quits it should reset the terminal settings itself. When vim is running you don't want to echo the i command which puts the editor into insert mode, for example. These settings tell the tty device how it should be processing what you type. While vim is running it takes care of echoing what should be echoed, etc. Aug 3, 2012 at 20:00
  • I have the same symptoms when I stop Zope (with CTRL+C) when it's running in the foreground and I'm in an ipdb debugging session. Aug 3, 2012 at 20:33
  • @MarkvanLent I think I've got that problem too
    – Niels Bom
    Aug 6, 2012 at 8:09
  • @JohnSGruber I've added the output of stty --all to my question. Thanks in advance!
    – Niels Bom
    Aug 6, 2012 at 8:14

3 Answers 3

103

When running a shell or most programs in a shell anything you type is echo'd back to the user's terminal by the kernel's tty subsystem. There's other special handling, too, for erase characters, Ctrl+R, Ctrl+Z, and so on.

Certain programs, (editors in particular) that run from a command line don't need or want this. For this reason they signal the kernel with an IOCTL call against the tty (terminal) device that they don't want this behaviour. They don't want special characters to do special things, either. Instead they ask the kernel for a "raw" mode. In particular, editor's like vim turn off various "echo settings". All this applies to real tty terminals on a computer's serial lines, or the virtual terminals at Alt+Ctrl+F4, or the really virtual terminals you get when you run something like gnome-terminal under a GUI.

Such programs are supposed to reset any modes they change on the virtual tty they are using before they quit, either by entering a quit editor command or by taking a signal (from Ctrl+C) for example.

If they fail to do this properly the tty is left in the funny state you have discovered. Since programs can fail to reset the terminal, the reset command was written to allow the user to recover.

I assume the interrupt is messing with the python software you are running. I'd guess that that program isn't getting a chance to reset the terminal, or is simply failing to do so.

In the vim case, when I run your example I get the same behaviour you describe. I also see a message "Vim: Warning: Input is not from a terminal" (It goes away when you reset). This is because vim isn't started normally from the shell. Instead the 'grep' and 'xargs' commands have been using the standard input, normally occupied by the tty, for purposes of passing the file names from grep tto xargs.

In your posted output from stty -a we can see "-echo", also confirming that this is the problem. If you were to kill vim in such a way that it couldn't handle the signal gracefully you would probably see the same problem.

The problem is described elsewhere at https://stackoverflow.com/questions/3852616/xargs-with-command-that-open-editor-leaves-shell-in-weird-state.

A solution for the vim case is avoid xargs and use instead:

vim $(grep foo * -l)

Here the list of files is constructed by the shell, as it had been by xargs, but the shell is calling vim, which is directly connected to the tty. There is warning message sent to the error output file, and vim sets and resets the tty settings correctly.

An alternative to reset that doesn't clear the screen is stty sane .

More references here, and another interesting one here. Another interesting solution is given in an answer to https://stackoverflow.com/questions/8228831/why-does-locate-filename-xargs-vim-cause-strange-terminal-behaviour.

7
  • Thanks for the thorough explanation. The complete reason why this does not work looks like a pretty deep rabbithole (tty, ioctl, etc) so I can't say I understand completely, but it's not voodoo anymore, so thanks again!
    – Niels Bom
    Aug 7, 2012 at 15:46
  • To be complete I can execute grep foo * -l | vim - without problems. So I think the problem is not with grep and xargs, but just with xargs. Would you agree?
    – Niels Bom
    Aug 7, 2012 at 15:55
  • 1
    It's not a problem with grep or xargs. It's a problem with the fact that stdin is no longer set to the tty. This fails as well `true | vi /tmp/afile1. One of the references mentions that vim sets stdin to stdout (still the tty) because stdin has been set to /dev/null in these situtations. When it does that vim could remember and reset the echo and other settings but doesn't. I think this is a problem with vim. Aug 7, 2012 at 19:11
  • This was very helpful as I have run into this. It felt random, but I bet it was always when I was trying to do something with vi that didn't exit cleanly or used a pipe. Oct 7, 2014 at 3:49
  • 1
    Thank you! Finally figured out how to recover on OS X bash after a ctrl-c to git add -p! Nov 26, 2016 at 22:11
24

Shell does not show typed-in commands, what do I do to fix it?

ie: how to fix a frozen or messed up terminal with the reset command.

Note: I don't actually answer the OP's question here. Rather, I am answering the question "Shell does not show typed-in commands, what do I do?", which is what many people are trying to figure out when they search and land on this page.

Summary: run this in the terminal which won't show the commands you type anymore:

reset

Your terminal will be cleared and reset, and you'll be able to see typed commands again. Note that while typing reset above, you won't be able to see anything, so it may be useful to press Ctrl + C before typing reset to clear any existing commands or stray characters before running the reset command.

Long answer from someone else: Shell does not show typed in commands, "reset" works, but what happened?

Don't use a pager when piping to git from xargs

See my question and @wjandrea's answer here: Git Grep sometimes makes terminal stop showing typed commands.

One of the causes of getting into this weird state where we have to type reset is when you pipe into git commands, such as git grep. Git uses a pager (the less viewer/pager), which allows you to scroll up and down to view long output such as from git log, but which can also cause problems when stringing commands together via the pipe (|) operator. So, for instance, when doing this command, use git --no-pager grep ... instead of 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"

The "wrong" command above runs and works, but then captures the cursor and text and gets us into the state where we can't see text we are typing and we have to type reset.

18

stty sane to "set terminal sane"

to re-enable echoing of input characters, including special chars like backspace

compared to reset, it keeps your terminal history (scrollback buffer)

3
  • stty echo might only fix part of the problem. e.g. in my case I do see what I type, but hitting backspace does not work as expected.
    – MoonLite
    Nov 24, 2020 at 8:55
  • 1
    stty sane usually seems to fix everything for me. You can see what you type again and backspace and control characters etc. seem to work. Also the terminal is not cleared so you can still scroll up. See man stty for details on sane.
    – MoonLite
    Nov 24, 2020 at 9:01
  • 1
    When using reset the terminal is reinitialized. It is cleared (no scrolling up to see previous output), and might also resize window etc. In other words it might have more unintended side effects beside just fixing your invisible text problem. It is probably the safest way to fix everything but just be prepared you might lose something.
    – MoonLite
    Nov 24, 2020 at 9:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .