Acho que o que você está pedindo é:
echo 1 && { echo 2 & } && echo 3 && echo 4
No acima, echo 1 é executado em primeiro plano, mas echo 2 é executado em segundo plano.
Observe que && após echo 2 pode não estar fazendo o que você pensa. Considere:
$ echo 1 && { false & } && echo 3 && echo 4
1
[2] 28445
3
4
O exemplo acima mostra que echo 3 é executado mesmo que o segundo comando false retorne falha. Isso ocorre porque o código de retorno do processo em segundo plano não está disponível quando a decisão de iniciar echo 3 é tomada.
Vamos considerar seu exemplo mais realista:
compile && { run server & } && run test 1 && run test 2 && kill server
run test 1 será iniciado independentemente de o run server ter sido bem-sucedido ou falhado. Pior que isso, run test 1 pode começar antes que run server termine de configurar o servidor. Uma solução rápida é atrasar run test 1 por tempo suficiente para que você tenha certeza de que run server terminou de fazer sua configuração:
compile && { run server & } && sleep 1 && run test 1 && run test 2 && kill server
Como alternativa, você precisa saber algo sobre run server para poder testar sua configuração bem-sucedida.
Antecedentes
-
As chaves,
{...}, criam uma lista. Assim, a construção{ echo 2 & }nos permite executarecho 2com o efeito do operador&confinado apenas nos comandos da lista. -
&&é bash e lógico. O comando após o&&é executado apenas se o comando anterior for bem-sucedido, ou seja, retorna com o código 0.