2

我使用 Tornado 构建了一个 Web 服务,它日夜提供服务。我使用命令启动我的服务:

nohup python my_service.py &

服务日志能够写入nohup.out. 但是,随着时间的推移,文件会变大。我想知道如何更方便地管理它?比如说,使用自动方法生成具有正确名称和大小的日志文件?如:

service_log_1.txt
service_log_2.txt
service_log_3.txt
...

谢谢。

4

4 回答 4

3

就在这里。使 cron-job 生效,它会截断文件(通过类似的东西 "cat /dev/null > nohup.out")。您必须多久运行一次此作业取决于您的流程生成多少输出。

但是,如果您完全不需要作业的输出(无论如何可能是垃圾,只有您可以回答),您可以nohup.out首先阻止写入文件。现在你以这样的方式开始这个过程:

nohup command &

将其替换为

nohup command 2>/dev/null 1>/dev/null &

并且文件 nohup.out 甚至不会被创建。

进程的输出被定向到文件的原因是:

通常所有进程(即:您从命令行输入的命令,也有例外,但在这里无关紧要)都连接到终端。默认情况下(这是 Unix 处理此问题的方式),这是可以显示文本并通过串行线路连接到主机的东西。如果您输入命令并关闭终端,您从进程中输入的终端也会终止 - 因为它丢失了终端。因为在串行通信中,技术人员传统上使用电话通信中的词(它来自哪里),所以通信的终止不称为“中断”或“终止”,而是“挂断”。所以程序在“挂断”时被终止,并且为了防止这种情况发生的程序是“nohup”,即“no-termination-upon-hangup”程序。

但是很可能这样一个孤立的进程没有终端可以写入 nohup 使用文件 nohup.out 作为“屏幕替换”,将输出重定向到那里,通常会转到屏幕。如果一个命令没有任何输出,尽管 nohp.out 不会被创建。

于 2013-05-16T10:20:23.877 回答
1

简单的:

nohup python my_service.py >service_log_1.txt 2>&1 &
于 2013-05-16T12:48:33.390 回答
1

如果输出是由您正在使用的某个库生成的并且您无法控制它,您可以在程序启动时将标准输出重定向到文件。然后,您可以定期关闭并重新打开文件,以防止文件永远增长。您可以使用时间戳作为文件名,因此它总是不同的。就像是:

import sys
import datetime
current_stdout = None
def reset_stdout():
    global current_stdout
    if current_stdout:
        current_stdout.close()
    sys.stdout = open(
        "{}.log".format(
            datetime.datetime.now().strftime('%Y%m%d%H%M%S')
            ),
        "w")
    current_stdout = sys.stdout
reset_stdout()

# Then call this every day.. week ..
reset_stdout()

如果您希望根据文件的大小重置文件,您可以定期监控其大小,如下所示:

if current_stdout.tell() > 1000000:
    reset_stdout()

但是,如果您确实可以控制要发送的输出,我强烈建议您使用日志库。它对您可以对输出进行的操作具有很大的灵活性。发送到日志的消息可以由称为handlers的对象处理。库中包含的处理程序之一可以执行您想要的操作,称为RotatingFileHandler。从文档中:

class logging.handlers.RotatingFileHandler(filename, mode='a', maxBytes=0, backupCount=0, encoding=None, delay=0)

“您可以使用 maxBytes 和 backupCount 值来允许文件以预定大小翻转。当即将超过大小时,文件将关闭并以静默方式打开一个新文件以进行输出。只要当前日志文件发生翻转就会发生长度接近 maxBytes;如果 maxBytes 为零,则永远不会发生翻转。”

因此,您可以使用以下方式进行所有日志记录:

import logging
import logging.handlers
# Create a logger
log = logging.getLogger('example')
# Set the level of the logger. By doing this all the messages with a "level" of INFO or higher will be 
# sent to the log
log.setLevel(logging.INFO)
# Create the handler and set 20 files to rotate and a maximum size of 1MB
handler = logging.handlers.RotatingFileHandler('log',maxBytes = 1000000,backupCount=20)
# Now attach the handler to the logger object
log.addHandler(handler)

# Now you can send your output like:
log.info('text text text text text text text text text')
log.info(....
于 2013-05-17T15:02:37.957 回答
0

@jujaro 的回答很有帮助,我logging在我的网络服务中尝试了模块。但是,使用登录仍然有一些限制Tornado。请参阅提出的另一个问题

结果,我尝试crontab在 linux 中在午夜创建一个 cron 作业(crontab -e在 linux shell 中使用):

59 23 * * * source /home/zfz/cleanlog.sh

这个 cron 作业cleanlog.sh每天 23:59 启动我的脚本。

的内容clean.sh

fn=$(date +%F_service_log.out)
cat /home/zfz/nohup.out >> "/home/zfz/log/$fn"
echo '' > /home/zfz/nohup.out

此脚本创建一个包含当天日期的日志文件,并在它变大时echo ''清除它。nohup.out这是我现在从 nohup.out 中拆分出来的日志文件:

-rw-r--r-- 1 zfz zfz  54474342 May 22 23:59 2013-05-22_service_log.out
-rw-r--r-- 1 zfz zfz  23481121 May 23 23:59 2013-05-23_service_log.out
于 2013-05-25T08:13:52.443 回答