Übergeben von Variablen zu Teilprozess.Popen
Ich habe ein script, das ruft ein weiteres python-Skript durch den Teilprozess.Popen-Modul. Da habe ich aber Argumente gespeichert in variable(N)
servers[server]['address']
servers[server]['port']
servers[server]['pass']
Ich bin nicht in der Lage, um den Befehl auszuführen
p = subprocess.Popen(["python mytool.py -a ", servers[server]['address'], "-x", servers[server]['port'], "-p", servers[server]['pass'], "some additional command"], shell=True, stdout=subprocess.PIPE)
- Die die Variablen verwenden, erstellen Sie eine Zeichenfolge, die den Befehl oder geben Sie Sie als eine Liste von Argumenten.
- Antworten, die nicht bearbeitet werden sollen, zu Fragen. Dabei vermeidet der springende Punkt bei der Bestellung basierend auf community-gewichtete Abstimmung, die ist besonders gefährlich, weil hier die Problemumgehung, die Sie verwenden, hat schwerwiegende Sicherheitslücken (wenn Sie einen server-Namen enthält
$(rm -rf ~)
, erraten, was passiert?). - Siehe auch Ist es OK, für die Bearbeitung der akzeptierten Antworten in der Frage? auf Meta-Stack Overflow.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Drop
shell=True
. Die Argumente, diePopen()
unterschiedlich behandelt werden, die auf Unix -, wennshell=True
:Beachten Sie, dass übergeben
shell=True
für Befehle mit externen Eingang ist ein Sicherheitsrisiko, wie beschrieben, durch eine Abmahnung in den docs.Beim Aufruf
subprocess.Popen
können Sie entweder einen string oder eine Liste, zu der der Befehl ausgeführt werden. Wenn Sie übergeben eine Liste, die Elemente, die geteilt werden soll, in einer bestimmten Weise.In Ihrem Fall, Sie brauchen, um es zu teilen, so etwas wie dieses:
Dies ist, weil, wenn Sie übergeben eine Liste
Popen
davon ausgegangen, dass Sie bereits aufteilen der Kommandozeile in Worte (die Werte, insys.argv
), so dass es nicht müssen.Die Art und Weise, die Sie aufrufen, es wird versuchen, eine Binärdatei namens "python mytool.py -ein", das ist nicht, was Sie meinte.
Den anderen Weg, es zu beheben ist, sich alle Wörter in einem string (die
Popen
wird dann aufgeteilt - sieheUnterprozess.list2cmdline
). Aber du bist besser dran mit der Liste, version, wenn möglich - es gibt einfachere Kontrolle darüber, wie die Kommandozeile aufgeteilt werden (wenn Sie Argumente mit Leerzeichen oder Anführungszeichen in Ihnen, zum Beispiel), ohne Durcheinander herum mit quoting Quoting-Zeichen.Dein problem geben
str
für die erstenPopen
argument. Ersetzen Sie, umlist
. Code unten funktionieren kann:Wenn
command
Argumente kommen von einer vertrauenswürdigen Quelle, können Sie konstruierencommand
und verwenden Sie es mitshell=True
auf solche Weise:Hinweis 1: konstruiert
command
mitshell=True
ist potenziell unsicher. Verwendenpipes.quote()
reduzieren-injection-Möglichkeit.Note 2:
pipes.quote()
veraltet seitpython2
; fürpython3
verwendenshlex
Modul.shell=True
das erste argument wird behandelt wie ein shell-Skript, und die nachfolgenden Argumente als Parameter für das Skript (seine$0
,$1
, etc). Die Ergebnisse diesershlex.split()
operation ist nicht eine Liste soll analysiert werden, die Weise; in der Praxis wird es laufenpython
ohne Argumente.pipes.quote()
(oder in Python 3shlex.quote()
) für die Erstellung von Inhalt, der kann ersetzt werden, in einen shell-Befehl sicher, anstatt nur darum, in unsafe-code mit ein paar Einschränkungen.Fassen Sie den Befehl, um eine ganze Zeichenfolge:
$(rm -rf ~)
ist, solltest du besser hoffe, niemand ist mit dieser Verkettung-basierten Ansatz. Dies ist Massiv unsicher, auch wenn Sie do verwenden möchtenshell=True
, die (nur) sicheren Weg, es zu tun ist die übergabe von Variablen out-of-band-script-code:p = subprocess.Popen(['python mytool.py -a "$1" -x "$2" -p "$3" some additional command', '_', str(servers[server]['address']), str(servers[server]['port']), str(servers[server]['pass'])], shell=True, stdout=subprocess.PIPE)