我在尝试构建简单的备份/升级数据库脚本时遇到问题。
错误在使用子进程的mysqldump调用中:
cmdL = ["mysqldump", "--user=" + db_user, "--password=" + db_pass, domaindb + "|", "gzip", ">", databases_path + "/" + domaindb + ".sql.gz"]
print "%s: backup database %s \n\t[%s]" % (domain, domaindb, ' '.join(cmdL))
total_log.write("%s: backup database %s \n\t[%s] \n" % (domain, domaindb, ' '.join(cmdL)))
p = subprocess.Popen(cmdL, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
在此之前,我将sys.stdout
和sys.stderr
重定向到文件,以便有一个日志系统。
在那些日志中,我发现错误:
[mysqldump--user=xxxxxx--password=yyyyyyyyy数据库名称| gzip>;/home/drush backup/2010-08-30.15.37/db/数据库名称.sql] [错误]:mysqldump:找不到表:“|”
似乎|
字符被视为mysqldump参数,而不是管道。
查看python子流程文档,这是正常的,但是如何获得所需的内容(调用命令mysqldump --user=xxxxxx --password=yyyyyyyy database_name | gzip > /home/drush-backup/2010-08-30.15.37/db/database_name.sql
)?
编辑我在python文档中看到了这个示例:
output=`dmesg | grep hda`
==>
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]
我已经编辑了我的脚本:
command = ["mysqldump", "--user=" + db_user, "--password=" + db_pass, domaindb, "|", "gzip", ">", databases_path + "/" + domaindb + ".sql.gz"]
cmdL1 = ["mysqldump", "--user=" + db_user, "--password=" + db_pass, domaindb]
cmdL2 = ["gzip", ">", databases_path + "/" + domaindb + ".sql.gz"]
print "%s: backup database %s \n\t[%s]" % (domain, domaindb, ' '.join(command))
total_log.write("%s: backup database %s \n\t[%s] \n" % (domain, domaindb, ' '.join(command)))
p1 = subprocess.Popen(cmdL1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
p2 = subprocess.Popen(cmdL2, stdin=p1.stdout, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
cmdError, cmdData = p2.communicate()
现在命令变量只是为了方便在日志中使用。
下一步将执行此操作,但它将在>
流中停止,并出现以下错误:
[Error]: gzip: >: No such file or directory
gzip: /path/to/backups/dir/natabase_name.sql.gz: No such file or directory
显然,如果我在终端上尝试这个命令,它就会工作。
尝试
subprocess.Popen(' '.join(cmdL), shell=True)
。管道(和重定向)被识别为这样,并由shell调度,并且在默认情况下(在Unix上),
subprocess
避免使用shell(它比较慢,给您的控制力也比较小)——如果管道或重定向是您绝对必须拥有的,则需要显式强制shell处于控制状态。通常情况下,人们会尽量在Python中避免管道(从而避免
shell=True
和关注的问题)(例如,在您的例子中,使用Python标准库的gzip
模块)。当然,对于这个,必须小心地将stdout(将进一步处理)与stderr分离,作为两个独立的管道。我不知道这管子怎么解释。如果这是一个问题,您可以编程创建一个pipelline。
发件人: http://docs.python.org/library/subprocess.html#replacing-shell-pipeline
编辑
至于文件重定向,可以将stdout指向文件。。
示例:
或者,如果您采纳Alex的建议并使用Python的标准库gzip模块,则可以执行以下操作:
给定path、user、pswd和dbname后,下面的操作就像一个符咒:
在
subprocess.Popen()
中使用f
作为stdout参数也可以工作,但不会压缩数据。 在Python 2.7之前,with
语句不起作用,因此请使用f=gzip.open(..)
和f.close()
。可以使用p.stderr.read()
读取错误,因此如果这不是空字符串,最好引发异常要恢复备份,可以执行以下操作:
相关问题 更多 >
编程相关推荐