Depuração: saída do console e scripts iniciados

16

Como você envia a saída de um script inicial para um terminal para encontrar rastreamentos no código python? Está me levando para sempre fazer coisas sem traços que costumavam levar apenas um segundo. Estou tendo que fazer várias chamadas de gravação de arquivo para rastrear erros. O que demorou a ser descoberto antes com um rastreio está se transformando em vários minutos minutos. Isso é miserável. Isso já dura algumas semanas e eu estou cansado disso. alguns diriam sobre isso, por favor. Sinto como se estivesse usando assembly sem um depurador novamente.

bambuntu
fonte

Respostas:

27

Se você usar o Upstart 1.4 ou mais recente, coloque-o console logno seu trabalho Upstart e toda a saída para stdout / stderr terminará /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.

Tuminoide
fonte
Meio atrasado para a festa, mas essa resposta me salvou :) Também parece que isso funciona para mim sem nenhuma configuração especial no arquivo conf inicial. Da minha parte, essa deve ser a resposta aceita.
rslite
Não sabia que os logs de serviço gerenciado inicial estavam /var/log/upstart. Realmente útil, obrigado.
Francisco
2

Há uma seção inteira sobre técnicas de depuração no Upstart Cookbook . A coisa mais fácil que você pode fazer é adicionar --debugaos argumentos do kernel, o que aumentará a verbosidade do iniciante e enviará tudo para o syslog. Sim, a depuração é complexa, é um reflexo da complexidade da rede necessária para criar um sistema init paralelo. Tenho certeza de que há espaço para melhorias.

ppetraki
fonte
2
o livro de receitas não explica adequadamente um ambiente de depuração para um iniciante. Já vi explicações semelhantes antes. Faltam ou fazem suposições sobre o guru. É muito frustrante para as pessoas que querem adicionar à comunidade e apenas começar. Nunca encontrei um ambiente de programação que não fornecesse a linha de código onde o erro ocorre, exceto na montagem, onde você está reinventando a roda, para que isso possa ser perdoado.
bambuntu 23/03
Bem, o que você sugeriria então? É um documento aberto. Se você possui uma técnica de depuração que ultrapassa os limites apresentados, adicione-a. Os problemas do OP são mais o resultado de não entender como gerenciar paradigmas básicos do unix dentro de seu tempo de execução adicional de escolha versus o contexto em que está sendo implantado. Só porque você está usando python ou [insira a linguagem de tempo de execução aqui] não significa que você ignorar o tempo de execução fundamental, UNIX.
23412 ppetraki
2

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

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

Algum código de exemplo (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 (ele também grava no log). Observe que eu também tenho uma variável DEBUG em um arquivo de configurações, quando é True, 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 seu pai geralmente é init e que eles são desapegados de qualquer tipo. Como eles são independentes, não há lugar predefinido para colocar sua saída.

Existem muitas bibliotecas e trechos de python para criar um daemon. No exemplo acima, eu uso minha própria função, que combina algumas idéias das versões Steinar Knutsens e Jeff Kunces. É o mais simples possível, observe que eu bifurco 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()
Javier Rivera
fonte
Bem ok. como você já está efetuando login no syslog, basta filtrar as mensagens do daemon e despejá-las no console. Não vejo por que isso é específico ao iniciante? O SysV init teria o mesmo problema.
22412 ppetraki
Você está certo, não é específico para iniciar, para dizer a verdade, a maioria dos meus servidores roda 8.04, não é inicial. Mas também é válido para iniciantes. O OP estava perguntando como depurar scripts python com o upstart, não um método que funcione apenas com o upstart. Não estou efetuando logon no syslog, mas em um arquivo específico, e o 'truque' aqui é capturar todas as exceções e despejar o rastreamento da pilha nesse arquivo.
22312 Javier Rivera
bem, isso é apenas gerenciar stdout com base no contexto, certo? Conheço muitos daemons unix que possuem verbosidade de log equivalente, independentemente de estar anexado a um tty ou funcionando como um daemon. Se fosse Ruby, eu substituiria ou decoraria o método da classe base que as exceções usam para a saída. Tenho certeza de que algo semelhante pode ser feito em Python. Você pode estar melhor atendido a essa pergunta na troca de pilhas adequada. Esse é mais um problema básico de codificação / design de daemon unix e, como você afirmou, não tem nada específico a ver com scripts init.
22412 ppetraki
Ainda estou me familiarizando com a linguagem. Presumo que por daemon, você quer dizer um script específico que é executado em segundo plano. No seu código, eu apenas coloquei meu script no lugar de actua () para obter os retornos de chamada para essa chamada de script? Existe alguma maneira de canalizá-lo para um console em vez de um arquivo?
22312 bambuntu
11
daemons no sentido autônomo geralmente são desanexados do tty em que foram iniciados, fecharam seus identificadores de arquivo originais para stdin, stdout e stdin e são filhos do init. Portanto, se você deseja imprimir exceções em algum lugar específico, descubra como elas são produzidas e direcione-as a partir daí. linfo.org/daemon.html . Novamente, isso não tem nada a ver com o iniciante ou mesmo o init. Obtenha seu programa funcionando corretamente no modo daemon verdadeiro e , em seguida, movê-lo arrivista.
ppetraki 23/03