Efetuar logon em um FIFO e redirecionar para um arquivo?

8

Eu tenho um aplicativo que deve registrar cada transação. Toda mensagem de log é liberada porque precisamos ter um registro do que ocorreu antes da falha. Meus colegas e eu estávamos curiosos sobre como obter os efeitos de desempenho do buffer, garantindo que a mensagem de log havia saído do processo.

O que criamos é:

  • faça um FIFO no qual o aplicativo possa gravar e
  • redirecionar o conteúdo desse FIFO para um arquivo regular via cat.

Ou seja, o que era normalmente:

app --logfile logfile.txt

é agora:

mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

Existem algumas dicas para essa abordagem? Funcionou quando o testamos, mas queremos ter certeza absoluta de que as mensagens encontrarão o caminho para o arquivo de redirecionamento, mesmo se o aplicativo original travar.

(Não temos o código-fonte para o aplicativo, portanto, as soluções de programação estão fora de questão. Além disso, o aplicativo não grava stdout, portanto, a canalização direta para um comando diferente está fora de questão. Portanto, syslognão é uma possibilidade .)


Atualização: eu adicionei uma recompensa. A resposta aceita não envolverá loggerpela simples razão de que nãologger é isso que perguntei. Como afirma a pergunta original, estou apenas procurando dicas no uso de um FIFO.

chrisaycock
fonte
Parece haver alguma confusão imensa em algumas das respostas até agora. Como havia destacado originalmente em minha pergunta, estou procurando dicas para a abordagem do uso de um FIFO como intermediário de registro . Não estou interessado em sugestões alternativas que, pelo menos, não explorem as dicas da minha pergunta original.
Chrisaycock
Se a minha resposta sobre o registro no stdout não for uma direção na qual você está interessado, talvez seja possível remover "Além disso, o aplicativo não grava no stdout, portanto, o canal direto para um comando diferente está fora de questão" da pergunta?
nickgrim

Respostas:

6

Observe que um fifo é normalmente necessário na programação em que a quantidade escrita pode exceder a quantidade lida.

Como tal, um fifo não funcionará perfeitamente como você esperava, mas resolveria o seu principal problema ao introduzir outro.

Existem três advertências possíveis.

  1. A gravação no fifo é bloqueada indefinidamente se nada estiver lendo a outra extremidade na inicialização.
  2. O fifo tem uma largura fixa de 64 K, pela qual, se o buffer for preenchido por esse ponto, outras gravações serão bloqueadas até que o leitor o alcance.
  3. O gravador de tubos será morto com SIGPIPE se o leitor morrer ou sair.

Isso significa que o seu problema (emular E / S com buffer em uma gravação sem buffer) será resolvido. Isso ocorre porque o novo 'limite' no seu FIFO se tornará, com efeito, a velocidade de qualquer utilitário que estiver gravando o que está no canal no disco (que provavelmente será E / S em buffer).

No entanto, o gravador fica dependente do seu leitor de log para funcionar. Se o leitor parar de ler de repente, o escritor bloqueará. Se o leitor sair repentinamente (digamos que você fique sem espaço em disco no seu destino), o gravador SIGPIPE e provavelmente sairá.

Outro ponto a ser mencionado é que, se o servidor entrar em pânico e o kernel parar de responder, você poderá perder até 64k de dados que estavam nesse buffer.

Outra maneira de corrigir isso será gravar logs no tmpfs (/ dev / shm no linux) e ajustar a saída para um local de disco fixo. Existem limites menos restritivos à alocação de memória fazendo isso (não 64K, normalmente 2G!), Mas podem não funcionar se o gravador não tiver uma maneira dinâmica de reabrir arquivos de log (você precisaria limpar os logs do tmpfs periodicamente). Se o servidor entrar em pânico nesse método, você poderá perder muito mais dados.

Matthew Ife
fonte
Essa é uma boa informação sobre /dev/shm. Também tínhamos considerado isso, embora tivesse me esquecido de usar tail -f.
Chrisaycock
4
mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

O que acontece quando seu cat logfifoprocesso morre, alguém o mata acidentalmente ou alguém acidentalmente o aponta para o local errado?

Minha experiência é que o appbloqueio e a trava rapidamente. Eu tentei isso com o Tomcat, Apache e alguns aplicativos caseiros pequenos, e tive o mesmo problema. Eu nunca investiguei muito longe, porque o loggersimples redirecionamento de E / S fez o que eu queria. Normalmente, não preciso da integridade do registro, que é o que você está tentando buscar. E como você diz, você não quer logger.

