7月 03

在linux下用python读取其他操作系统编写的配置文件

  在windows、mac、linux下编写的配置文件会有头部或者换行有区别。为了分析方便简单做个记录,只为演示,代码并不完整,需要自己修改

def conf(conf_context):
    # 替换window或mac操作系统下的换行符
    import re
    _get_file = re.sub(r'(\r\n|\r|\n)', '\n', conf_context)
    # 将配置放在内存中
    import StringIO
    _tmp_file = StringIO.StringIO()
    # 将文件写入内存
    _tmp_file.write(_get_file)
    _tmp_file.seek(0)
    # 如果是在window下编辑的文件将,utf-8 BOM开始的头替换掉
    if _tmp_file.read(3).startswith('\xef\xbb\xbf'):
        _tmp_file.seek(3)
    else:
        _tmp_file.seek(0)
    # 导入配置
    import ConfigParser
    try:
        cf = ConfigParser.SafeConfigParser()
        cf.readfp(_tmp_file)
        config_list = cf.sections()
    except:
        _tmp_file.close()
        return "error"
    _tmp_file.close()
    return "ok"
6月 24

监控mysql从机同步状态脚本1.1

  之前写了个一个检查mysql从机的脚本(http://www.simonzhang.net/?p=1823),但是在使用中发现一个问题。如果数据库被重启了,但是同步的没有启动,此脚本检查还是正常,不会进行报警,数据不会同步。
  我做了个调整,每次检查同步主机的pos,通过crontab进行调用,如果多次都没有变化则进行告警。如果10分钟调用一次,设为3次,就是半个小时内没有更新则报警。
crontab配置如下:
*/10 * * * * /bin/bash /script/check_mysql_slave/check_mysql_slave.sh start >/dev/null 2>&1
部分代码如下:

#!/usr/local/bin/python
# -*- coding:utf-8 -*-
# -------------------------------------------------------------------------------
# Filename:    check_nagios.py
# Revision:    1.1
# Date:        2013-06-24
# Author:      simonzhang
# Email:       simon-zzm@163.com
# -------------------------------------------------------------------------------
import os
import pexpect
import time
import smtplib
from email.mime.text import MIMEText

#### base se
mysql_bin = '/program/mysql5/bin/mysql'
mysql_user = 'checkslavestatus'
mysql_pass = 'xxxxxxxxxx'
#设置错多少次开始告警
max_error = 3
mail_host = 'smtp.exmail.qq.com'
mail_user = 'warning@xxx.net'
mail_pwd = 'xxxxxxxxx'
mail_cc = "simon-zzm@163.com"
####

def mail_warn(error_ip):
    content = 'IP %s mysql slave is error!'%error_ip
    msg = MIMEText(content)
    msg['From'] = mail_user
    msg['Subject'] = 'mysql warnning %s'%error_ip
    msg['To'] = mail_to
    try:
        s = smtplib.SMTP()
        s.connect(mail_host)
        s.login(mail_user,mail_pwd)
        s.sendmail(mail_user,[mail_to],msg.as_string())
        s.close()
    except Exception ,e:
        print e

def main():
    error_context = ''
    #读取上次检查master同步点的记录
    try:
        f = open('MasterPos.txt', 'rb').read()
        try:
            old_master_pos = f.split(':')[0]
            error_count = f.split(':')[1]
        except:
            old_master_pos = 0
            error_count = 0
    except:
        old_master_pos = 0
        error_count = 0
        pass
    # 获得数据库同步状态
    status = os.popen("%s -u%s -p%s -e 'show slave status\G'"%
                      (mysql_bin,mysql_user,mysql_pass)).readlines()
    # 查看同步主节点数据
    for status_l in status:
        if status_l.find('Read_Master_Log_Pos: ') > 0:
            f = open('MasterPos.txt', 'wb')
            # 防止出现空值
            try:
                new_master_pos = int(status_l.split(': ')[1])
            except:
                new_master_pos = 0
            if int(new_master_pos) == int(old_master_pos) or int(old_master_pos):
                f.write('%s:%s' % (new_master_pos, int(error_count)+1))
            else:
                f.write('%s:0' % new_master_pos)
            f.close()
            if int(error_count)+1 > max_error:
                error_context += 'slave error!'
    # 判断是否报警
    print error_context:
    if len(error_context) > 1:
        ip = os.popen("/sbin/ifconfig|grep 'inet addr'|awk '{print $2}'").read()
        get_local_ip = ip[ip.find(':')+1:ip.find('n')]
        mail_warn("%s"%get_local_ip)

if __name__ == "__main__":
    main()

源代码

6月 07

python 对字符串的加密解密

  需求是是要将密码存在数据库里,所以要加密解密是可逆的,在数据库里不要有特殊字符,防止数据库备份和恢复中出错。
  安装PyCrypto,可以用AES和DES。我使用DES加解密。加密后将密文转为16进制,在入库。测试代码如下。

#!/bin/python
#-*- coding:utf-8 -*-
# Filename:
# Revision:    
# Date:        2013-06-07
# Author:      simonzhang
# web:         www.simonzhang.net
# Email:       simon-zzm@163.com
### END INIT INFO
# easy_install PyCrypto
from binascii import b2a_hex, a2b_hex
from Crypto.Cipher import DES
key = '12345678' #长度必须是8位的
text = 'simonzhang.net  '  #长度必须是8的倍数,我用空格补的
# 实例化
obj = DES.new(key)
# 加密
cryp = obj.encrypt(text)
pass_hex = b2a_hex(cryp)
print pass_hex
print '=' * 20
# 解密
get_cryp = a2b_hex(pass_hex)
after_text = obj.decrypt(get_cryp)
print after_text

测试代码

6月 05

python 抓取页面

  最初只是简单抓取没有问题,现在要在线上做抓取时发现很多问题。比如:长时间使用报500错误,需要cookie,有的网站有gzip压缩。本段代码已经解决以上问题,但是字符集问题没有处理,因为我要抓的页面没字符问题。我将代码放在tornado上跑,分析的服务器请求后直接抓取返回信息给分析的服务器。

import urllib2
import cookielib

def get_url_context(_url):
    # cookie
    cj = cookielib.CookieJar()
    _myopener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
    _req = urllib2.Request("http://%s" % _url)
    # add head
    _req.add_header("Accept-Language", "zh-cn")
    _req.add_header("Content-Type", "text/html; charset=utf-8")
    _req.add_header("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322)")
    # open
    _get_page_data = _myopener.open(_req)
    _get_headers = _get_page_data.info()
    _get_rawdata = _get_page_data.read()
    _get_page_data.close()
    # check gzip
    if ('Content-Encoding' in _get_headers and _get_headers['Content-Encoding']) or \
        ('content-encoding' in _get_headers and _get_headers['content-encoding']):
        import gzip
        import StringIO
        data = StringIO.StringIO(_get_rawdata)
        gz = gzip.GzipFile(fileobj=data)
        _get_rawdata = gz.read()
        gz.close()
    return _get_rawdata

get_page测试代码