python定时任务执行shell脚本切割Nginx日志

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

Python定时任务执行shell脚本切割Nginx日志

缘起

我们有一个Nginx服务用来接收埋点上报数据输出的日志文件比较大Nginx没有自带日志分割组件这样输出的日志文件就比较大抽取日志就比较麻烦。
网上切割日志的方式一般就两种logratate和crontab+shell脚本
我这里探索的是第二中方式中间踩了不少坑记录一下。

环境

  • aliyunk8s
  • openresty 1.7.x
  • python2.7
  • 容器基础镜像为debian10

过程

1. crontab + shell

首先写分割日志的脚本如下文件名为 cut_and_del_log_file.sh

#!/bin/bash
# 初始化
LOGS_PATH=/opt/app/logs
CURRENT_TIME=$(date +%Y%m%d%H%M%S)
logFileList=(access error)

for fileIterm in ${logFileList[@]}
    do
      currentLogFileBaseName=${fileIterm}
      currentPathFileName=${LOGS_PATH}/${currentLogFileBaseName}.log
      echo "["${CURRENT_TIME}"]" "当前处理文件 "${currentPathFileName}
      if [ -s $(echo $currentPathFileName) ]; then
        afterReNameFileName=${LOGS_PATH}/${currentLogFileBaseName}_${CURRENT_TIME}.log
        echo "["${CURRENT_TIME}"]" "移动后文件名 "${afterReNameFileName}
        mv ${currentPathFileName} ${afterReNameFileName}
      fi
    done

#向nginx主进程发送USR1信号重新打开日志文件否则会继续往mv后的文件写数据的。原因在于linux系统中内核是根据文件描述符来找文件的。如果不这样操作导致日志切割失败。
kill -USR1 `ps axu | grep "nginx: master process" | grep -v grep | awk '{print $2}'`

#删除2天前的日志
cd ${LOGS_PATH}
find . -mtime +2 -name "*.log" | xargs rm -f

exit 0

使用crontab 执行这段脚本就大功告成了但是遇到的第一个问题是我在容器里执行脚本的时候报错

Syntax error: "(" unexpected

查了下是因为debian系统默认使用dash替换bash可以通过

dpkg-reconfigure

然后输入no就可以了但无论是dockerfile还是启动脚本都做不到然后采用第二种方法执行以下脚本

rm /bin/sh
ln -s /bin/bash /bin/sh

直接进入docker容器内部执行没问题但是发布的时候也不能进容器去做这个操作啊于是决定放在dockerfile里面但是执行完rm /bin/sh就会提示无法执行ln命令原因是sh找不到了妹的。于是我放在了容器启动脚本中但是也没用因为提示没有rm权限我们k8s里面启动的默认账户不是root于是想到了一个办法既然先删除后链接不行那就执行更新好了dockerfile添加命令

RUN ln -snf /bin/bash /bin/sh

于是完美解决这个问题。
然后又遇到了crontab启动权限问题
我的dockerfile中crontab配置脚本是

# op_user是我将来启动容器的用户 如果你使用root的话 op_user替换成root即可
RUN echo "0 */4 * * * sh /opt/app/cut_and_del_log_file.sh > /opt/app/logs/cut.log 2>&1" > /var/spool/cron/crontabs/op_user

容器启动脚本是

ENTRYPOINT ["sh","/opt/app/start.sh"]

/opt/app/start.sh这个文件内容是

nohup service start cron &
nginx -g "daemon off;"

然后提示我没权限启动cron服了这定时任务crontab没机会了。

2. python + shell

于是使用了python首先dockerfile安装python环境

# 安装python环境和pip
RUN apt-get update -y && apt-get install python2.7 python-pip --no-install-recommends -y
# 安装python组件schedule
RUN pip install schedule -i http://mirrors.cloud.aliyuncs.com/pypi/simple --trusted-host mirrors.cloud.aliyuncs.com

python脚本如下(文件名为 loopCut.py)

# -*- coding: UTF-8 -*-
import schedule
from datetime import datetime
import os

def job():
    now = datetime.now()
    dateTimeStr = now.strftime("%Y-%m-%d %H:%M:%S")
    print("start cut log shell ",dateTimeStr)
    os.system("sh /opt/app/cut_and_del_log_file.sh >> /opt/app/logs/cut.log")
    print("end cut log shell")

def func():
    schedule.clear()
    schedule.every(4).hours.do(job)
    while True:
        schedule.run_pending()

func()

容器中启动脚本为

nohup python loopCut.py 2>&1 &
nginx -g "daemon off;"

dockerfile中的ENTRYPOINT命令不变发布后可以正确切割日志了
至此搞定此项任务。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6