Depuración: salida de consola y secuencias de comandos de inicio

16

¿Cómo se envía la salida de un script inicial a un terminal para encontrar trazas en el código de Python? Me está tomando para siempre hacer cosas sin trazas que solían tomar solo un segundo. Tengo que hacer varias llamadas de escritura de archivos para localizar errores. Lo que tardó en encontrar antes con un rastreo es convertirlo en varios minutos minutos. Esto es miserable Esto ha estado sucediendo durante algunas semanas y estoy harto de eso. algunos hablarían sobre esto por favor. Siento que estoy usando el ensamblaje sin un depurador nuevamente.

bambuntu
fuente

Respuestas:

27

Si usa Upstart 1.4 o posterior, ingrese console loga su trabajo de Upstart y toda la salida a stdout / stderr terminará en /var/log/upstart/<job>.log. Entonces puede hacer tail -f /var/log/upstart/<job>.log &que la salida aparezca en la terminal.

Tuminoide
fuente
Es un poco tarde para la fiesta, pero esta respuesta me salvó :) También parece que esto funciona para mí sin ninguna configuración especial en el archivo conf de inicio. Por mi parte, esta debería ser la respuesta aceptada.
rslite
No sabía que existían registros de servicios administrados advenedizos /var/log/upstart. Realmente útil, gracias.
Francisco
2

Hay una sección completa sobre técnicas de depuración en el libro de cocina de Upstart . Lo más fácil que puede hacer es agregar --debuga los argumentos de su núcleo, lo que aumentará la verbosidad del advenedizo y volcará todo a syslog. Sí, la depuración es compleja, es un reflejo de la complejidad neta requerida para crear un sistema de inicio paralelo. Estoy seguro de que hay margen de mejora.

ppetraki
fuente
2
el libro de cocina no explica adecuadamente un entorno de depuración a un recién llegado. He visto explicaciones similares antes. Faltan o hacen suposiciones de gurú. Es muy frustrante para las personas que desean sumarse a la comunidad y recién comenzar. Nunca me he encontrado con un entorno de programación que no proporcionara la línea de código donde se produce el error, excepto en el ensamblaje, donde reinventa la rueda, para que se pueda perdonar.
bambuntu
Bueno, ¿qué sugerirías entonces? Es un documento abierto. Si tiene una técnica de depuración que va más allá de lo que se presenta allí, agréguela. Los problemas del OP son más el resultado de no entender cómo administrar los paradigmas básicos de Unix dentro de su tiempo de ejecución adicional en comparación con el contexto en el que se está implementando. El hecho de que esté usando python o [insertar un lenguaje de ejecución elegante aquí] no significa que usted ignorar el tiempo de ejecución fundamental, UNIX.
ppetraki
2

Cuando escribo un demonio de Python, capto todas las excepciones y las lanzo al archivo de registro. No solo lo uso para depurar, sino también en producción. Tengo un pequeño script que ejecuto todas las mañanas que busca algo molesto en los registros.

También ayuda a mantener el demonio en funcionamiento, por supuesto.

Algún código de muestra (elimino las partes no interesantes):

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)

Donde actua () es el verdadero demonio (también escribe para iniciar sesión). Tenga en cuenta que también tengo una variable DEBUG en un archivo de configuración, cuando es True, no bifurco el demonio para que se ejecute en la consola.

Demonios

Los demonios son el equivalente de Unix a los servicios de Windows. Son procesos que se ejecutan en segundo plano independientemente de otros procesos. Eso significa que su padre suele ser init, y que están separados de cualquier tty. Como son independientes, no hay un lugar predefinido para colocar su salida.

Hay muchas bibliotecas y fragmentos de Python para hacer un demonio, en el ejemplo anterior utilizo mi propia función, que combina algunas ideas de las versiones de Steinar Knutsens y Jeff Kunces. Es lo más simple posible, tenga en cuenta que me bifurco dos veces .

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
fuente
Bien ok. dado que ya está iniciando sesión en syslog, simplemente filtre sus mensajes de daemon y vuélvalos a la consola. No veo por qué esto es específico para el advenedizo. SysV init tendría el mismo problema.
ppetraki
Tienes razón, no es específico para el arranque, para decir la verdad, la mayoría de mis servidores funcionan con 8.04, sin arranque. Pero también es válido para advenedizos. OP preguntaba cómo depurar los scripts de Python con el arranque, no para un método que solo funciona con el arranque. No estoy iniciando sesión en syslog sino en un archivo específico, y el 'truco' aquí es detectar todas las excepciones y volcar el seguimiento de la pila en ese archivo.
Javier Rivera
bueno, eso es solo administrar stdout basado en el contexto ¿verdad? Conozco muchos demonios Unix que tienen una verbosidad de registro equivalente independientemente de si está conectado a un tty o funciona como un demonio. Si se tratara de Ruby, anularía o decoraría el método de clase base que las excepciones usan para la salida. Estoy seguro de que se puede hacer algo similar en Python. Es mejor que hagas esta pregunta sobre el intercambio de pila propiamente dicho. Esto es más un problema básico de codificación / diseño de demonio de Unix, y como usted dijo, no tiene nada específico que ver con los scripts de inicio.
ppetraki
Todavía me estoy familiarizando con la jerga. Supongo que por demonio te refieres a un script específico que se ejecuta en segundo plano. En su código, ¿acabo de colocar mi script en lugar de actua () para obtener las devoluciones de llamada para esa llamada de script? ¿Hay alguna forma de canalizarlo a una consola en lugar de un archivo?
bambuntu
1
los demonios en el sentido independiente generalmente se separan del tty en el que se iniciaron, han cerrado sus identificadores de archivos originales a stdin, stdout y stdin, y son hijos de init. Entonces, si desea imprimir excepciones a un lugar específico, averigüe cómo se superan y diríjalas desde allí. linfo.org/daemon.html . Una vez más, esto no tiene nada que ver con el advenedizo, ni siquiera con init para el caso. Haga que su programa funcione correctamente en modo verdadero demonio y luego muévalo hacia arriba.
ppetraki