Atribui pid do processo de segundo plano Subshell para variável

4

Atualmente, estou iniciando um processo de segundo plano em um subshell e queria saber como atribuir seu número de pid a uma variável fora do escopo da subshell?
Eu tentei muitas maneiras diferentes, mas MYPID sempre permanece definido como 0 .

MYPID = 0;
({ sleep 2 & }; $MYPID=$!)
({ sleep 2 & }; echo $!) > $MYPID

A única maneira de retornar um valor é com:

$MYPID=$({ sleep 2 & }; echo $!)

No entanto, isso descarta a instrução de processo em segundo plano e só retornará um resultado após 2 segundos.

    
por zanona 24.09.2014 / 15:09

2 respostas

7

bash não deve imprimir o status do trabalho quando não é interativo.

Se isso for realmente para um bash interativo, você pode fazer:

{ pid=$(sleep 20 >&3 3>&- & echo "$!"); } 3>&1

Queremos que o stdout de sleep vá até onde estava antes, não o canal que alimenta a variável $pid . Então, salvamos o stdout outer no descritor de arquivo 3 ( 3>&1 ) e o restauramos por sleep dentro da substituição do comando. Então pid=$(...) retorna assim que echo termina porque não há mais nada com um descritor de arquivo aberto no canal que alimenta $pid .

No entanto, note que, como ele é iniciado a partir de um subshell (aqui em uma substituição de comando), o sleep não será executado em um grupo de processos separado. Portanto, não é o mesmo que executar sleep 20 & em relação a E / S para o terminal, por exemplo.

Talvez seja melhor usar um shell que suporte a geração de empregos em segundo plano deserdados , como zsh , onde você pode fazer:

sleep 20 &! pid=$!

Com bash , você pode aproximá-lo com:

{ sleep 20 2>&3 3>&- & } 3>&2 2> /dev/null; pid=$!; disown "$pid"

bash produz o [1] 21578 para stderr. Então, novamente, nós salvamos stderr antes de redirecionar para / dev / null e restaurá-lo para o comando sleep . Dessa forma, o [1] 21578 vai para /dev/null , mas o sleep é como sempre.

Se você for redirecionar tudo para / dev / null, pode simplesmente fazer:

{ apt-get update & } > /dev/null 2>&1; pid=$!; disown "$pid"

Para redirecionar somente a stdout:

{ apt-get-update 2>&3 3>&- & } 3>&2 > /dev/null 2>&1; pid=$!; disown "$pid"
    
por 24.09.2014 / 16:38
1

segunda linha não funciona

({ sleep 2 & }; $MYPID=$!)

o ( ... ) bifurca um subshell, o MYPID é definido, depois o subshell sai e seu valor é perdido.

terceira linha também não funcionou

({ sleep 2 & }; echo $!) > $MYPID

você apenas ecoa $! para um arquivo chamado 0 no diretório local.

A única resposta que posso fornecer é através de um arquivo temporário (como var não pode ser empurrar de volta)

 ( { sleep 100 & } ; echo $! > u ) > /dev/null &> /dev/null
 MYPID=$(<u)

você pode substituir u por qualquer arquivo.

    
por 24.09.2014 / 16:30