Como obter um status de saída do processo de outra sessão do shell?

7

Suponha que eu execute um comando em uma sessão de shell, por exemplo bash -c 'apt-get update && apt-get upgrade'. Cinco minutos depois, decido sair para um lanche e percebo que esqueci de adicionar algum tipo de mecanismo de notificação para saber se a saída foi bem-sucedida ou falha.

Bem, o que eu faço agora? Se ao menos eu pudesse consultar em outro terminal o status de saída desse outro comando (ou especificamente, esse PID), talvez eu pudesse exibir algum tipo de pop-up. Portanto, a pergunta é: como posso consultar o status de saída de um processo já em execução de outro terminal?

Em outras palavras,

Dado que eu tenho um processo em execução no terminal A E seu PID é conhecido

QUANDO executo algum comando no terminal B

ENTÃO, devo saber se o processo no terminal A termina com o status de saída 0 ou com o status de saída> 1.

Sergiy Kolodyazhnyy
fonte
Então, você deseja que algo (um comando de alerta que relate o código de saída?) Seja executado assim que um processo arbitrário A especificado (PID) terminar, depois de anexar um "observador" a ele com o comando B? Não podemos assumir que A é um trabalho em segundo plano sendo executado no mesmo shell em que você mais tarde digita B, não?
Byte Commander
@ByteCommander Correct. É um trabalho em primeiro plano.
Sergiy Kolodyazhnyy 03/09/19
Eu não acho que é possível obter um código de retorno de um filho de um shell diferente. Você pode usar waitpara obter o código de um processo em segundo plano no shell atual, após o término, mas não foi possível encontrar nada que permitisse consultar outros shells. Simplesmente monitorar se um processo ainda está em execução e emitir um alerta após a saída também é trivial novamente, mas não é possível descobrir seu código de saída. A única maneira que eu poderia pensar seria em preparar os shell PROMPT_COMMANDpara armazenar o último código de saída em um arquivo temporário ou local acessível semelhante. Isso seria uma opção?
Byte Commander
@ByteCommander Nope. Sem preparar o terminal A, faça tudo do terminal B. E confie em mim, é possível.
Sergiy Kolodyazhnyy 04/09/19
1
Bem, seria uma preparação permanente (editando .bashrc uma vez), mas tudo bem. Ansioso para ler a resposta, se você encontrar uma.
Byte Commander

Respostas:

8

Use da straceseguinte maneira:

sudo strace -e trace=none -e signal=none -q -p $PID

Nem as chamadas nem os sinais do sistema são de interesse aqui, por isso dizemos stracepara ignorá-los com as -eexpressões e suprimir uma mensagem de status com -q. straceanexa ao processo com o PID $PID, aguarda que ele saia normalmente e gera seu status de saída assim:

+++ exited with 0 +++

Uma ifexpressão simples para chamar qualquer tipo de notificação pode ser:

if sudo strace -e trace=none -e signal=none -q -p $PID |& grep -q ' 0 '; then
  echo yeah
else
  echo nope
fi

Exemplo de execução

# in terminal 1
$ (echo $BASHPID;sleep 10;true)
8807
# in terminal 2
$ if sudo strace -e{trace,signal}=none -qp8807|&grep -q ' 0 ';then echo yeah;else echo nope;fi
yeah

# in terminal 1
$ (echo $BASHPID;sleep 10;false)
12285
# in terminal 2
$ if sudo strace -e{trace,signal}=none -qp12285|&grep -q ' 0 ';then echo yeah;else echo nope;fi
nope

A maior parte do crédito vai para esta resposta no U&L ; deixe um voto positivo lá se você achar isso útil.

sobremesa
fonte