Existe uma ferramenta para redirecionar dinamicamente a saída para um novo arquivo, mediante solicitação

8

No momento, estou redirecionando a saída de uma ferramenta de monitoramento para um arquivo, no entanto, o que eu gostaria de fazer é redirecionar essa saída para um novo arquivo na minha solicitação (usando uma combinação de teclas), sem interromper a referida ferramenta.

Algo como

monitor_program | handle_stdout

Onde handle_stdoutme permite definir um novo arquivo onde colocar o log em determinado ponto.

Eu sei que poderia escrevê-lo facilmente, mas estou me perguntando se existe alguma ferramenta que já permita isso.

Treviño
fonte
Provavelmente, você pode executar logrotatemanualmente um arquivo de configuração personalizado, dependendo do comportamento do seu monitor_program, mas isso é um tanto imprudente.
Ulrich Schwarz
Parece que sua edição é na verdade uma resposta para a pergunta. Nesse caso, publique-o como resposta (as auto-respostas são incentivadas!) E remova a resposta da sua pergunta.
cat

Respostas:

9

Vou sugerir um pipe nomeado.

  1. Crie um canal mkfifo p(chame-o como quiser, se não for 'p')

  2. Crie um script de "leitor" que leia do canal e grave onde quiser

  3. Diga ao programa de monitoramento para gravar seus logs no canal nomeado

Aqui está um script de leitor de amostra que lê de um canal nomeado 'p' e grava os dados em um arquivo 'mylog' indexado:

#!/bin/sh

INDEX=0

switchlog() {
  read INDEX < newindex
  echo now writing to "mylog.$INDEX"
}

trap switchlog USR1

while :
do
  cat p >> mylog."$INDEX"
done
Jeff Schaller
fonte
2
Você também pode interceptar um sinal (USR1 por exemplo) no script do leitor como o sinal para alternar os logs.
Jeff Schaller
Isso começa a ser algo que eu precisaria ... No entanto, o script do leitor deve ser capaz de alterar a saída com base no meu kebinding. E potencialmente me pedir um novo nome de arquivo para usar (embora este é opcional, mesmo tendo nomes de log seqüencial seria ótimo)
Treviño
Editei o exemplo de script para mostrar um exemplo de troca de log com kill -USR1. ecoar um novo número no arquivo 'newindex' para que ele atenda.
Jeff Schaller
1
apenas outra idéia - se você mantiver uma janela aberta para o script "reader" em execução, poderá interceptar 'INT' em vez de USR1 e apenas pressionar Control-C nessa janela para notificá-lo sobre um novo nome de arquivo de log.
Jeff Schaller
1
Por que reade em printfvez de apenas cat <p >> mylog."$INDEX"?
Wildcard
7

Desenvolvendo sua ideia SIGINT, aqui usando SIGQUIT (Ctrl+\ ), você ainda pode usar Ctrl+Cpara parar a coisa toda:

(trap '' QUIT; monitor_command) | (
   trap : QUIT
   ulimit -c 0 # prevent core dump so SIGQUIT behaves like SIGINT
               # for cat
   n=0; while n=$((n+1)); file=output.$n.log; do
     printf 'Outputting to "%s"\n' "$file"
     cat > "$file"
   done)

Isso pressupõe que catnão está embutido no seu shell (então ele é interrompido por você pressionar Ctrl+\).

Observe que, como em sua abordagem, há uma chance de que o SIGQUIT seja entregue no momento errado (na chamada do sistema de gravação), causando a perda de alguns dados.

Stéphane Chazelas
fonte
1

Você provavelmente poderia usar lesse salvar a partir daí, digitando so nome do arquivo no qual deseja salvar Enter. De Como escrevo todas as linhas de menos para um arquivo? .

BenjaminH
fonte
Infelizmente, não é possível usar mais arquivos de log. Depois de definir um, você não poderá redefinir um novo. Além disso, você não pode limpar o log uma vez feito. Então ... Bom ponto de partida (obrigado), mas ainda não o suficiente.
Treviño
0

Sem saber mais sobre o seu "pedido", não é realmente possível responder. Se fosse baseado no tamanho ou no intervalo do arquivo, os rotatelogs (que devem vir com o Apache httpd) funcionarão.

symcbean
fonte
Desculpe, eu não disse isso explicitamente, estou assumindo uma combinação de teclas que permitiria alterar o nome do log.
Treviño 04/04
0

Graças à resposta de Jeff Schaller , acabei com algo assim, que basicamente faz o que eu preciso, vamos chamá-lo reader.sh:

#!/bin/sh

INDEX=0
LOGNAME="$INDEX.log"

switchlog() {
  local custom_name
  read -p "Add log name: " custom_name
  INDEX=$((INDEX+1))
  LOGNAME="$(printf "%03d" $INDEX).$custom_name.log"
  echo now writing to $LOGNAME
}

trap switchlog INT
switchlog

while :
do
  read foo < p
  printf "%s\n" "$foo" >> "$LOGNAME"
done

Então, trata-se de criar um pipe nomeado com mkfifo pe usar dois terminais onde monitor_program > pe em reader.shexecução. Posso parar o leitor para definir um novo log usando Ctrl+ Ce inserir um novo nome. Ctrl+ Z, como sempre, para parar e matá-lo.

Treviño
fonte