Führen Sie Shell-Befehle in Python aus

65

Ich studiere derzeit Penetrationstests und Python-Programmierung. Ich möchte nur wissen, wie ich einen Linux-Befehl in Python ausführen würde. Die Befehle, die ich ausführen möchte, sind:

echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 8080

Wenn ich nur printPython verwende und es im Terminal ausführe, wird es genauso ausgeführt, als ob Sie es selbst tippen und drücken würden Enter?

iZodiac
quelle
5
os.system kann das.
Fuß
2
und ich dachte, bashes wäre eine aufgeblähte Muschel ...
mikeserv
3
Die Dokumentation os.systemempfiehlt die Verwendung des subprocessModuls.
Jordanien
Benötigen Sie die Ausgabe von iptables?
Kira
3
Diese Frage sollte nach Stackoverflow migriert werden.
www139

Antworten:

106

Sie können os.system()wie folgt verwenden:

import os
os.system('ls')

Oder in deinem Fall:

os.system('echo 1 > /proc/sys/net/ipv4/ip_forward')
os.system('iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 8080')

Besser noch, Sie können den Aufruf des Unterprozesses verwenden, er ist sicherer, leistungsfähiger und wahrscheinlich schneller:

from subprocess import call
call('echo "I like potatos"', shell=True)

Oder, ohne Shell aufzurufen:

call(['echo', 'I like potatos'])

Wenn Sie die Ausgabe erfassen möchten, gehen Sie folgendermaßen vor:

import subprocess
cmd = ['echo', 'I like potatos']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

o, e = proc.communicate()

print('Output: ' + o.decode('ascii'))
print('Error: '  + e.decode('ascii'))
print('code: ' + str(proc.returncode))

Ich empfehle dringend , ein timeoutin zu setzen communicateund auch die Ausnahmen zu erfassen, die Sie erhalten, wenn Sie es aufrufen. Dies ist ein sehr fehleranfälliger Code. Sie sollten also damit rechnen, dass Fehler auftreten, und diese entsprechend behandeln.

https://docs.python.org/3/library/subprocess.html

Kira
quelle
23
os.system ist seit Version 2.6 veraltet. Subprozess ist das richtige Modul.
Binärsubstrat
@binarysubstrate, veraltet als in nicht unterstützt oder nicht verfügbar? Ich habe vor kurzem an Maschine mit 2.7 gearbeitet (nicht durch Wahl) und arbeitet os.systemnoch.
openwonk
1
Wenn Sie subprocess.callwie empfohlen verwenden, müssen Sie möglicherweise angeben, shell=True... siehe hier
openwonk
Bei Python 3.4 muss die Shell = True angegeben werden, da sonst der Aufrufbefehl nicht funktioniert. Standardmäßig wird beim Aufruf versucht, eine durch die Zeichenfolge angegebene Datei zu öffnen, sofern nicht shell = True festgelegt ist. Es sieht auch so aus, als ob in Python 3.5 der Aufruf durch run ersetzt wird
DLH
Generischer POSIX-Code sollte wahrscheinlich decode()mit einem Zeichensatz aus einer LC_CTYPEUmgebungsvariablen aufgerufen werden.
Mikko Rantalainen
29

Der erste Befehl schreibt einfach in eine Datei. Das würden Sie nicht als Shell-Befehl ausführen, da Sie pythonohne die Hilfe einer Shell in Dateien lesen und schreiben können:

with open('/proc/sys/net/ipv4/ip_forward', 'w') as f:
    f.write("1")

Der iptablesBefehl kann extern ausgeführt werden. Der beste Weg, dies zu tun, ist die Verwendung des Unterprozessmoduls .

import subprocess
subprocess.check_call(['iptables', '-t', 'nat', '-A',
                       'PREROUTING', '-p', 'tcp', 
                       '--destination-port', '80',
                       '-j', 'REDIRECT', '--to-port', '8080'])

Beachten Sie, dass diese Methode auch keine Shell verwendet, was unnötigen Overhead bedeutet.

Jordanien
quelle
13

Der schnellste Weg:

import os
os.system("your command here")

Dies ist nicht der flexibelste Ansatz. Wenn Sie mehr Kontrolle über Ihren Prozess benötigen, als "ihn einmal bis zum Abschluss ausführen und blockieren, bis er beendet wird", sollten Sie subprocessstattdessen das Modul verwenden.

Tom Hunt
quelle
8

In der Regel sollten Sie nach Möglichkeit Python-Bindungen verwenden (unter anderem besseres Abfangen von Ausnahmen).

Für den echoBefehl ist es offensichtlich besser, Python zu verwenden, um in die Datei zu schreiben, wie in der Antwort von @ jordanm vorgeschlagen.

Für den iptablesBefehl würde möglicherweise python-iptables( PyPi-Seite , GitHub-Seite mit Beschreibung und Dokument ) angegeben, was Sie benötigen (ich habe Ihren spezifischen Befehl nicht überprüft).

Dies würde Sie von einer externen Bibliothek abhängig machen, sodass Sie die Vorteile abwägen müssen. Verwenden von Unterprozessen funktioniert, aber wenn Sie die Ausgabe verwenden möchten, müssen Sie sie selbst analysieren und in zukünftigen iptablesVersionen mit Änderungen der Ausgabe umgehen .

Jérôme
quelle
Eine andere Sache zu beachten ist, dass Unit-Testing-Code mit subprocessAufrufen weniger nützlich ist. Ja, Sie können die Anrufe verspotten, aber die Tests müssen Annahmen über die Ergebnisse der externen Anrufe treffen.
Jordanien
Ihre Antwort ist eher ein Ratschlag. Das OP hat speziell gefragt, wie er einen Linux-Systembefehl von Python ausführen kann.
Kapad
@kapad Ja, aber er hat auch angegeben, warum er das wollte, und ich habe eine Alternative vorgeschlagen.
Jérôme
2

Eine Python-Version Ihrer Shell. Sei vorsichtig, ich habe es nicht getestet.

from subprocess import run

def bash(command):
        run(command.split())

>>> bash('find / -name null')
/dev/null
/sys/fs/selinux/null
/sys/devices/virtual/mem/null
/sys/class/mem/null
/usr/lib/kbd/consoletrans/null
Timothy Pulliam
quelle
0

Wenn Sie diesen Befehl in einem anderen System nach SSH ausführen möchten, müssen Sie möglicherweise das Modul namens Paramiko verwenden. Es ist wirklich nützlich.

Wenn die Befehlsausführung von einem lokalen Computer aus erfolgen muss, sind die Funktionen des OS-Moduls hilfreich.

Homepage: https://www.paramiko.org/

Entwicklung: https://github.com/paramiko/paramiko

Mikhilesh Sekhar
quelle