4
$ command1 && command2 && command3
Running command1 ...
Running command2 ...^Z
[1]+  Stopped
$ fg && command4 && wrong_command5 && command6
Running command3
Running command4

How do I cancel the wrong_command5, scheduling right_command5 instead after the termination of currently running command4?

  • 2
    Note: this is not an urgent question. – Vi. Aug 21 '14 at 1:36
  • Did you mean to say command4 && wrong_command5 (two ampersands)? – Michael Homer Aug 21 '14 at 8:02
  • @MichaelHomer, Yes. – Vi. Aug 21 '14 at 12:04
2

If command4 is currently running, it is possible to do this pretty straightforwardly:

^Z
$ fg && right_command5 && command6

This is essentially what you were already doing to start command4 in the first place. wrong_command5 and the rest will be replaced and never execute.

I think that behaviour is going to be unexpected to you, so read on for an explanation of where things don't work the way you thought they would.


However: note that your original command sequence does not do what you think it does. When you do:

$ command1 && command2 && command3
Running command1 ...
Running command2 ...^Z
[1]+  Stopped
$ fg && command4

then command2 will be resumed, but the rest of the chain will not be. Stopping command2 with Ctrl-Z means that it exits abnormally with SIGTSTP (-20). Since command2 exits non-succesfully, && short-circuits out of the chain and command3 will never run. command4 will start immediately after the end of the resumed command2.

You can watch this behaviour in action by replacing the && with ||:

$ command2 || echo Running command3, exit was $?
^Z
[1]+  Stopped                 command2
Running command3, exit was 148
$

You have to list out the entire subsequent chain of commands when you resume if you want the behaviour you're aiming for. Alternatively, if you want to be able to stop and resume whole command chains you need to run them in a subshell:

$ (command1 && command2 && command3)
^Z
$ fg

In that case, though, there's no way to intercede and replace a command at all.

  • In that case, though, there's no way to intercede and replace a command at all. -> I expect I can suspend the the chain, analyse what is currently being executed, then kill -9 the subshell, than resume execution, appending corrected remainder of the chain. – Vi. Aug 21 '14 at 12:33
  • Note: asked another question about && chains and jobs: unix.stackexchange.com/questions/151376/… – Vi. Aug 21 '14 at 12:34
1

(This answers an earlier version of the question, which was pretty different due to the omission of one character. The second command was fg && command4 & wrong_command5 && command6 originally, and it turned out that it was really meant as fg && command4 && wrong_command5 && command6. This answers the old question with the background command, see other answers for the new question variant)


The command that you want to cancel is running in the foreground, and it is also "chained" with the next command by &&. If it behaves nicely on ^C and exits with non-zero status, all is fine:

To simplify the examples, I will split this line:

$ fg && command4 & wrong_command5 && command6

into the equivalent lines:

$ fg && command4 & 
$ wrong_command5 && command6

We need to exit the foreground program wrong_command5, and can do so easily with ^C.
Then, we list the background jobs to see which one we want to wait for. The job id is used with the builtin command wait to wait for the job to terminate.
We use the wait as the start of the list which runs the replacement command, and then the following command previously used.

$ command1 && command2 && command3
Running command1 ...
Running command2 ...^Z
[1]+  Stopped
$ fg && command4 & 
$ wrong_command5 && command6
^C
$ jobs
[1]  - running    command3
[2]  + running    command4
$ wait %2 && right_command5 && command6

If wrong_command5 does not behave nicely on getting a ^C from keyboard, but on some other signal, you can use kill instead of ^C like this:

$ fg && command4 & 
$ wrong_command5 && command6
[1] 14407
^Z
[2]  + 14408 suspended  wrong_command5
$ jobs
[1]  - running    command3
[2]  + running    command4
[3]    suspended  wrong_command5
$ kill %2
[2]  + 14408 terminated  wrong_command5
$ wait %2 && right_command5 && command6
  • The question was a bit wrong: it supposed to have double && everywhere. And I need to unschedule wrong_command5 without disrupting currently running command4. – Vi. Aug 21 '14 at 12:08
  • Hmm... that's pretty different. I thought about whether you mean it that way, but the & did make sense somehow... – Volker Siegel Aug 21 '14 at 12:26
  • With & the wrong command gets executed immediately, so I can find a PID and cancel it. – Vi. Aug 21 '14 at 12:28
  • Ah... did I get it right: command4 is running, and you want to let if finish normally, but make wrong_command5 not start after command4? Makes even more sense, interesting question :) – Volker Siegel Aug 21 '14 at 12:36
  • Ok, I read the other answer, that's good... so this answer just stopped to make sense :) Do you see any reason to keep it? (I would need to add an explanation why I use the older command variant of course) – Volker Siegel Aug 21 '14 at 12:40

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.