10

In Bash, occasionally I will type in a list of commands and hit Enter, and only later realize that there is a mistake with some command near the end of the list. I know that if I press Ctrl+C it will terminate the currently running command and cancel the rest of the list. Is there any way to cancel the rest of the list without terminating the currently running command?

For example, let's say I have typed something like

foo; bar

or

foo && bar

where foo is a long-running command that it is very important not to interrupt, and bar does something irreversible and unwanted (say, shutdown -h now or rm -rf /). While foo is still running, is there a general way of telling the shell to let foo finish but not to run bar afterwards? (Yes, I could change the permissions on bar so that it's not executable, but that's not particularly convenient if bar is something like rm that I want to use in the meantime, nor will it work if I don't own bar or if bar is a builtin.)

  • You can modify the last bar command to some_command : ^bar^some_command before to be executed. – GAD3R Apr 2 '18 at 9:34
  • 3
    @GAD3R: but this will not modify current line, it will start a new one. – Arkadiusz Drabczyk Apr 2 '18 at 9:37
3

I've observed that using CtrlZ to shift the program to a background process does the trick.

foo && bar

Thanks to @Arkadiusz Drabczyk for pointing it in comments that foo; bar doesn't give control in the required way.

Then:

^Z

[1]+  Stopped                 foo

The command stops only the first task and

fg %1

This brings only task foo to the foreground and completes the task and exits.

PS: This can be checked with two scripts writing to a file. The first one sleeping for a few seconds to give time to be put back.

I'm lost on why the CtrlZ handles only the command running and leaves the rest. Would love to get to know.

  • 1
    I cannot reproduce it. What bash version do you use? I use GNU bash, version 4.3.46(1)-release (x86_64-slackware-linux-gnu). I wrote 2 bash scripts that write to different files: write1.sh: pastebin.com/rbKmdWgB and write2.sh: pastebin.com/bNx3VRws. I run them like that: ./write1.sh ; ./write2.sh. The first script echoes wrote 1 for a few times, I press C-z, it says [1]+ Stopped ./write1.sh and I can immediately see output of the second script: wrote 2 being echoed repeatedly. – Arkadiusz Drabczyk Apr 2 '18 at 20:46
  • 2
    I think the reason that this method works with command1 && command2 pipelines is that Control-z sends SIGCHLD signal to the process. It can be checked with echo $?. Bash then sees that the first process didn't finish successfully and does not execute next processes. – Arkadiusz Drabczyk Apr 2 '18 at 21:32
  • I am using GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16). Yeah, I think you are right. foo; bar cannot be controlled in the desired way. But we can do the required stop of the second process with Ctrl+Z if the command run is foo && bar. I will update the answer. Thank you for pointing it out. – Revanth Chetluru Apr 3 '18 at 5:46
  • @ArkadiuszDrabczyk doesn't Ctrl-Z send SIGTSTP? – muru Apr 3 '18 at 5:55
  • @RevanthChetluru note that bar is still suspended and shows up in jobs output, so it probably should be killed too. – muru Apr 3 '18 at 6:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.