289

I normally run multiple commands with something like this:

sleep 2 && sleep 3

or

sleep 2 ; sleep 3

but what if I want to run them both in the background from one command line command?

sleep 2 & && sleep 3 &

doesn't work. And neither does replacing && with ;

Is there a way to do it?

alex
  • 479,566
  • 201
  • 878
  • 984
Palace Chan
  • 8,845
  • 11
  • 41
  • 93

7 Answers7

519

Exactly how do you want them to run? If you want them to be started in the background and run sequentially, you would do something like this:

{ sleep 2; sleep 3; } &

If you want sleep 3 to run only if sleep 2 succeeds, then:

sleep 2 && sleep 3 &

If, on the other hand, you would like them to run in parallel in the background, you can instead do this:

sleep 2 & sleep 3 &

And the two techniques could be combined, such as:

{ sleep 2; echo first finished; } & { sleep 3; echo second finished; } &

Bash being bash, there's often a multitude of different techniques to accomplish the same task, although sometimes with subtle differences between them.

Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158
Kitsune
  • 9,101
  • 2
  • 25
  • 24
  • 2
    What happens if we do `sleep 2 && sleep 3 &` ? I tried it in bash and it seems to work the same way (tried with echo). – Wajahat Feb 09 '19 at 04:09
  • @HakanBaba, Yes it does indeed create a subshell in the background. – Douwe van der Leest May 21 '19 at 06:04
  • 3
    @Wajahat, Did you try `sleep 2 && echo "foo" && sleep 3 & echo "bar""` ? The `&&` operator tells the shell to execute the command before it, and only if that command executes without any error the shell executes the subsequent command. This is essentially different from `;`, because `;` lets the subsequent command execute regardless of the exit status of the previous command unless it was a fatal error. The `&` tells the shell to execute all of the "connected" commands preceding it, in the background. "connected" here means the command is part of a pipe ( `|` ) or a logical operator. – Douwe van der Leest May 21 '19 at 06:53
  • `Of these list operators, ‘&&’ and ‘||’ have equal precedence, followed by ‘;’ and ‘&’, which have equal precedence.` in bash manual. – rosshjb Jun 13 '20 at 05:40
  • For some reason this is not working for me - ```i=0;while [ $i -le 10 ]; do echo i:$i;i=$[$i+1];sleep 2;done; & j=10;while [ $j -ge 0 ]; do echo j:$j;j=$[$j-1];sleep 2;done; &``` or ```(i=0;while [ $i -le 10 ]; do echo i:$i;i=$[$i+1];sleep 2;done; &) ; (j=10;while [ $j -ge 0 ]; do echo j:$j;j=$[$j-1];sleep 2;done; &)``` gives out ```-bash: syntax error near unexpected token `&'``` error. Am i missing something? – Ira Aug 20 '20 at 00:52
  • This is not working. My first command runs `rdiff-backup` and I want to unmount the `source` when the command finishes. I put the command in backgrund like above, write to a logfile, and the next line in the script shows a log `tail -f logfile`. Now, if I cancel the `tail` it will also cancel the `rdiff-backup` which I put into background. I see this because the log will how a SIGTERM. – bomben Jul 06 '22 at 20:06
65

You need to add some parens in your last version --

(sleep 2 &) && (sleep 3 &)

or this also works --

(sleep 2 &) ; (sleep 3 &)
iagreen
  • 31,470
  • 8
  • 76
  • 90
  • 2
    Note : When a list is used with `&`, its exit status is always zero. So, the two cases above do the same thing(The shell executes both sides in turn *asynchronously*). – rosshjb Jun 13 '20 at 12:03
11

to run multiple background command you need to add & end of each command. ex: (command1 &) && (command2 &) && (command3 &)

saeed
  • 139
  • 6
  • -1. Joining bg'ed commands with `&&` accomplishes nothing, since they always return zero immediately. That is, it's the same as using `;`. What OP wants is `(command 1 && command 2) &` – André Chalella May 10 '23 at 03:08
7

The answers above use parentheses. Bash also can use braces for a similar purpose:

{ sleep 2 && sleep 3; } &

Note that the braces are more picky about syntax--the space after {, the space before }, and the final semicolon are required. In some situations the braces are more efficient because they don't fork a new subshell. In this case I don't know if it makes a difference.

Greg Reagle
  • 71
  • 1
  • 2
4

You can use the bash command substitution $(command) like this:

$(command1 ; command2) &

Note that stdin and stdout are still linked to the parent process and redirecting at least the stdout can be tricky. So alternatively you can chain the commands in a single line then pass the string to the bash command to spawn a new process which will handle the execution.

bash -c "command1 ; command2" & 

This is especially useful in a bash script when you need to run multiple commands in background.

This two statements should be equivalent. A bash process is spawn in both cases to handle the command (chain of commands) and the & at the end detaches the execution.

This time you can add &>/dev/null before the & at the end of the command to redirect at least the stdout and avoid the output on the stdout of the parent process. Something like:

bash -c "command1 ; command2" &>/dev/null &
Bemipefe
  • 1,397
  • 4
  • 17
  • 30
3

This works:

$(sleep 2 &) && sleep 3 &

Also you can do:

$(sleep 2 && sleep 3) &
higuaro
  • 15,730
  • 4
  • 36
  • 43
1

I have the same mission too. I have try (sleep2 ; fg )& sleep3 ; fg,it's working. And when you preass ctrl+c doubled,the two process can be stoppped.