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?


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


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.


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.


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.


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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.