Depuração: Scripts de saída e upstart do console

16

Como você envia a saída de um script upstart para um terminal para encontrar tracebacks em código python? Está me levando para sempre fazer coisas sem rastros que costumavam levar apenas um segundo. Eu estou tendo que colocar várias chamadas de gravação de arquivo para rastrear erros. O que demorou segundos para encontrar antes com um traceback está se transformando em alguns minutos minutos. Isso é miserável. Isso já dura algumas semanas e estou farto disso. alguns falariam por favor. Eu sinto que estou usando assembly sem um depurador novamente.

    
por bambuntu 22.03.2012 / 09:02

3 respostas

27

Se você usar o Upstart 1.4 ou mais recente, coloque console log em seu trabalho do Upstart e toda a saída para stdout / stderr terminará em /var/log/upstart/<job>.log . Então você pode fazer tail -f /var/log/upstart/<job>.log & para que a saída apareça no terminal.

    
por Tuminoid 26.03.2012 / 08:52
2

Há toda uma seção sobre técnicas de depuração no livro de receitas do Upstart . A coisa mais fácil que você pode fazer é adicionar --debug aos argumentos do kernel, o que aumentará o detalhamento do upstart e despejará tudo no syslog. Sim, a depuração é complexa, é um reflexo da complexidade da rede necessária para criar um sistema init paralelizado. Tenho certeza de que há espaço para melhorias.

    
por ppetraki 22.03.2012 / 09:26
2

Quando eu escrevo um daemon python, eu pego todas as exceções e as lanço no arquivo de log. Eu não uso apenas para depuração, mas também na produção. Eu tenho um pequeno script que eu corro todas as manhãs que procura algo perturbador nos logs.

Também ajuda a manter o daemon em execução, é claro.

Algum exemplo de código (eu removo as partes não interessantes):

import logging

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(levelname)s %(message)s',
                    filename=LOG_FILE,
                    filemode='w')
    logging.info("Sincrod inicializado")
    if not DEBUG:
        daemonize()
    while True:
        try:
            actua()
        except:
            logging.error(sys.exc_info())
        if (datetime.datetime.now().hour > NOITE_EMPEZA\
         and datetime.datetime.now().hour < NOITE_REMATA):
            time.sleep(INTERVALO_NOITE)
        else:
            time.sleep(INTERVALO_DIA)

Onde actua () é o daemon real (escreve também para logar). Note que eu também tenho uma variável DEBUG em um arquivo de configurações, quando é True, eu não bifurco o daemon para que ele seja executado no console.

Daemons

Daemons são o equivalente unix aos serviços do Windows. São processos executados em segundo plano, independentes de outros processos. Isso significa que o pai deles é geralmente init e que eles estão separados de qualquer tty. Como são independentes, não há lugar predefinido para colocar a saída.

Existem muitas bibliotecas e snippets python para fazer um daemon, no exemplo acima eu uso minha própria função, que combina algumas idéias das versões de Steinar Knutsens e Jeff Kunces. É o mais simples possível, note que eu garfo duas vezes .

def daemonize():
    """Forks this process creating a daemon and killing the original one"""
    if (not os.fork()):
        # get our own session and fixup std[in,out,err]
        os.setsid()
        sys.stdin.close()
        sys.stdout = NullDevice()
        sys.stderr = NullDevice()
        if (not os.fork()):
            # hang around till adopted by init
            ppid = os.getppid()
            while (ppid != 1):
                time.sleep(0.5)
                ppid = os.getppid()
        else:
            # time for child to die
            os._exit(0)
    else:
        # wait for child to die and then bail
        os.wait()
        sys.exit()
    
por Javier Rivera 22.03.2012 / 09:38