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.
Keeping track of the PID
and killing it from the shellscript works for me in a live system of Ubuntu 16.04.1 LTS with the Xenial kernel and also in an up to date installed system with Ubuntu 16.04 LTS (and the Xenial kernel).
#!/bin/bash
echo "Starting Nautilus"
nautilus --no-desktop ~/Downloads & pid=$!
echo "pid=$pid"
ps -A|grep "$pid"
read -p "Press Enter when you are ready to kill the Nautilus window"
kill "$pid"
sync
echo "Checking that the process is gone"
ps -A|grep "$pid"
Edit:
It works, when killed like this, but when closed with the x control button, the process is still alive, which is a problem with Nautilus.
But if you use Thunar instead of Nautilus, the process will be killed, when the window is closed with the x button. So I suggest to switch file browser for this task,
#!/bin/bash
echo "Starting Thunar"
thunar ~/Downloads
echo "Checking that the process is gone"
ps -A|grep "thunar"
Best Answer
As I mentioned in my comment there are some vital pieces missing here and these commands together don't quite make sense, but I will go over them.
if [ ! -w "." ]
:.
represents the current directory.-w
tests if it is writeable.!
negates the test (so the statement returns true if the directory is not writeable vs the other way around).ps -d | grep -ic -e firefox -e gedit
:ps -d
prints all processes minus session starters.grep
searches the piped output fromps
for patterns (which we'll get to in a minute).-i
makes the search case insensitive.-c
outputs a count of the matches instead of the actual matches.-e
takes the search expressions. In this casefirefox
andgedit
. So if neither FF nor gedit is running the command will output 0. If one of them is running it will output 1. If both are running it will output 2.firefox &
: Start firefox.&
forces the process into the background.firefoxPid=$!
: In a bash shell script$!
holds the job number of the last background command.firefoxPid
is a variable. So what's happening here is the job number of the last background command (which happens to be firefox's) is stored to a variable namedfirefoxPid
.