Make sure all non-printable bytes in your PS1 are contained within \[ \]
. Otherwise, bash will count them in the length of the prompt. It uses the length of the prompt to determine when to wrap the line.
For example, here bash counts the prompt as 19 columns wide, while the prompt displayed by the terminal is only 10 columns wide (My prompt
written in cyan, and >
written in default color):
PS1='\e[36mMy prompt\e[0m>' # bash count: 19, actual: 10
while here it only counts the prompt as 10 columns wide because it ignores the bytes between the special \[
and \]
escapes:
PS1='\[\e[36m\]My prompt\[\e[0m\]>' # bash count: 10, actual: 10
For good practice though, use tput
to generate the terminal escapes rather than hard coding them:
cyan=$(tput setaf 6) # \e[36m
reset=$(tput sgr0) # \e[0m
PS1='\[$cyan\]My prompt\[$reset\]>'
See http://mywiki.wooledge.org/BashFAQ/053, and also http://wiki.bash-hackers.org/scripting/terminalcodes for more on tput
.
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.
Best Answer
Lines in Bash history are saved as plain lines of text without any meta-information like an invocation timestamp. So it is not possible to automatically erase all the command history from a single day, because you simply can not tell any more which command was run when.
If you simply want to remove the entire command history of your current Bash session (i.e. everything that is still only in memory and not written to the disk yet), you can either clear the in-memory history buffer or replace it with the old history file's contents from the disk.
Clearing the history buffer will result in an empty in-memory history for your current session, meaning that no commands will show up if you press ↑, etc. Once you exit your Bash session, all new commands that were entered after the clearing will be appended to the history file and in your next session, you will see the complete history again, with only the range between start of your last session and the clear command missing.
Replacing the current in-memory history buffer with the history file's content from the disk will have the same final result as clearing the history buffer, except that in your current session you will have access to the old command history instead of an empty list.
If that is not helpful for you because you want to tidy up entries from previous sessions or only a partial session, the surgical method is what you need:
Synchronize your current in-memory history buffer to the history file on the disk and then open that file in a text editor and remove all the offending entries manually.
To append the history from your current session to the history file manually (because it only happens automatically when you exit your session), run this first:
After that, open the Bash history file
~/.bash_history
in your favourite text editor (as you're on a server, I'd suggest e.g.nano
) and edit the command list to your likes. The file lists all recorded commands in chronological order, newest commands last. Simply remove the offending lines and save your work.After that, you should reload the modified history into your in-memory history buffer using the command below, in order to prevent old entries from memory to be appended to the tidied history file when you exit your session: