9

Suppose you run a command which takes some time to return and want to execute a different command after it has been executed but you didn't plan this in advance.

I know that there is the option to press Ctrl + Z and then submit fg && otherCommand. However, this has two major flaws:

  1. It doesn't work if the first command is a composition of different commands (command1 && command2 or command1; command2) because then the subsequent commands of the first submitted line aren't executed.
  2. Execution of the first command is stopped while you enter the next command. With those nasty 30 second commands, the time you spend entering the next command makes up a good portion of the remaining execution time, if not all of it.

I also know that you can just type in the next command while one command is being executed and then hit Enter to sumbit it. However, this also has two major flaws:

  1. It doesn't work if the command you execute first reads from stdin.
  2. If the command you execute first produces output, you can't see what you entered.

Is there a quick way to queue up more commands while one command is being executed, possibly involving using a special terminal emulator or several terminals?

5
  • So when you are typing the second command, you want the first command to stay running; in addition, the first command may read from stdin. These two requirements seem to contradict each other: you do both "typing the second commands" and "feeding the first command" with your stdin simultaneously? Apr 30 '17 at 16:51
  • I think there are probably two different cases: the first command is either interactive (so it reads from stdin), or non-interactive (so it doesn't get in the way when you instruct the shell about the second command). Apr 30 '17 at 17:03
  • @FranklinYu I can see several ways this can be fulfilled. Maybe there is a terminal emulator which can open a new terminal window after the user pressed some shortcut and only starts executing stuff in that new terminal after execution of the command which was executed in the first terminal when the shortcut was activated terminated. Maybe there is one which has a shortcut which lets the user add commands in an extra line or a pop-up which are sent to the terminal after the current command terminated.
    – UTF-8
    Apr 30 '17 at 17:35
  • Maybe there is a ctrl. seq. which suppresses the output of the current command while you type the next command and then replays the output (both stdout and stderr) after you hit enter. Maybe there is a terminal window manager (like screen) which introduces a ctrl. seq. that does that. Maybe there is a command which misuses job control to do this (launches a new process to do the actual work and then pipes that process's output through put the new process isn't affected by ctrl + Z). My point is: There are lots of options. Probably a lot more than I can think about while writing a comment.
    – UTF-8
    Apr 30 '17 at 17:39
  • I got your point. So you may want to add to the question that you are fine with multiple terminal sessions (it seems that I'm not the only one making wrong assumptions), and that you are already using a graphic terminal emulator like GNOME Terminal or Konsole. In addition, by saying "the command you execute first reads from stdin" you are actually fine if the first command can't read certain byte like ^Z (which is not the case if, for example, the first command is a shell). May 1 '17 at 4:48
5

Press Ctrl+Z and immediately run bg. This causes the current command to keep running in the background. Then you can use fg && otherCommand to schedule otherCommand after the current one.

To make this easier, I've configured Ctrl+Z in my shell to run bg when I press it on an empty command line. See In zsh, how can I more quickly disown the foreground process? and How do you send command line apps directly to the background? ; I haven't checked if modern versions of bash make it easy to do the same.

1
  • 1
    That's weird because it says "Stopped" when Ctrl+ Z is pressed. In either case: It has the problem described in point 1 of the first list in the question.
    – UTF-8
    May 1 '17 at 11:55
1

You most likely want:

wait $pid

If you aren't running in the same shell you can't use a built in and will need a workaround. See discussion here.

3
  • Does this mean I should end all commands with an & so I get the PID of the process? Even if I did this, I couldn't wait for the process in a different terminal (using wait), so I'd have to write in the output of the previous command, again.
    – UTF-8
    Apr 30 '17 at 16:08
  • No you don't have to start them i in the background. you can send them to the background while they are running and get their pid using ps. You won't have to write the output of the previous command but yoiu will have to start the new job in the same shell, i'm not sure why that would be a problem. Apr 30 '17 at 18:02
  • I don't know how you can send commands directly to the background. I only know of the ctrl + Z and then bg method. But if I do this (which is fairly quick), I have to decide between writing in the output of the then-resumed command after entering bg and writing bg && secondCommand where otherCommand may be complex and take me quite some time to write. And if I then want to add a third command before the first one terminates, the whole thing breaks because secondCommand won't be executed if I do the exact same thing again. So I think I don't know what you're talking about.
    – UTF-8
    Apr 30 '17 at 18:33
0

Assuming the premise that you cannot open a second terminal/connection, you can run your session in a terminal multiplexer, such as screen or tmux.

Then you can easily open another session at any time to get more done while waiting for a command to finish in the current session.

This also has the benefit of keeping the session(s) alive, should the connection/emulator get interrupted for any reason.

1
  • 1
    I can keep as many concurrent terminal sessions open as I want. What feature of screen allows me to schedule future commands?
    – UTF-8
    Apr 30 '17 at 16:04
0

EDIT: I misinterpreted the question, but the technique below might still be useful to people when running commands in a bash script (so they have single PID)

This is what I use (on Linux), when command1 is printing useful output and I just want to start another process in a another shell once it's finished (that is, I don't want to background command1):

tail --pid=$command1_pid -f /dev/null; command2

where $command1_pid is the PID of the process you are waiting to finish

(I think I originally found it here: https://stackoverflow.com/a/41613532/1676393. See there for helpful other details. Such as a version that will work on Darwin (macOS))


Step by step:

  • stop command1 with Ctrl + Z
  • run ps, then look for the process corresponding to command1, and find its PID
  • then restart the process of command1 by typing fg, and in a new shell, run the above command

Like this, command2 will start in the new shell when command1 is done in the old shell.

2
  • This doesn't work for the same reason the other answers don't work: If several commands are queued, they don't have a common PID. In fact, only the command currently running has a PID at all.
    – UTF-8
    May 13 at 11:22
  • Ah you are correct, of course! I use this when my commands are in a bash script, but of course you're right... I'll leave this here in case someone finds it useful, but edit it to make it clear it doesn't work for your case?
    – postylem
    May 13 at 16:38

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.