日志

通过Python扫描代码关键字并进行预警

 来源    2020-05-23    0  

近期线上出现一个bug,研发的小伙伴把测试环境的地址写死到代码中,在上线前忘记修改,导致线上发布的代码中使用了测试环境地址。

开发过程中虽然有各种规范制度,但是难免有粗心,与其责备不如通过技术手段将问题进行避免。

为了达到上述需求,初步想通过以下步骤来实现代码关键字自动扫描告警。

  1. Python安装
  2. Git安装
  3. GitPython安装
  4. 定时任务配置(方案一:crontab   方案二:APScheduler)
  5. git代码获取
  6. 关键词扫描
  7. 邮件告警
#安装python的依赖包
yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel libffi-devel gcc
#下载Python安装包,版本号:Python-3.7.1.tgz(在/opt下创建目录Python3)
wget https://www.python.org/ftp/python/3.7.1/Python-3.7.1.tgz
#解压安装包
tar -zxvf Python-3.8.1.tgz
#指定python3安装目录
./configure --prefix=/usr/local/python3
#编译&安装
make && make install
#创建软连接,将自定目录管理到指定目录
ln -s /usr/local/python3/bin/python3 /usr/bin/python3
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
#添加环境变量
vi /etc/profile

export PATH=/usr/local/python3/bin:$PATH

  source /etc/profile

#至此Python3安装完毕,通过命令验证

Git安装
#下载git安装包,版本号:2.21.0
wget https://github.com/git/git/archive/v2.21.0.tar.gz
#解压
tar -zxvf v2.21.0.tar.gz
#安装
make prefix=/usr/local/git install
#添加环境变量
vi /etc/profile

export PATH=/usr/local/git/bin:$PATH
source /etc/profile

  #至此Python3安装完毕,通过命令验证

GitPython3安装
#可以采用在线安装
pip3 install GitPython
#但是我这里由于网络限制无法在线安装,只能采用手动安装
#下载依赖包,下载地址https://pypi.org/,可以根据关键字smmap、gitdb进行检索下载
smmap-3.0.4.tar.gz
gitdb-4.0.5.tar.gz
#安装
tar -zxvf smmap-3.0.4.tar.gz
cd smmap-3.0.4
python3 setup.py install

tar -zxvf gitdb-4.0.5.tar.gz
cd gitdb-4.0.5
python3 setup.py install

tar -zxvf GitPython-3.1.2
cd GitPython-3.1.2
python3 setup.py install

#安装完毕后,可以写一个demo.py进行验证

from git.repo import Repo
import os

demo_git_path = '/opt/workspace/demo'

#定义本地目录
Repo.clone_from('http://git.***.com/demo/demo_git.git',to_path=demo_git_path, branch='master')

  #最终代码库将克隆到本地目录(执行前将demo.py赋权)

  python3 demo.py

linux下配置定时任务
#定时任务采用linux的crontab来实现
#编辑定时任务
crontab -e

* * * * * python3 /opt/python3-workspace/demo.py >> /opt/python3-workspace/logs/demo.log
#前五个是时间指令,分钟(0-59)小时(0-28)日期(1-31)月份(1-12)星期几(0-6,其中0代表星期日)
#python3 是具体执行的指令 后面跟的是执行的脚本 在后面跟的是日志
#编辑保存后会立即执行
#查看当前正在运行的任务,本案例中已临时注释#
crontab -l

 原计划使用linux的crontab进行任务调度,但是在执行GitPython命令时遇到两个问题,即

  问题一:在crontab中无法调用GitPython命令,解决方案,在crontab中增加GitPython的路径

   主要内容是在crontab中增加如下代码,至此第问题一可以解决

SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/git/bin:/root/bin
MAILTO=root
HOME=/

  问题二:在crontab中执行GitPython命令时,无法读取linux记录的账号密码,导致自动任务始终无法检出代码,由于该问题一直未解决,因此决定采用python的定时任务调度解决该问题,具体见下文

APScheduler安装
#这里由于网络限制无法在线安装,只能采用手动安装
#下载依赖包,下载地址https://pypi.org/,可以根据关键字pytz、six、tzlocal进行检索下载
pytz-2020.1.tar.gz
six-1.14.0.tar.gz
tzlocal-2.1.tar.gz
APScheduler-3.6.3.tar.gz

#安装tzlocal
tar -zxvf tzlocal-2.1.tar.gz
cd tzlocal-2.1
python3 setup.py install

