Como pausar o comando quando sai alguma string?

1

Eu preciso de uma ferramenta que monitore a saída de outro comando e quando ela imprimir uma string especificada, por exemplo. "error", pára o comando monitorado. Então modifico alguns ambientes e arquivos e continuo o trabalho. É possível?

Editar: Exemplo:

Tenha o seguinte job.sh

for i in $(ls)
do
    echo file $i
    sleep 0.1
    cat $i
done

Quando executado na pasta que contém os arquivos a.txt e b.txt, quero pausar job.sh depois de imprimir file b.txt para editá-lo, depois continue job.sh e veja o novo conteúdo b.txt. Eu não posso tocar job.sh como é realmente compilado programa C. O sono simboliza que a pausa não precisa ser imediata, mas ainda assim rápida.

    
por Chocimier 13.07.2018 / 11:47

2 respostas

2
% ./mystery
a
b
c
% 

Pode-se emitir o sinal STOP para um programa e, em seguida, CONT para continuá-lo; o código TCL a seguir aguarda que b apareça na saída e, nesse ponto, interrompe o processo, que deve permanecer parado até que o usuário digite uma linha para que expect_user atue (no mínimo, uma nova linha).

#!/usr/bin/env expect
spawn -noecho ./mystery
set spid [exp_pid]
expect -ex b { exec kill -STOP $spid; send_user "STOP\n" }
expect_user -re . { exec kill -CONT $spid }
expect eof

Isso, é claro, tem todos os tipos de problemas, como se mystery fosse executado muito rapidamente, ou se a saída estivesse em buffer, etc. Eu tive que diminuir o C e desligar o buffer para que funcionasse:

% cat mystery.c
#include <stdio.h>
#include <unistd.h>
int main(void)
{
    setvbuf(stdout, (char *) NULL, _IONBF, (size_t) 0);
    printf("a\n");
    sleep(1);
    printf("b\n");
    sleep(1);
    printf("c\n");
    return 0;
}

Um programa C pode ser melhor controlado, executando-o em um depurador como gdb ; os pontos de interrupção seriam uma maneira muito mais precisa de interromper a execução em um ponto exato no código do que reagir a E / S. A depuração de símbolos ajudará, mas não é necessária:

% gdb mystery
Reading symbols from mystery...(no debugging symbols found)...done.
(gdb) quit
% otool -dtv mystery | grep callq
0000000100000f26        callq   0x100000f70
0000000100000f32        callq   0x100000f6a
0000000100000f3c        callq   0x100000f76
0000000100000f48        callq   0x100000f6a
0000000100000f52        callq   0x100000f76
0000000100000f5e        callq   0x100000f6a

Então, isso é realmente em um Mac (a desmontagem varia de acordo com a plataforma). As chamadas acima são setvbuf , printf e sleep com o endereço inicial

% otool -dtv mystery | sed 3q
mystery:
_main:
0000000100000f06        pushq   %rbp
% perl -E 'say 0x0000000100000f52 - 0x0000000100000f06'
76
% gdb mystery
Reading symbols from mystery...(no debugging symbols found)...done.
(gdb) b *main + 76
Breakpoint 1 at 0x100000f52
(gdb) r
Starting program: /Users/jhqdoe/tmp/mystery
a
b

Breakpoint 1, 0x0000000100000f52 in main ()
(gdb) 

E então você pode fazer o que for necessário e continuar o programa conforme desejado.

Outra ideia seria usar LD_PRELOAD para ajustar a forma como o programa se comporta, assumindo, é claro, que a opção mais sensata - recompilar o programa da origem - não é possível. Ainda outra opção seria corrigir o binário C para se comportar como desejado .

    
por 13.07.2018 / 17:01
0

Você pode usar read , que aguarda a entrada do usuário antes de prosseguir

Exemplo:

Este programa executa um loop e imprime a saída de ls -lhtr , aguarda a entrada do usuário (Pressione enter ou qualquer outro caractere) e depois imprime a saída e continua o processo em um loop infinito

#!/bin/bash

while (true); do
        ls -lhtr;
        read i;
done

Então, basicamente o inlace de ls -lhtr , você pode usar o comando cuja saída você precisa monitorar, assim que você terminar de modificar o ambiente e os arquivos, você pode pressionar qualquer tecla para continuar monitorando a saída do comando novamente

    
por 13.07.2018 / 12:03

Tags