Obtém o PID e o código de retorno de uma linha bash call

2

Imagine que temos um longo comando sleep 10 (por exemplo). Gostaríamos de executá-lo em outro servidor usando python (a biblioteca ssh paramiko para ser específica).

Eu preciso de um comando de 1 linha que inicie o comando, imprima o PID do comando e espere que ele termine e finalmente retorne o status de saída do comando.

O que eu tentei até agora:

bash -c "echo $BASHPID ; exec sleep 10" ; echo $?

Isso imprime o PID do shell, depois chama exec no comando longo e, em seguida, aguarda e imprime o status de saída. O problema é que $BASHPID imprime o PID do shell bash externo (possivelmente indicando que chamar bash -c cmd não gera realmente um novo shell?).

Se eu chamar o comando acima em três linhas, isso funciona.

bash
echo $BASHPID ; exec sleep 10
echo $?

Qualquer tentativa usando subshells também não funcionou para mim.

echo $(echo $BASHPID ; exec sleep 10) ; echo $?

Isso funciona, mas o subshell canaliza todas as suas saídas para ecoar e echo imprime tudo de uma vez, o que significa que o $BASHPID não é impresso até que o sleep termine. O PID deve ser impresso imediatamente.

    
por chub500 10.03.2017 / 16:34

2 respostas

4

Quando você executa, por exemplo:

bash -c "echo $BASHPID ; exec sleep 10"

ou

echo $(echo $BASHPID ; exec sleep 10)

seu shell atual está interpolando a variável $BASHPID antes que a segunda bash (ou subshell) a veja. A solução é impedir a expansão dessas variáveis pelo shell atual:

bash -c 'echo $BASHPID ; exec sleep 10'
    
por 10.03.2017 / 17:53
4

Isso é um comando shell que você executa sobre ssh já (interpretado pelo shell de login do usuário remoto), não é necessário iniciar outro shell em cima disso. Supondo que o shell seja parecido com Bourne ou csh:

echo "$$"; exec sleep 10

deve ser o suficiente. Não há necessidade de instalar o bash no host remoto. ssh também relatará o status de saída do comando remoto, sem necessidade de imprimi-lo. Mas se você precisar, você pode fazer:

sleep 10 & echo "$!"; wait; echo "$?"

Não para shells semelhantes a csh, já que $? é $status .

Se você não pode garantir que o shell de login do usuário remoto seja semelhante ao Bourne, você poderia fazer:

exec sh -c 'sleep 10 & echo "$!"; wait; echo "$?"'

Esse comando deve ser compatível com os shells das famílias Bourne, csh e rc, pelo menos.

    
por 10.03.2017 / 18:02