Wykonuj polecenia powłoki w Pythonie

65

Obecnie studiuję testy penetracyjne i programowanie w języku Python. Chcę tylko wiedzieć, jak bym wykonał polecenie Linuksa w Pythonie. Polecenia, które chcę wykonać, to:

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

Jeśli po prostu printużyję w Pythonie i uruchomię go w terminalu, czy będzie on działał tak samo jak wykonywanie go tak, jakbyś pisał go sam i naciskał Enter?

iZodiac
źródło
5
os.system może to zrobić.
fooot
2
i pomyślałem, że bashto
rozdęta
3
Dokumenty os.systempolecają korzystanie z subprocessmodułu.
jordanm
Czy potrzebujesz wyjścia z iptables?
Kira
3
To pytanie należy przenieść do Stackoverflow.
www139,

Odpowiedzi:

106

Możesz użyć os.system()takiego:

import os
os.system('ls')

Lub w twoim przypadku:

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

Co więcej, możesz użyć połączenia podprocesu, jest to bezpieczniejsze, potężniejsze i prawdopodobnie szybsze:

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

Lub bez wywoływania powłoki:

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

Jeśli chcesz przechwycić dane wyjściowe, możesz to zrobić w następujący sposób:

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

Ja bardzo polecam ustawienie timeoutin communicate, a także przechwytywać wyjątków można uzyskać podczas wywoływania go. Jest to bardzo podatny na błędy kod, więc należy spodziewać się, że wystąpią błędy i odpowiednio je obsłużyć.

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

Kira
źródło
23
os.system jest przestarzały od wersji 2.6. Podproces jest właściwym modułem do użycia.
binarysubstrate
@ binarysubstrate, przestarzałe, ponieważ nie jest obsługiwane lub niedostępne? Ostatnio pracuję na komputerze z wersją 2.7 (nie z wyboru) i os.systemnadal działa.
openwonk,
1
Ponadto, jeśli używasz subprocess.callzgodnie z zaleceniami, może być konieczne określenie shell=True... patrz tutaj
openwonk
W Pythonie 3.4 należy podać shell = True, w przeciwnym razie polecenie call nie będzie działać. Domyślnie wywołanie będzie próbowało otworzyć plik określony przez ciąg znaków, chyba że ustawiono shell = True. Wygląda również na to, że w Pythonie 3.5 wywołanie jest zastąpione przez run
DLH
Ogólny kod POSIX powinien prawdopodobnie wywoływać za decode()pomocą zestawu znaków ze LC_CTYPEzmiennej środowiskowej.
Mikko Rantalainen
29

Pierwsze polecenie po prostu zapisuje do pliku. Nie wykonałbyś tego jako polecenia powłoki, ponieważ pythonmoże czytać i zapisywać pliki bez pomocy powłoki:

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

iptablesKomenda jest coś może chcesz wykonać na zewnątrz. Najlepszym sposobem na to jest użycie modułu podprocesu .

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

Zauważ, że ta metoda również nie używa powłoki, co jest niepotrzebnym narzutem.

Jordan
źródło
13

Najszybszy sposób:

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

To nie jest najbardziej elastyczne podejście; jeśli potrzebujesz więcej kontroli nad procesem niż „uruchom go raz, do końca i blokuj, aż zakończy się”, powinieneś subprocesszamiast tego użyć modułu.

Tom Hunt
źródło
8

Zasadniczo lepiej używać powiązań pytona, gdy tylko jest to możliwe (między innymi lepsze przechwytywanie wyjątków).

W przypadku echopolecenia lepiej jest użyć Pythona do zapisu w pliku, jak sugeruje odpowiedź @ jordanm.

Do iptablespolecenia, może python-iptables( strona PyPI , GitHub strona z opisem i doc ) stanowiłaby co trzeba (nie sprawdzić konkretną komendę).

To sprawi, że będziesz zależał od zewnętrznej biblioteki lib, więc musisz rozważyć korzyści. Korzystanie z podprocesu działa, ale jeśli chcesz użyć danych wyjściowych, musisz je przeanalizować samodzielnie i poradzić sobie ze zmianami danych wyjściowych w przyszłych iptableswersjach.

Jérôme
źródło
Inną rzeczą wartą odnotowania jest to, że kod testowania jednostkowego z subprocesspołączeniami jest mniej przydatny. Tak, możesz wyśmiewać połączenia, ale testy muszą opierać się na wynikach połączeń zewnętrznych.
jordanm
Twoja odpowiedź jest bardziej jak rada. OP dokładnie zapytał, w jaki sposób może uruchomić komendę systemu Linux z python.
kapad
@kapad Tak, ale określił również, dlaczego chce to zrobić, a ja zaproponowałem alternatywę.
Jérôme,
2

Pythonowa wersja twojej powłoki. Uważaj, nie testowałem tego.

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
źródło
0

Jeśli chcesz wykonać to polecenie w innym systemie po SSH, być może będziesz musiał użyć modułu o nazwie Paramiko. To jest naprawdę przydatne.

Jeśli wykonanie polecenia musi być wykonane z lokalnego komputera, pomocne będą funkcje modułu os.

Strona domowa: https://www.paramiko.org/

Rozwój: https://github.com/paramiko/paramiko

Mikhilesh Sekhar
źródło