How can I run multiple commands which have & in one command line?
Use ().
If you want to run them sequentially:
(myCommand1; myCommand2) &
or
(myCommand1 &) && (myCommand2 &)
If you want them to run parallel:
myCommand1 & myCommand2 &
In bash you can also use this (space behind the { and the ; are mandatory):
{ myCommand1 && myCommand2; } &
I suppose you want this:
myCommand1 & myCommand2 &
This starts myCommand1
and sends it to the background as it's followed by ampersand, then immediately starts myCommand2
and sends also this to the background, therefore releasing the shell again.
Lists
For better understanding you may substitute pipeline by command here.
A list is a sequence of one or more pipelines separated by one of the operators ;, &, &&, or ||, and optionally terminated by one of ;, &, or .
If a command is terminated by the control operator &, the shell executes the command in the background in a subshell. The shell does not wait for the command to finish, and the return status is 0. Commands separated by a ; are executed sequentially; the shell waits for each command to terminate in turn. The return status is the exit status of the last command executed.
AND and OR lists are sequences of one or more pipelines separated by the && and || control operators, respectively.
Source:man bash
Let's break that down into examples. You can build a list by combining commands and separating them with one of these: ; & && ||
:
command1 ; command2 # runs sequentially
command1 && command2 # runs sequentially, runs command2 only if command1 succeeds
command1 || command2 # runs sequentially, runs command2 only if command1 fails
command1 & command2 # runs simultaneously
You can terminate lists with one of these: ; & <newline>
.
Normally you execute a command or a list by pressing Enter, that equals <newline>
. The semicolon ;
serves the very same purpose especially in scripts. Ampersand &
however starts the command(s) in a subshell in the background, immediately releasing the shell.
You can use round ()
or curly brackets {}
to further group lists, the difference being that round brackets spawn a subshell and curly ones don't. Curly brackets need a space after the first and a semicolon or a newline before the closing bracket. For example:
# if c1 succeeds start a shell in the background
# and run c2 and c3 sequentially inside it
c1 && ( c2 ; c3 ) &
# run c1 and if it succeeds c2 sequentially as a group command
# if c1 or c2 fail run c3 in the background
{ c1 && c2 ;} || c3 &
This can get quite complicated, if you're unsure use true
and false
to test whether the construction works as expected:
$ { true && true ;} || echo 2
$ { true && false ;} || echo 2
2
Job Control
The jobs
command displays a list of the background jobs that are running or have recently been finished in the current shell. There are a number of keyboard shortcuts and commands for job control:
- Ctrl+Z types the suspend character that causes the process currently running in the foreground to be stopped, it is not terminated, but remains in the
jobs
list - Ctrl+Y types the delayed suspend character that causes the process currently running in the foreground to be stopped when it attempts to read input from the terminal
fg
=%
brings a process into the foreground starting it if necessary, you can specify the process as follows:% # last process in the jobs list %1 # 1st process in the jobs list %abc # process beginning with the string “abc” %?abc # process containing the string “abc” anywhere
bg
=%&
takes a process into the background starting it if necessary:%& # last process in the jobs list %1& # 1st process in the jobs list %abc& # process beginning with the string “abc” %?abc& # process containing the string “abc” anywhere
wait
waits for a background process to be finished and returns its termination status:wait %1 # 1st process in the jobs list
Imagine you started a lengthy process (
jobs
reveals it's number 3) and then realize you want the computer to be suspended when it finishes, plusecho
a message if the process didn't succeed:wait %3 || echo failed ; systemctl suspend