基于Python的数据库备份脚本错误捕捉

62 阅读2分钟

用户遇到一个问题,在使用Python脚本备份和加密MySQL数据库时,遇到了错误代码3,很难找到具体的原因。他希望能够捕获到标准错误输出(stderr)的信息,以帮助诊断错误情况。脚本代码如下:

huake_00257_.jpg

def dbbackup():
    while True:
        item = q.get()
        # 省略其他代码...

        args = ['mysqldump', '-u', config[item]['UserNm'],
                '-p' + config[item]['Passwd'], '-P', config[item]['Portnu'],
                '-h', config[item]['Server']]
        args.extend(config[item]['MyParm'].split())
        args.append(config[item]['DBName'])
        p1 = subprocess.Popen(args, stdout=subprocess.PIPE)
        p2 = subprocess.Popen(['gpg', '-o', genfile, '-r',
                               config[item]['PubKey'], '-z', '9', '--encrypt'], stdin=p1.stdout)
        p2.wait()
        if p2.returncode == 0:
            syslog.syslog(item + ' encryption successful')
        else:
            syslog.syslog(syslog.LOG_CRIT, item + ' encryption failed '+str(p2.returncode))
            p1.terminate()
        p1.wait()
        # 省略其他代码...

def main():
    # 省略其他代码...

    for i in range(2):
        t = threading.Thread(target=dbbackup)
        t.daemon = True
        t.start()

if __name__ == '__main__':
    main()

2. 解决方案

为了让脚本能够捕捉到标准错误输出(stderr)的信息,可以采用以下步骤:

  1. subprocess.Popen()中将stderr参数设置为subprocess.PIPE,这样就可以将标准错误输出信息捕获到一个管道中。
  2. p1p2进程中,使用communicate()方法来获取标准输出和标准错误信息。
  3. 检查p2.returncodep1.returncode的值,如果它们不为0,则表示出现了错误,此时可以读取错误信息并记录下来。

修改后的代码如下:

def dbbackup():
    while True:
        item = q.get()
        # 省略其他代码...

        args = ['mysqldump', '-u', config[item]['UserNm'],
                '-p' + config[item]['Passwd'], '-P', config[item]['Portnu'],
                '-h', config[item]['Server']]
        args.extend(config[item]['MyParm'].split())
        args.append(config[item]['DBName'])
        p1 = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        p2 = subprocess.Popen(['gpg', '-o', genfile, '-r',
                               config[item]['PubKey'], '-z', '9', '--encrypt'], stdin=p1.stdout, stderr=subprocess.PIPE)
        out, err = p2.communicate()
        if p2.returncode == 0:
            syslog.syslog(item + ' encryption successful')
        else:
            syslog.syslog(syslog.LOG_CRIT, item + ' encryption failed '+str(p2.returncode))
            p1.terminate()
        p1.wait()
        out, err = p1.communicate()
        if p1.returncode == 0:
            # 省略其他代码...
        else:
            syslog.syslog(syslog.LOG_CRIT, item + ' extract failed '+str(p1.returncode))
        q.task_done()

def main():
    # 省略其他代码...

    for i in range(2):
        t = threading.Thread(target=dbbackup)
        t.daemon = True
        t.start()

if __name__ == '__main__':
    main()

现在,当p2p1进程出现错误时,脚本就会将标准错误输出信息捕获到outerr变量中,然后可以将其输出到日志文件中或使用其他方式处理。