Como você implementa totais de saída de uso gerados por um programa em um script para que eles continuem funcionando corretamente através de execução repetida?

2

Eu tenho um script com um pipeline onde os dados são limitados por um programa. A cada 20 minutos, um status de transferência é enviado em stderr , e eu simplesmente redireciono isso para um arquivo:

command | cstream -t -512k -T 1200 -B 64m 2>>/home/user/totals.log | command

Também posso enviar um sinal SIGUSR1 para cstream ( kill -s 10 PID ) e produziria exatamente a mesma saída de quando eu defini um intervalo como eu fiz, e uma linha é adicionada ao arquivo. A ideia é que você pode definir o intervalo e também consultar um status sob demanda. A saída é formatada assim com um único caractere de espaço em branco e terminada com uma nova linha:

...
1931255808 B 1.8 GB 3683.6 s (1:01 h) 524289 B/s 512.00 KB/s
2560401408 B 2.4 GB 4883.6 s (1:21 h) 524289 B/s 512.00 KB/s
3189547008 B 3.0 GB 6083.6 s (1:41 h) 524289 B/s 512.00 KB/s
3818692608 B 3.6 GB 7283.6 s (2:01 h) 524289 B/s 512.00 KB/s
4447838208 B 4.1 GB 8483.6 s (2:21 h) 524289 B/s 512.00 KB/s
10829824 B 10.3 MB 20.65 s 524487 B/s 512.19 KB/s

Você pode ver o progresso dos dados, mas não pode apenas somar (ou mediar) cada coluna. Há apenas dois eventos neste exemplo (linhas 1-5, 6), por exemplo, usei o script duas vezes. Acontece que podemos adicionar as duas últimas linhas - porque eu reiniciei e temos um instantâneo daquele momento, mas isso é arbitrário. O que leva ao que acontece quando eu saio do comando e o reinicio, como você pode ver acontecendo na última linha - o contador é, claro, reinicializado.

O objetivo é ter um total cumulativo da saída de status para todas as instâncias do script que eu inicio ao longo do tempo. Eu geralmente nunca lanço mais de uma instância de cada vez. Então, estou pensando em adicionar ao meu script ("são" para uma única instância do script):

  • Primeiro, exclua todos, exceto a última linha do meu log
  • Por último, quando o script sair, faça-o escrever seu status no log
    • Soma / média de cada coluna da primeira e da última linha
    • Excluir todas as linhas intermediárias

Temo que não consiga ligar os pontos. Qual é a maneira mais simples e melhor de projetar e implementar o que eu quero? A complexidade sobrecarrega o benefício e devo me concentrar apenas na manipulação dos dados de log com um comando simples à medida que eles são preenchidos?

    
por jus cogens prime 08.06.2014 / 10:49

1 resposta

1

Bem, com base no que você mostra, consegui dividi-lo de forma bastante confiável, mas há um problema sério com esses dados: não é normal . Você tem valores human-friendly aqui - isso não é bom. Por exemplo, as diferenças de MB e GB entre a primeira e a última linha - manipulação que é um lote de trabalho extra que você não deveria ter que fazer - porque não apenas contar bytes? E o que há com a coisa ([h]:[mm]) - por que é na primeira linha e não na última linha e por que não na hora do Unix?

Honestamente, este não é o tipo de dados que você deveria estar registrando - não é muito útil. Claro, é mais fácil para você ler, mas você vai ler 10.000 linhas dela? Eu acho que você preferiria não e é por isso que você fez essa pergunta. Você precisa alterar essa saída - não obter letras, apenas contagens de bytes e segundos desde a época. Faça isso, e isso será um muito mais fácil para você.

Agora, dito isso, aqui está o que eu fiz :

set -- $(
sed '$bl;1H;d;:l;x;G
     s/([1-9][^)]*) //;h
     s/\n/First:&       /
     s/[^:]\(\n\)/&Last:      /
     w /dev/fd/2
     g' <<\DATA
1931255808 B 1.8 GB 3683.6 s (1:01 h) 524289 B/s 512.00 KB/s
2560401408 B 2.4 GB 4883.6 s (1:21 h) 524289 B/s 512.00 KB/s
3189547008 B 3.0 GB 6083.6 s (1:41 h) 524289 B/s 512.00 KB/s
3818692608 B 3.6 GB 7283.6 s (2:01 h) 524289 B/s 512.00 KB/s
4447838208 B 4.1 GB 8483.6 s (2:21 h) 524289 B/s 512.00 KB/s
10829824 B 10.3 MB 20.65 s 524487 B/s 512.19 KB/s
DATA
)

Essa primeira linha sed é o suficiente para obter apenas suas primeiras e últimas linhas e colocá-las no mesmo espaço padrão para a edição sed , cada uma delas precedida por um caractere \n ewline. Esta declaração faz tudo isso:

$bl;1H;d;:l;x;G

A próxima linha elimina os dados do funky time out - que é parte do problema - e armazena uma cópia extra dos resultados em h old space:

s/([1-9][^)]*) //;h

As próximas três linhas inserem as palavras Primeiro: e Último: e \n ewline e <tab> caracteres antes de suas respectivas linhas e gravam os resultados em stderr :

 s/\n/First:&       /
 s/[^:]\(\n\)/&Last:      /
 w /dev/fd/2

A última sed line apenas g ets essa segunda cópia fora de h old space e sobrescreve o espaço de padrão atual com ela, que sed depois segue com sua ação padrão de imprimir o espaço padrão final seguido por um \n ewline. Os resultados, neste momento, não são, admito, tão impressionantes. Executar o bit de script acima só produzirá o seguinte:

First:
        1931255808 B 1.8 GB 3683.6 s 524289 B/s 512.00 KB/s
Last:
        10829824 B 10.3 MB 20.65 s 524487 B/s 512.19 KB/s

Mas eu intencionalmente set os resultados no array shell e mantiveram ambas as linhas acessíveis no espaço de padrão sed por um motivo. Por exemplo, após a última linha g em sed - se você quisesse - você poderia trabalhar com um espaço padrão semelhante a este:

\n1931255808 B 1.8 GB 3683.6 s 524289 B/s 512.00 KB/s\n10829824 B 10.3 MB 20.65 s 524487 B/s 512.19 KB/s$ 

Ou, se você deixou como está, e apenas adicionou o seguinte ao que já está lá ...

printf '%s LINE, FIELDs 1 and 2: %s and %s' \
    FIRST "$1" "$2" LAST "${11}" "${12}"

Sua saída deve se parecer com:

FIRST LINE, FIELDs 1 and 2: 1931255808 and B
LAST LINE, FIELDs 1 and 2: 10829824 and B

Isso é uma adição à saída stderr que ela já fornece.

    
por 09.06.2014 / 04:54