8

I am running multiple commands on the command line separated using semi-colons:

cmd1; cmd2; cmd3

If I press Ctrl+C on the above, it would kill all commands instead of just the one which is executing currently.

kartik@kartikpc:~/junk/exp$ ls
test1  test2
kartik@kartikpc:~/junk/exp$ cat; ls
cat is running
cat is running
^C
kartik@kartikpc:~/junk/exp

But Ctrl+Z would only suspend the current process and continue with the next one.

kartik@kartikpc:~/junk/exp$ ls
test1  test2
kartik@kartikpc:~/junk/exp$ cat; ls
cat is running 
cat is running
^Z
[1]+  Stopped                 cat
test1  test2
kartik@kartikpc:~/junk/exp$

Why is there a disperancy in behaviour, and is there any way to make Ctrl+C behave like Ctrl+Z?

I'm actually running a server through tmux session as follows node app.js; $bash, and when I do a Ctrl+C to kill the server, it kills bash as well. I want to return to shell. Is there any alternative to achieve the behavior I want?

[UPDATE]

tcsh behaves the same with Ctrl+C and Ctrl+Z. It would always act on all commands just as bash is doing with onlt Ctrl+C. But bringing back the job with fg would only bring back cat and not ls.

[kartika@vm-kartika-vnc ~/junk]$ ls
file1  file2
[kartika@vm-kartika-vnc ~/junk]$ echo $SHELL
/bin/tcsh
[kartika@vm-kartika-vnc ~/junk]$ cat; ls
cat is running 
cat is running
^C
[kartika@vm-kartika-vnc ~/junk]$ cat ; ls
cat is running
cat is running
^Z
Suspended
[kartika@vm-kartika-vnc ~/junk]$ jobs
[1]  + Suspended                     cat
[kartika@vm-kartika-vnc ~/junk]$ fg
cat                                     // Pressing ctrl-d here to exit cat
[kartika@vm-kartika-vnc ~/junk]$ 

System Information:

kartik@kartikpc:~/junk/exp$ uname -a
Linux kartikpc 3.13.0-70-generic #113-Ubuntu SMP Mon Nov 16 18:34:13 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
kartik@kartikpc:~/junk/exp$ echo $SHELL
/bin/bash
1
  • Does grep SigIgn /proc/$$/status have the 4 bit on in the lowest position? That's often the case. Then you can type Control-backslash to send a SIGQUIT to kill the foreground job without making the shell discard the rest of the command line. But it may produce a core dump of the foreground job, depending on your configuration. Dec 3, 2015 at 17:18

2 Answers 2

6

You need to look up bash job controls. There is a decent explanation here: http://web.mit.edu/gnu/doc/html/features_5.html

But in a nutshell Ctrl+C will kill the commands (all of the line) and Ctrl+Z will background the running command. In your case it is backgrounding cat (supresses output and halts processing) and then continuing on to run the ls command.

You can confirm this by checking the process list and you will find your cat is still in the list.

To bring that job to the foreground look into the fg command.

2
  • I'm actually running a server through tmux as follows node app.js; $bash, and when I do a ctrl-c to kill the server, it kills bash as well. I want to return to shell. Is there any alternative to achieve the behavior I want? Dec 3, 2015 at 16:55
  • Is there any way to suspend a whole multi-line command that is separated using a semi-colon?
    – Kvothe
    Mar 8 at 19:12
0

If that node ...;$bash thing is being pushed into the pty input buffer by tmux, then a possible solution is to configure the terminal appropriately, to trap terminal interrupts in such a way that only affects the interactive shell, and to use newlines rather than ;.

stty noflsh; trap : INT

^that should handle the first two requirements.

The difference between a ; and a \n is due to the way shells read input - a ; semicolon is equivalent to a newline in that it delimits command lists, but it differs in that it does not delimit read input. For example:

prompt$ cat; echo something

this the cat process
this the cat process
^C
prompt$

But because I've configured the tty driver not to flush the input buffer on receipt of an interrupt with stty noflsh:

prompt$ cat^Jecho something

this is the cat process
this is the cat process
^C
something
prompt$

bash's readline will actually display a literal newline for the key-combo Ctrl+V then Ctrl+J rather than the escape shown above, but the effect is the same: when the shell itself effectively ignores interrupts but its children do not, you can execute interrupted lines of tty input in serial so long as the terminal itself does not discard interrupted input entirely.

You must log in to answer this question.

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