Python-Unterprozess, mysqldump und Pipes

Ich habe ein Problem, das versucht, ein einfaches Backup / Upgrade-Datenbank-Skript zu erstellen.

Der Fehler ist im mysqldump-Aufruf unter Verwendung des Unterprozesses:

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) 

Vor diesem Cose, ich umleiten sys.stdout und sys.stderr in Dateien, um ein Log-System haben.

In diesem Protokoll finde ich den Fehler:

[Mysqldump –user = xxxxxx –password = yyyyyyyy Datenbankname Gzip> /home/drush-backup/2010-08-30.15.37/db/database_name.sql] [Fehler]: mysqldump: Konnte die Tabelle nicht finden: "|"

Scheint, dass die | Charakter wird als mysqldump Argumente gesehen, stattdessen als Pipe.

Wenn ich in die Pythonmysqldump --user=xxxxxx --password=yyyyyyyy database_name | gzip > /home/drush-backup/2010-08-30.15.37/db/database_name.sql , dann ist das normal, aber wie mysqldump --user=xxxxxx --password=yyyyyyyy database_name | gzip > /home/drush-backup/2010-08-30.15.37/db/database_name.sql was ich brauche (ruf den Befehl mysqldump --user=xxxxxx --password=yyyyyyyy database_name | gzip > /home/drush-backup/2010-08-30.15.37/db/database_name.sql )?

BEARBEITEN Ich sehe gerade dieses Beispiel auf Python-Docs:

 output=`dmesg | grep hda` ==> p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) output = p2.communicate()[0] 

Und ich habe mein Skript bearbeiten:

 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() 

Jetzt wird die Befehlsvariable gerade für die Bequemlichkeit in Protokollen verwendet.

Dies geht einen Schritt weiter, aber es hört im > Stream auf, mit diesem Fehler:

 [Error]: gzip: >: No such file or directory gzip: /path/to/backups/dir/natabase_name.sql.gz: No such file or directory 

Offensichtlich, wenn ich den Befehl in einem Terminal ausprobiere, funktioniert es.

3 Solutions collect form web for “Python-Unterprozess, mysqldump und Pipes”

Ich bin mir nicht sicher, wie die Pfeife interpretiert wird. Wenn das ein Problem ist, kannst du programmatisch einen Pipelilne erstellen.

Von: http://docs.python.org/library/subprocess.html#replacing-shell-pipeline

 p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) output = p2.communicate()[0] 

bearbeiten

Wie für die Dateiumleitung können Sie stdout in eine Datei eintragen.

Stdin, stdout und stderr spezifizieren die Standard-Eingabe, die Standardausgabe und die Standardfehler-Datei-Handles der ausgeführten Programme. Gültige Werte sind PIPE, ein vorhandener Dateideskriptor (ein positiver Integer), ein vorhandener Dateiprojekt und keine.

Beispiel:

 out_file = open(out_filename, "wb") gzip_proc = subprocess.Popen("gzip", stdout=out_file) gzip_proc.communicate() 

Oder wenn Sie Alex's Rat nehmen und Pythons Standard-Bibliothek gzip- Modul verwenden, können Sie so etwas tun:

 import gzip import subprocess ... #out_filename = path to gzip file cmdL1 = ["mysqldump", "--user=" + db_user, "--password=" + db_pass, domaindb] p1 = subprocess.Popen(cmdL1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) dump_output = p1.communicate()[0] f = gzip.open(out_filename, "wb") f.write(dump_output) f.close() 

Versuche subprocess.Popen(' '.join(cmdL), shell=True) .

Pipelines (und Umleitungen) werden als solche erkannt und von der Shell geplant , und standardmäßig (auf Unix) vermeidet der subprocess die Verwendung einer Shell (es ist langsamer und gibt Ihnen weniger Kontrolle) – Sie müssen explizit eine Shell erzwingen Kontrolle, wenn eine Pipeline oder Umleitung ist, was Sie unbedingt haben müssen.

Normalerweise versucht man, Pipelines zu vermeiden (und damit vermeiden shell=True und shell=True Attendand Issues), indem du so viel wie möglich in Python machst (zB in deinem Fall mit dem gzip Modul von Pythons Standardbibliothek). Natürlich muss man hierfür stabile Stdout (wie man weiterverarbeiten soll) sorgfältig trennen, als zwei getrennte Rohre.

Mit Pfad, Benutzer, pswd und dbname gegeben, die folgenden Werke wie ein Charme:

 import gzip from subprocess import Popen, PIPE cmd = "mysqldump --user={user} --password={pswd} {dbname}".format(**locals()) p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE) with gzip.open(path, "wb") as f: f.writelines(p.stdout) 

Mit f als stdout-Argument in subprocess.Popen() funktioniert auch, aber nicht komprimieren die Daten. Vor Python 2.7 funktioniert die with Anweisung nicht, also verwenden Sie f=gzip.open(..) und f.close() . Fehler können mit p.stderr.read() gelesen werden, also wenn dies nicht eine leere Zeichenfolge ist, p.stderr.read() du besser eine Ausnahme aus


Um die Sicherung wiederherzustellen , können Sie Folgendes tun:

 cmd = "mysql --user={user} --password={pswd} {dbname}".format(**locals()) p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE) with gzip.open(path, "rb") as f: p.stdin.write(f.read()) p.communicate()[0] p.stdin.close() p_err = p.stderr.read() if p_err: raise Exception('Error restoring database:\n{0}'.format(p_err)) 
  • Modul-Subprozess hat kein Attribut 'STARTF_USESHOWWINDOW'
  • Überprüfen Sie den Rückgabecode eines Befehls, wenn der Unterprozess eine CalledProcessError-Ausnahme auslöst
  • Python: Ausführen eines Shell-Befehls
  • Python, um Benutzereingaben in einem interaktiven Perl-Skript zu emulieren
  • Erstellen von Befehlszeilenalias mit Python
  • Führen Sie mehrere Programme nacheinander in einer Windows-Eingabeaufforderung aus?
  • Python - Unterprozess mit Zitaten und Pipe Grep
  • Alternative in python zu subprocess
  • Python ist die beste Programmiersprache der Welt.