Por que o double comercial e as condições encadeadas correm em segundo plano juntas, a última?

3

Eu tenho algumas condições para executar algum trabalho em segundo plano:

condition-command && condition-command && background-job &

O problema é: eu quero que as condições sejam bloqueadas até que o trabalho seja executado, como se eu tivesse executado:

condition-command; condition-command; background-job &

Mas não é uma condição, se o comando anterior falhar, não quero que o trabalho seja executado.

Eu percebi que é assíncrono, mas não deve, na minha opinião, os dois scripts seguintes devem ser os mesmos, mas eles não:

sleep 2; echo foo & sleep 1; echo bar; wait   # prints foo, then bar: correct
sleep 2 && echo foo & sleep 1; echo bar; wait # prints bar, then foo: bug

Eu sei se eu testar a variável $? que funcionaria, ou se eu colocar a última dentro de uma subshell (mas eu perderia controles de trabalho, eu quero evitar daemons), mas eu quero saber por que bash make desta forma, onde é documentado? Existe alguma maneira de evitar esse comportamento?

Editar: Acorrentado if s é nojento, é por isso que não aceitarei isso como uma forma alternativa.
Editar 2: Conheço um subshell é possível, mas não vai funcionar para mim, vamos imaginar que eu quero executar um monte de comandos, em seguida, wait no final. Será possível se eu verificar a existência do diretório /proc/$PID , mas seria uma dor no pescoço se houver vários trabalhos.
Editar 3: A questão principal é PORQUE o bash faz onde está documentado? Se tem ou não uma solução, é um bônus!

    
por Tiago Pimenta 21.11.2014 / 19:34

2 respostas

3

Se você não quiser que o plano de fundo seja aplicado à linha inteira, use eval :

sleep 2 && eval 'sleep 10 &'

Agora, apenas o segundo comando será um trabalho em segundo plano e será um trabalho em segundo plano adequado em que você pode wait .

    
por 21.11.2014 / 20:11
1

Após a sua edição: o problema é que && tem precedência mais alta que & , então a coisa toda é agrupada em um AND list e obtém um fundo como uma unidade. Consulte Listas de Comandos no manual, embora não seja muito claro.

A menor alteração no código original que funcionaria é

if condition-command && condition-command; then background-job & fi

( é um if , mas não um encadeado).

Apenas

condition-command && condition-command && (background-job &)

deve fazer o truque.

    
por 21.11.2014 / 20:11