Registrando a saída de um daemon com o Upstart

34

Eu tenho um daemon personalizado que é gerenciado pelo iniciante no meu servidor Ubuntu. Funciona perfeitamente, exceto que eu preciso capturar (log) a saída do daemon. A página oficial das estrofes diz que eu posso usar console loggedisso, mas em qual arquivo ele faz logon?

Também li que nãoconsole logged é mais uma estrofe válida . Atualmente, estou usando 0.3.9 (Hardy), mas vou atualizar para 0.6.x (Lucid) em alguns meses. Se console logged, de fato, não funcionará com versões posteriores, o que devo usar?

Alex Reisner
fonte
11
Você pode simplesmente atualizar seu daemon personalizado para enviar a saída para o syslog ou para um arquivo de log especificado no arquivo de configuração do daemon?
Zoredache

Respostas:

35

Esse trecho direcionará a saída do seu serviço para o criador de logs, enquanto ainda permite que você execute o processo do serviço (substituindo assim o processo do shell) para que o iniciante não fique confuso. Ele também garante que o processo do criador de logs seja reparado para iniciar, por isso não é um filho do seu serviço e evita deixar cruft parado no sistema de arquivos, mesmo que seja necessário criar um fifo temporariamente.

script
  mkfifo /tmp/myservice-log-fifo
  ( logger -t myservice </tmp/myservice-log-fifo & )
  exec >/tmp/myservice-log-fifo
  rm /tmp/myservice-log-fifo
  exec myservice 2>/dev/null
end script

Veja como funciona:

  1. mkfifo /tmp/myservice-log-fifosimplesmente cria o arquivo especial fifo (também conhecido como pipe). Digite man 7 fifopara mais informações.
  2. ( logger ... </tmp/myservice-log-fifo & ) inicia a leitura do registrador do fifo, em segundo plano. As parênteses fazem com que o processo do criador de logs seja reparado para iniciar, em vez de permanecer um filho do processo atual do shell.
  3. exec >/tmp/myservice-log-fiforedireciona o stdout do shell atual para o fifo. Agora temos um descritor de arquivo aberto para esse fifo e não precisamos mais da entrada do sistema de arquivos ...
  4. rm /tmp/myservice-log-fifo então vamos removê-lo.
  5. exec myservice 2>/dev/nullsimplesmente executa o serviço da maneira usual. O Stdout já está no fifo e isso não muda quando o novo programa é executado.

UPDATE: set -e não é necessário, pois o Upstart executa scripts com esta opção por padrão (consulte http://upstart.ubuntu.com/cookbook/#develop-scripts-using-bin-sh )

Keith Rarick
fonte
ótima resposta e não deixa arquivos quino espalhados por qualquer lugar.
Ash Berlin-Taylor
Qual é o set -e?
Peter Mounce
11
Isso set -efaz com que o script saia imediatamente se algum comando falhar. Sem essa linha, o script continuaria executando comandos subseqüentes inutilmente (e possivelmente perigosamente).
21430 Keith Rarick #
11
Para registrar stderr e stdout, adicione a linha exec 2>&1acima da rmlinha e remova-a 2>/dev/nullda última linha.
Itsadok
31

Para versões recentes do Ubuntu (12.04+), basta usar

console log

E a saída do daemon (STDOUT & STDERR) será anexada a /var/log/upstart/<service>.log

http://upstart.ubuntu.com/cookbook/#console-log

Willem
fonte
2
Isso seria limpo e agradável, mas infelizmente não funciona no CentOS 6.x, que ainda fornece uma versão antiga do upstart que não suporta isso.
Cristian Măgherușan-Stanciu
11

Se você usar a console output sub - rotina e canalizar a saída do seu script para logger(a interface de comando do shell para o módulo de log do sistema syslog (3)), isso funcionará.

Por exemplo

console output
exec /my/script | logger

registrará em /var/log/messages

Por exemplo

console output
exec /my/script | logger -t my-script

registrará /var/log/messagese marcará cada mensagem commy-script

logger --help para opções de uso do criador de logs.

(Estou na Amazon Linux AMI, que é baseada no Centos 5.x; YMMV)

Peter Mounce
fonte
4
Acontece que essa não é uma boa solução. as travas iniciais no PID logger, não no processo que você realmente deseja que ele gerencie.
Peter Mounce
10

Não consegui o mkfifotruque para funcionar satisfatoriamente; ele não pareceu capturar o stderr e as tentativas de redirecionamento fizeram com que o Upstart fosse liberado sem erros.

Ele também tem um efeito colateral lamentável de fazer com que o loggerprocesso permaneça como filho init, de modo que as informações sobre quem é o proprietário do criador de logs são perdidas e qualquer pessoa que ainda não esteja ciente disso mkfifopode assumir que é um processo pendente que pode ser morto.

Em vez disso, acabei com a seguinte solução, que resolve todos esses problemas. Faz com logger que se torne um processo filho, preservando o serviço como o processo raiz. Infelizmente, isso exige execução bash, mas parece sujo.

script
  # ... setup commands here, e.g. environment, cd, ...
  exec bash <<EOT
    exec 1> >(logger -t myservice) 2>&1
    exec myservice
EOT
end script

Isso usa um truque que redireciona stdout e stderr para um comando. Como executamos o serviço dentro do bashcomando, isso tem o efeito colateral de substituir o shell e fazer do bash magicamente um processo filho do serviço, conforme mostrado por ps aufxw:

myservice 
 \_ bash -c exec 1> >(logger -t myservice) 2>&1 && exec myservice
    \_ logger -t myservice

Por alguma razão, o comando acima deve ser envolvido em a bash -c. Presumo que isso ocorra porque o Upstart apenas finge executar seu script via Bash, mas na verdade não é. Se alguém puder sugerir uma maneira de evitar o shell bash extra, isso seria incrível.

Alexander Staubo
fonte
11
Sim! Estou tão feliz por ter encontrado isso. Parece melhor do que a variante mkfifo e, no meu caso, eu precisava fazer exec bash -l << EOFisso sem perdas.
thom_nic
6

Isso é feio, mas até agora o melhor que encontrei

exec / caminho / para / servidor >> /tmp/upstart.log 2> & 1

Jorge Vargas
fonte
2
A solução não é boa quando se trata de rotação de log, porque o aplicativo está registrando diretamente no arquivo. O log no syslog evita problemas relacionados.
Mark Stosberg
3

Você também pode redirecionar a saída para o syslog, por exemplo

exec $SERVER 2>&1 | logger -t myservice -p local0.info

No entanto, o pipeline pode fazer com que o inicio confunda o PID do processo de log com o PID do daemon.

Nikratio
fonte
O daemon que confunde o PID é na verdade um daemon inútil, pois deve assistir ao processo, reaparecer em seguida. Alguma idéia de como garantir que o PID certo esteja sendo observado?
Johann Philipp Strathausen
Eu acho (mas não tentei) que você vai querer o expect forkou expect daemonestrofe. Ou você poderia catcolocar o arquivo pid na mensagem de log, caso contrário, eu acho.
Peter Mounce
1

Outra alternativa é usar tee como:

exec $SERVER 2>&1 | tee /dev/stderr | logger -t myservice

para obter o arquivo inicial e a saída do syslog

perl
fonte