Fundo:
Estou escrevendo um script de teste para um software de biologia computacional. O software que estou testando pode levar dias ou até semanas para ser executado, por isso possui uma funcionalidade de recuperação integrada, no caso de falhas no sistema ou falhas de energia.
Estou tentando descobrir como testar o sistema de recuperação. Especificamente, não consigo descobrir uma maneira de "travar" o programa de maneira controlada. Eu estava pensando em, de alguma forma, cronometrar uma instrução SIGKILL para executar após algum tempo. Provavelmente, isso não é o ideal, pois não é garantido que o caso de teste execute a mesma velocidade todas as vezes (ele é executado em um ambiente compartilhado); portanto, seria difícil comparar os logs com a saída desejada.
Este software imprime uma linha para cada seção de análise concluída.
Questão:
Eu queria saber se havia uma maneira boa / elegante (em um script de shell) para capturar a saída de um programa e depois matar o programa quando uma determinada linha / # de linhas é produzida pelo programa?
Respostas:
Um script de wrapper como este é uma abordagem padrão. O script executa o programa em segundo plano e depois faz um loop, verificando o arquivo de log a cada minuto em busca de alguma sequência. Se a string for encontrada, o programa em segundo plano será eliminado e o script será encerrado.
fonte
Se o seu programa for finalizado no SIGPIPE (que é a ação padrão), deve ser suficiente direcionar a saída para um leitor que sairá ao ler essa linha.
Portanto, pode ser tão simples quanto
Se você deseja suprimir a saída padrão, use
Da mesma forma, se alguém quiser parar após um certo número de linhas, poderá usar a cabeça no lugar de sed, por exemplo
O tempo exato de pelo que a matança ocorre faz depender do comportamento de buffer do terminal como stardt sugere nos comentários.
fonte
sed
término. O OP diz "Este software imprime uma linha para cada seção de análise concluída". Isso pode significar que o programa completará uma seção extra! Prova de conceito:{ echo 1; sleep 3; >&2 echo peekaboo; sleep 3; echo 2; } | sed -e '/1/q'
. Veja esta resposta . Solução possível:( program & ) | sed -e '/Suitable text from the line/q'; killall program
. Faça sua resposta ciente da falha e eu revogarei meu voto negativo.Como alternativa à resposta do dmckee, o
grep
comando com a-m
opção (consulte, por exemplo, esta página de manual ) também pode ser usado:para parar quando uma linha correspondente ao texto for encontrada ou
aguardar 10 linhas que não correspondem ao texto fornecido.
fonte
Você pode usar
expect(1)
para assistir ao stdout de um programa e executar ações predefinidas em alguns padrões.Ou um one-liner para incorporar em outro script:
Observe que o
expect
comando não vem com todos os sistemas operacionais por padrão. Pode ser necessário instalá-lo.fonte
set timeout -1
para definir o tempo limite indefinido, caso contrário, tudo será fechado comexpect
o tempo limite padrão de 10s.Você pode usar uma declaração "while":
Você precisa canalizar a saída do seu software (ou de seus logs) e, em seguida, para cada nova linha, fazer um teste de condição e executar kill -KILL. Por exemplo (eu testei com / var / log / messages como o arquivo de log):
Ou com o software diretamente:
Você precisa substituir o caminho do log / nome do aplicativo, a linha a ser correspondida e o PID a ser eliminado (você também pode usar o killall).
Boa sorte com seu software,
Hugo,
fonte