Há alguma discussão sobre esse problema no Linux non-blocking fifo (registro sob demanda) .

Stefan Lasiewski
fonte
Interessante. Então o aplicativo pode bloquear mesmo assim? Estamos pensando em jogar a toalha e pedir o Fusion IO neste momento.
Chrisaycock
De uma chance. Para mim, esse resultado aconteceu rapidamente (em um ambiente de teste em hardware de baixa especificação). Isso foi no Ubuntu e RedHat 5. Não tenho certeza se o FreeBSD etc. tem um comportamento semelhante.
Stefan Lasiewski
2

Suas opções são bastante limitadas pelo aplicativo, mas o que você testou funcionará.

Fazemos algo semelhante com verniz e varnishncsa aos logs get em algum lugar útil para nós. Temos um fifo e apenas lemos com syslog-ng e enviamos para onde precisamos. Lidamos com cerca de 50 GB e não encontramos nenhum problema com essa abordagem até o momento

goo
fonte
Legal, fico feliz em saber que não somos os únicos a sugerir isso.
Chrisaycock
2

O ambiente é o CentOS e o aplicativo grava em um arquivo ...

Em vez de enviar para um arquivo regular, eu enviaria a saída para o syslog e garantiria que as mensagens do syslog sejam enviadas para um servidor central e também localmente.

Você deve poder usar um script de shell como este:

logger -p daemon.notice -t app < fifo

Você também pode receber entrada (para logger) de catou tail -fpara um canal:

tail -f fifo | logger ...
cat fifo | logger ...

O único problema é que ele não se diferencia com base na importância da mensagem de log (tudo é AVISO ), mas pelo menos é registrada e também enviada fora do host para um servidor central.

A configuração do syslog depende do servidor que você está usando. Existe rsysloge syslog-ng(ambos muito capazes).

EDIT : Revisado após obter mais informações do pôster.

Mei
fonte
As mensagens de log são gravadas em um arquivo que podemos selecionar, mas o aplicativo não grava stdout. O sistema operacional é o CentOS (eu havia marcado a questão como linux , mas acho que é fácil perder isso). Todas as mensagens são de igual importância, portanto, não há diferença entre um aviso e um erro neste aplicativo.
Chrisaycock
Não há diferença entre um aviso e um erro? Ah mesmo ? Não há diferença entre Slow query detectede Database halted?
Mei
(Atualizei a postagem.)
Mei
1

Você escreve:

Além disso, o aplicativo não grava em stdout...

Você tentou fazer logon no "arquivo" /dev/stdout? Isso pode permitir que você faça algo como:

app --logfile /dev/stdout | logger -t app
nickgrim
fonte
Isso é diferente de um FIFO? Quais são as dicas? Não estou procurando uma alternativa, por si só ; Estou procurando informações sobre se a abordagem listada é robusta. Isso é tudo que eu estou interessado.
chrisaycock
1
Sim, é diferente de um FIFO; é essencialmente um arquivo conectado ao STDOUT. Então você pode usar isso para fazer logon no STDOUT e, a partir daí, no syslog ou similar. Ele é planejado como uma solução para o seu problema original, mas espero que seja mais robusto do que um FIFO devido a ter menos peças móveis.
nickgrim
1

Não há nenhum ponto em escrever para um fifo e depois ter outro processo gravá-lo em um arquivo. Basta escrever diretamente no arquivo normalmente e, uma vez que o write()retorno, ele esteja nas mãos do kernel; ainda o gravará no disco se o aplicativo falhar.

psusi
fonte
Toda mensagem de log é liberada : estas estão bloqueando as gravações. Não temos controle sobre isso, pois não temos o código fonte do aplicativo.
Chrisaycock
@chrisaycock, certo ... então, onde está o problema?
Psusi
Meus colegas e eu estávamos curiosos sobre como obter os efeitos de desempenho do buffer, garantindo que a mensagem de log havia saído do processo.
Chrisaycock
@chrisaycock, ohh, então o aplicativo atualmente usa O_SYNC ou fsync()espera que cada gravação atinja o disco, e você NÃO deseja que isso aconteça (risco de perda no caso de uma falha no sistema)?
22412 psusi
1
@chrisaycock, não tem nada a ver com a interface do drive, normalmente significa apenas que o kernel o copiou no cache do sistema de arquivos (e fora do aplicativo). Como eu disse na minha resposta originalmente, uma vez que o write()aplicativo retorne, o aplicativo poderá travar como quiser - os dados chegarão ao disco enquanto o kernel não travar.
Psusi