#安装six
tar -zxvf six-1.14.0.tar.gz
cd six-1.14.0
python3 setup.py install

#安装pytz
tar -zxvf pytz-2020.1.tar.gz
cd pytz-2020.1
python3 setup.py install

#安装APScheduler
tar -zxvf APScheduler-3.6.3.tar.gz
cd APScheduler-3.6.3
python3 setup.py install

至次APScheduler安装完毕,写个demo验证下:

 

git代码获取

通过Repo.clone_from获取远程代码仓库,指定master分支,将远程代码库clone到本地/opt/workspace/demo目录下,
如果当前目录不为空,则通过shutil.rmtree()进行级联删除

关键词扫描
利用os组件,实现对指定目录进行递归扫描,将符合要求的文件扩展名.css .js .ftl .properties等文件进行逐行扫描
关键词扫描其实就是利用正则表达式,对要扫描的关键词进行匹配,如果匹配成功则将目标文件名称放入到异常文件列表
详细代码如下:
import os
import re

project_git_path = '/opt/workspace/demo'

cssnum = 0
jsnum = 0
ftlnum = 0

fileList = []

pattern = re.compile(r'.test.com')

def analysiFile(pathFilename):
    #print('文件名:', filename)
    fo = open(pathFilename, 'r', encoding='UTF-8')
    for line in fo.readlines():
        match = pattern.search(line)
        if match:
            if(fileList.count(filename) == 0):
                fileList.append(filename);

#循环打印目录下的所有文件
for parentdir, dirname, filenames in os.walk(project_git_path):
    for filename in filenames:
        if os.path.splitext(filename)[1] == '.css':
            #分析具体文件
            analysiFile(parentdir + '\\' + filename)
        if os.path.splitext(filename)[1] == '.js':
            #分析具体文件
            analysiFile(parentdir + '\\' + filename)
        if os.path.splitext(filename)[1] == '.ftl':
            #分析具体文件
            analysiFile(parentdir + '\\' + filename)
        if os.path.splitext(filename)[1] == '.properties':
            #分析具体文件
            analysiFile(parentdir + '\\' + filename)

for item in fileList:
    print('命中文件:', item)

print('共计:', len(fileList))

邮件告警
邮件告警即通过smtp服务将上述匹配出来的异常文件列表,发送给对应系统负责人

详细代码如下:
import smtplib
from email.mime.text import MIMEText
from email.header import Header

# 第三方 SMTP 服务
mail_host = "smtp.****.com"  # 设置服务器
mail_user = "*****@****.com"  # 用户名
mail_pass = "*****"  # 口令

sender = '*****@****.com'
receivers = ['***@***.com']  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱

message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
message['From'] = Header("Python自动化检查", 'utf-8')
message['To'] = Header("系统负责人", 'utf-8')

subject = '某系统近2个月版本内网域名检查结果'
message['Subject'] = Header(subject, 'utf-8')

try:
    smtpObj = smtplib.SMTP()
    smtpObj.connect(mail_host, 25)  # 25 为 SMTP 端口号
    smtpObj.login(mail_user, mail_pass)
    smtpObj.sendmail(sender, receivers, message.as_string())
    print
    "邮件发送成功"
except smtplib.SMTPException:
    print
    "Error: 无法发送邮件"

  至此,该项目所需要的所有模块均已开发完毕,最后只需要根据自己的实际需求将上述各个模块组合在一起运行即可

由于本人是python初学者,代码基本是按照顺序执行的方式进行设计的,以能实现最终目的为主,为对代码结构、性能等合理性做出特别考虑

最后利用nohup命令,实现最终脚本的后台运行

  #文章中的安装包,如果有需要可以站内信联系

