线上降级后,发现日志不再宰割,记录以下排查过程以及所波及的常识。

1.配置文件排查

询问老工程师,反馈是通过Python的logging模块进行宰割的,其中logging模块介绍如下:
logging模块采纳模块化设计思维,次要包含四种模块:

  • Logger:记录器,提供应用程序调用的各种接口;
  • Handler:处理器,解决记录器产生的日志;
  • Filter:过滤器,提供更好的粒度管制;
  • Formatters:格局器,格式化日志内容的组成和音讯字段;

其中logging模块详解请见:logging模块详解(转自刘江的博客)
日志解决流程如下图所示:

Django中的logging配置解释如下,其中Django读取settings.py中的LOGGING配置:

LOGGING = {    'version': 1, #版本号    'disable_existing_loggers': False,    'formatters': { # 格局器        'verbose': { # 简单格局名称            'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',            'style': '{',        },        'simple': { # 简洁格局名称            'format': '{levelname} {message}',            'style': '{',        },    },    'filters': { # 过滤器        'special': { # 过滤器名称            '()': 'project.logging.SpecialFilter',            'foo': 'bar',        },        'require_debug_true': {            '()': 'django.utils.log.RequireDebugTrue',        },    },    'handlers': { # 处理器       'logit': { # 名称            'level': 'DEBUG',            'class': 'logging.handlers.TimedRotatingFileHandler',# 按某一时间来宰割            'filename': '/tmp/logit.log', # 门路            'when': 'midnight', # Roll over at midnight            'backupCount': 10, # 备份数量            'formatter': 'verbose', # 格局器        },        'console': { # 处理器名称            'level': 'INFO', # 级别            'filters': ['require_debug_true'], # 过滤器            'class': 'logging.StreamHandler', # 流处理器            'formatter': 'simple' # 格局器        },        'file': {            'level': 'DEBUG',            'class': 'logging.FileHandler', # 文件处理器            'filename': '/path/to/django/debug.log', # 文件门路        },        'mail_admins': { # 名称            'level': 'ERROR',            'class': 'django.utils.log.AdminEmailHandler', # 邮件处理器            'filters': ['special']        }    },    'loggers': {        'django': {            'handlers': ['console'],            'propagate': True,        },        'django.request': {            'handlers': ['mail_admins'],            'level': 'ERROR',            'propagate': False,        },        'myproject.custom': {            'handlers': ['console', 'mail_admins'],            'level': 'INFO',            'filters': ['special']        }    }}

然而排查线上配置文件,并未配置TimedRotatingFileHandler处理器。并且查看文件批改记录及git记录,该文件并未批改。所以判断,日志宰割应用了其余办法。

logrotate

通过排查代码,确定日志宰割的形式是通过crond+logrotate进行宰割的。
其中logrotate介绍如下:
logrotate用于管理系统生成的大量日志,能够主动的宰割、压缩、移除或者mailing日志文件。
个别,logrotate作为daily cron job运行,除非rotate的规范是基于log文件大小,且logrotate命令今天被执行屡次,即自定义了定时工作。再或者手动执行logrotate时增加了-f/--force选项;
logrotate.conf参数阐明

# see "man logrotate" for details  # rotate log files weekly: 每周rotate log文件一次  weekly  # keep 4 weeks worth of backlogs: # 保留最近4周的log日志,因为下面是每周rotate一次  rotate 4  # create new (empty) log files after rotating old ones:# rotate老日志文件之后,创立一个新的空日志文件  create  # use date as a suffix of the rotated file:#rotate的文件以日期格局为后缀,比方:access_log-20200422,#如果不加这个选项,rotate的格局为:access_log.1,access_log.2等等。  dateext  # uncomment this if you want your log files compressed:# 如果想压缩rotate后的文件,把上面compress后面的#号去掉就能够了。  #compress  # RPM packages drop log rotation information into this directory:# RPM包的日志rotation配置信息,倡议放到/etc/logrotate.d这个文件夹下,# 实现自定义管制log文件rotate  include /etc/logrotate.d # no packages own wtmp and btmp -- we'll rotate them here:wtmp和btmp# 这两个不属于任何package,咱们就把rotate的规定写到这里/var/log/wtmp {     monthly #每个月执行一次rotate     create 0664 root utmp  #创立空文件,权限是664, 所属用户名 所属用户组     minsize 1M       #日志文件大小超过1M才执行rotate,否则跳过     rotate 1         #rotate时,只保留一份rotate文件    }  /var/log/btmp {     missingok     monthly     create 0600 root utmp     rotate 1    }     # system-specific logs may be also be configured here. # 其它系统日志也能够在这里配置rotate规定

RPM包的日志配置信息,倡议放到/etc/logrotate.d下,具体的日志配置信息如下:

/var/log/xxx.log { # 日志门路    size=500M # 当日志文件达到指定的大小时才转储/宰割,默认的大小单位是bytes    dateext # 应用当期日期作为命名格局    rotate 365 # 指定rotate日志文件保留的数量    compress # 通过gzip压缩而后备份日志    delaycompress # 提早压缩旧的日志文件,先rotate,不压缩;等下次rotate时,再压缩;须要跟compress同时应用    missingok # 如果日志不存在,不产生错误信息    notifempty # 如果日志为空,不做rotate,与ifempy互斥    # sharedscripts # 配合prerotate and postrotate 应用    create 644 root root # rotate之后,创立新文件的日志文件并指定新文件的属性    postrotate # rotate之后想要执行的脚本,须要放在postrotate 与 endscript两头,这两个选项要独自成行        /usr/bin/killall -HUP rsyslogd    endscript}

为什么备份日志一天一次呢?是因为在/etc/cron.daily下有个logrotate可执行脚本,脚本内容如下:

#!/bin/sh  /usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf  EXITVALUE=$?  if [ $EXITVALUE != 0 ]; then     /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"  fi  exit 0
crond

当然也能够自定义crontab打算。
这里再介绍一下crontab的简略用法:
Linux的调度工作分为两类:
系统调度工作,由crond服务来管制,默认随系统启动;
用户调度工作,应用crontab设置工作打算;

crondtab配置文件如下所示:

SHELL=/bin/bashPATH=/sbin:/bin:/usr/sbin:/usr/bin #系统命令门路MAILTO=root # crond的工作执行信息将通过电子邮件发送给root用户HOME = / # 执行命令或者脚本时应用的主目录# For details see man 4 crontabs# Example of job definition:# .---------------- minute (0 - 59)# |  .------------- hour (0 - 23)# |  |  .---------- day of month (1 - 31)# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat# |  |  |  |  |# *  *  *  *  * user-name  command to be executed  0  0  *  *  * root       /bin/sh /etc/cron.daily/logrotate
crontab命令详解
crontab [-u user] filecrontab [ -u user ] [ -i ] { -e | -l | -r }
  • -u user:用于设定某个用户的crontab服务;
  • file: file为命令文件名,示意将file作为crontab的工作列表文件并载入crontab;
  • -e:编辑某个用户的crontab文件内容,如不指定用户则示意以后用户;
  • -l:显示某个用户的crontab文件内容,如不指定用户则示意以后用户;
  • -r:从/var/spool/cron目录中删除某个用户的crontab文件。
  • -i:在删除用户的crontab文件时给确认提醒。
crontab留神点
  1. crontab有2种编辑形式:间接编辑/etc/crontab文件与crontab –e,其中/etc/crontab里的打算工作是零碎中的打算工作,而用户的打算工作须要通过crontab –e来编辑;
  2. 每次编辑完某个用户的cron设置后,cron主动在/var/spool/cron下生成一个与此用户同名的文件,此用户的cron信息都记录在这个文件中,这个文件是不能够间接编辑的,只能够用crontab -e 来编辑。
  3. crontab中的command尽量应用绝对路径,否则会常常因为门路谬误导致工作无奈执行。
  4. 新创建的cron job不会马上执行,至多要等2分钟能力执行,可从起cron来立刻执行。
  5. %在crontab文件中示意“换行”,因而如果脚本或命令含有%,须要应用%来进行本义。

总结:

1.线上配置个别不会更改;
2.线上服务器肯定不能在线做批改、删除等操作;
3.最初排查,是docker内的crond服务挂掉,重启crond服务后,日志宰割失常;

参考文档:
刘江的博客
Linux自带神器logrotate详解
crontab用法与实例