调试:控制台输出和Upstart脚本


16

如何将新贵脚本的输出发送到终端,以便在python代码中查找回溯?我花了永远做过去没有回溯的事情,而过去只花一秒钟的时间。我必须放置几个文件写入调用来跟踪错误。追溯之前花了第二秒才找到的是几分钟。真惨 这已经持续了几个星期,我对此感到厌烦。有人请对此发表意见。我觉得我再次使用没有调试器的程序集。

Answers:


27

如果您使用Upstart 1.4或更高版本,则将其console log放入Upstart作业,并且stdout / stderr的所有输出都将以结束/var/log/upstart/<job>.log。然后,您可以tail -f /var/log/upstart/<job>.log &使输出出现在终端中。


参加聚会有点晚了,但是这个答案救了我:)看起来对我也有用,在upstart conf文件中没有任何特殊设置。就我而言,这应该是公认的答案。
rslite

不知道有新贵托管服务日志/var/log/upstart。真的很有用,谢谢。
弗朗西斯科

2

Upstart Cookbook中有一整节关于调试技术的内容。您最容易做的就是添加--debug到内核​​参数中,这将增加新贵的冗长性,并将所有内容转储到syslog中。是的,调试很复杂,这反映了创建并行化初始化系统所需的净复杂性。我敢肯定还有改进的余地。


2
烹饪书没有正确地向新手解释调试环境。我以前见过类似的解释。要么缺乏假设,要么做出假设。对于想要加入社区并刚刚起步的人们来说,这非常令人沮丧。我从来没有遇到过这样的编程环境,除了汇编中重新编写轮子的过程之外,没有提供发生错误的代码行,因此可以原谅。
bambuntu 2012年

好吧,那你有什么建议?这是一个打开的文档。如果您的调试技术超出了此处介绍的范围,请添加它。OP的问题更多是由于不了解如何在其选择的其他运行时以及如何部署的上下文中管理基本的unix范例而引起的。仅仅因为您使用的是python或[在此处插入奇特的运行时语言]并不意味着您忽略基本的运行时UNIX。
ppetraki 2012年

2

当我编写python守护程序时,我捕获了所有异常,然后将其抛出到日志文件中。我不仅用于调试,还用于生产。我有一个小脚本,每天早上运行,它在日志中查找令人沮丧的内容。

当然,它也有助于保持守护进程的运行。

一些示例代码(我删除了不感兴趣的部分):

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)

其中actua()是真正的守护程序(它也写入日志)。请注意,我在设置文件中还有一个DEBUG变量,当它为True时,我不会派生该守护程序,因此它将在控制台上执行。

守护进程

守护程序是与Windows服务等效的unix。它们是在后台独立于其他进程运行的进程。这意味着他们的父亲通常是init,并且他们与任何tty无关。由于它们是独立的,因此没有预定义的位置可以放置其输出。

在上面的示例中,我使用了自己的函数,该函数结合了Steinar Knutsens和Jeff Kunces版本中的一些想法,因此有很多python库和代码片段可用于创建守护程序。它尽可能简单,请注意我分了两次

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()

好吧 由于您已经登录到syslog,因此只需过滤出守护程序消息并将其转储到控制台。我不明白为什么这是针对新贵的?SysV init将具有相同的问题。
ppetraki 2012年

没错,这不是特定于新贵,说实话我的大多数服务器都运行8.04,没有新贵。但这对暴发户也是有效的。OP正在询问如何使用upstart调试python脚本,而不是问一种仅适用于upstart的方法。我不是登录到syslog,而是登录到特定文件,这里的“窍门”是捕获所有异常并将堆栈跟踪信息转储到该文件。
哈维尔·里维拉

好吧,那仅仅是基于上下文管理标准输出吗?我知道很多unix守护程序具有相同的日志记录详细程度,无论它是附加到tty还是用作守护程序。如果是Ruby,我将重写或修饰异常用于输出的基类方法。我确信可以在Python中完成类似的操作。适当地在堆栈交换上问这个问题可能会更好。这更多的是基本的unix守护程序编码/设计问题,正如您所说,它与初始化脚本没有任何特定关系。
ppetraki 2012年

我仍然对术语非常熟悉。我假设守护程序是指在后台运行的特定脚本。在您的代码中,我只是将脚本替换为actua()来获取该脚本调用的回调?无论如何,将其引导到控制台而不是文件?
bambuntu 2012年

1
独立而言,守护程序通常与启动它们的tty分离,并已将其原始文件句柄关闭到stdin,stdout和stdin,并且是init的子代。因此,如果要将异常打印到特定的地方,请找出异常的输出方式,然后从那里进行定向。linfo.org/daemon.html。再说一次,这与新贵,甚至与初始化无关。让您的程序在真正的守护程序模式下正确运行,然后将其移至新贵的位置。
ppetraki 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.