python – 自扫描代码,以防止打印状态
问答我有一个我正在研究的python项目,而不是print语句,我调用函数say(),这样我就可以在开发过程中打印信息并在生产过程中记录日志信息.但是,我经常忘记这一点并错误地将print语句放入代码中. ...
1
python – 以下代码中的’as’关键字是什么?
问答我正在学习Python中的"异常". 请考虑以下代码: def fancy_divide(): try: print(5/0) except Exception: print(Ex ...
1
python 低版本一段扫描代码
日志个人在做Linux渗透测试往内网跨的时候,通常我碰到的Linux环境都会是如下集中情况 1: DMZ,严格的DMZ,根本跨不到内网里去.这种最恶心了. 2:WEB SERVER,严格区分,工作机和工作 ...
python – pyodbc代码中没有SQL Server临时表
问答我在python中运行了一系列复杂的sql查询,它涉及临时表.我的自动提交方法似乎无法从临时表中检索数据.我在下面使用的代码片段,这是我得到的输出: testQuery=""&qu ...
1
python – 在代码或函数的一部分上禁用pylint执行
问答我正在使用pylint 0.27和python 2.7.3. Pylint有一个已知的错误,它在分析具有.next()调用的代码时会遇到错误.如http://www.logilab.org/12279 ...
1
Python单元测试代码,调用OS / Module级python函数
问答我有一个python模块/脚本,它可以完成其中的一些操作 >在脚本内的各种嵌套级别,我接受命令行输入,验证它们,应用合理的默认值 >我还检查是否存在一些目录 以上只是两个例子.我试图找出测 ...
1
如何使用GCP Dataflow中的python管道代码读取BigQuery表
问答有人可以分享语法来读取/写入在python中为GCP Dataflow编写的管道中的bigquery表::在Dataflow上运行 首先,使用以下选项构造一个Pipeline,以便在GCP DataF ...
1
python – Django代码更改不反映在生产服务器上
问答我更改了.py文件和本地开发中反映的更改.删除.pyc后的Django服务器. 生产服务器甚至没有.pyc用于此特定文件.尝试触摸apache wsgi并重新启动apache on prod.服务器, ...
1
在我的Nexus 5上更新Android 6后,蓝牙发现/扫描代码无法正常工作
问答更新后(Android 6)我的nexus 5,我正在运行的应用程序无法扫描(找到)任何蓝牙设备. getBondedDevices()让配对设备列表工作正常. 我还测试了蓝牙功能的许多示例代码和应用 ...
python-2.7 – 用于DHT 11温度传感器的Python GPIO代码在PI 2中失败
问答我正面临着使用Python2.7 GPIO 0.5.11在PI 2中运行DHT 11温度传感器的问题.我指的是http://www.uugear.com/portfolio/dht11-humidit ...
2
python – 类似代码之间的巨大速度差异
问答为什么以下L2范数计算之间存在如此大的速度差异: a = np.arange(1200.0).reshape((-1,3)) %timeit [np.sqrt((a*a).sum(axis=1))] ...
1
python – 这个代码是什么意思:“print >> sys.stderr”
问答print >> sys.stderr, "Error in atexit._run_exitfuncs:" 为什么要打印'>>'在sys.stderr前面 ...
1
python – 从代码中禁用pyserial中的DTR
问答我正在尝试使用pyserial将数据发送到arduino.但是当我打开COM端口时,它将DTR设置为低电平并重置电路板.但是,我有我的arduino代码设置,因此我必须通过按住两个按钮1秒钟将其置于串 ...
1
如何在文本文件上执行二进制搜索以在python中搜索关键字?
问答文本文件包含两列 – 索引号(5个空格)和字符(30个空格). 它按字典顺序排列.我想执行二进制搜索来搜索关键字.::使用Python的内置bisect模块,这是一种有趣的方法. import bis ...
试图理解Python memoization代码片段
问答在最近的Hacker Newsletter期刊中,关于Python中装饰器的this very useful article被链接了.我喜欢这篇文章,我想我理解了大多数装饰器的例子.但是,在非装饰器的 ...
1
python – 打开包含关键字参数,但只包含匹配该函数的参数
问答假设我有一个功能: def foo(a = None, b=None, c=None): return "a:%s, b:%s, c:%s" % (a,b,c) 我有一个字典包含上 ...
python – tensorflow代码TypeError:*:’int’和’Flag’的不支持的操作数类型
问答BATCH_QUEUE_MAX = 100 self._data_path = data_path self._vocab = vocab self._hps = hps self._single_p ...
python – Scrapy代码抛出TypeError:’NoneType’对象不可迭代
问答我试图提出参数site_search_url的请求,但是当我运行时出现以下错误:": start_requests = iter(self.spider.start_requests()) ...
1
python – 将代码从openCV更新为openCV2
问答我正在尝试将一些代码从openCV更新到python中的openCV2.原始代码如下: self.capture = cv.CaptureFromCAM(0) cv.SetCapturePropert ...
1
python – 将代码添加到__init__.py
问答我在看看django中的模型系统如何工作,我注意到一些我不明白的东西. 我知道你创建一个空的__init__.py文件来指定当前目录是一个包.并且你可以在__init__.py中设置一些变量,使imp ...