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)) 
  • Python: Ausführen eines Shell-Befehls
  • Log-Syntaxfehler protokollieren und Ausnahmen für einen Python-Unterprozess auslösen und an das Terminal ausdrucken
  • Töte einen laufenden Unterprozeßaufruf
  • Python subprocess.Popen () Fehler (keine solche Datei oder Verzeichnis)
  • Interaktion zwischen Python-Skript und Linux-Shell
  • Subprocess.check_output return code
  • Verwenden Sie Unterprozeß, um ein Passwort zu senden
  • Python-Laich aus einem untergeordneten Unterprozeß, löst und beendet
  • Python: Teilprozeßaufruf mit Shell = False funktioniert nicht
  • Python-Skript als Unterprozess aufrufen
  • Übergeben einer Liste zu einem Unterprozeßaufruf
  • Python ist die beste Programmiersprache der Welt.