Jalankan perintah shell dengan Python


65

Saya sedang mempelajari pengujian penetrasi dan pemrograman Python. Saya hanya ingin tahu bagaimana cara menjalankan perintah Linux dengan Python. Perintah yang ingin saya jalankan adalah:

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

Jika saya hanya menggunakan printPython dan menjalankannya di terminal, apakah akan melakukan hal yang sama seperti mengeksekusi seolah-olah Anda mengetik sendiri dan menekan Enter?


5
os.sistem dapat melakukan ini.
Foot

2
dan saya pikir bashitu adalah shell yang membengkak ...
mikeserv

3
Dokumen untuk os.systemdirekomendasikan menggunakan subprocessmodul.
jordanm

Apakah Anda memerlukan output dari iptables?
Kira

3
Pertanyaan ini harus dimigrasikan ke Stackoverflow.
www139

Jawaban:


106

Anda dapat menggunakan os.system(), seperti ini:

import os
os.system('ls')

Atau dalam kasus Anda:

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

Lebih baik lagi, Anda dapat menggunakan panggilan subproses, lebih aman, lebih kuat, dan lebih cepat:

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

Atau, tanpa menggunakan shell:

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

Jika Anda ingin menangkap output, salah satu cara melakukannya adalah seperti ini:

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

Saya sangat merekomendasikan pengaturan timeoutdi communicate, dan juga untuk menangkap pengecualian Anda bisa dapatkan ketika menyebutnya. Ini adalah kode yang sangat rawan kesalahan, jadi Anda harus mengharapkan kesalahan terjadi dan menanganinya sesuai.

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


23
os.sistem sudah tidak digunakan lagi sejak versi 2.6. Subproses adalah modul yang tepat untuk digunakan.
binarysubstrate

@ biner substrat, usang karena tidak didukung atau tidak tersedia? Saya baru-baru ini mengerjakan mesin dengan 2.7 (bukan karena pilihan), dan os.systemmasih berfungsi.
openwonk

1
Juga, jika menggunakan subprocess.callseperti yang disarankan, Anda mungkin perlu menentukan shell=True... lihat di sini
openwonk

Dengan Python 3.4 shell = True harus dinyatakan sebaliknya perintah panggilan tidak akan berfungsi. Secara default panggilan akan mencoba membuka file yang ditentukan oleh string kecuali shell = True diatur. Ini juga terlihat seperti itu di Python 3.5 panggilan diganti dengan menjalankan
DLH

Kode POSIX generik mungkin harus memanggil decode()dengan charset dari LC_CTYPEvariabel lingkungan.
Mikko Rantalainen

29

Perintah pertama hanya menulis ke file. Anda tidak akan menjalankan itu sebagai perintah shell karena pythondapat membaca dan menulis ke file tanpa bantuan shell:

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

The iptablesPerintah adalah sesuatu yang Anda mungkin ingin mengeksekusi eksternal. Cara terbaik untuk melakukan ini adalah dengan menggunakan modul subproses .

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

Perhatikan bahwa metode ini juga tidak menggunakan shell, yang merupakan overhead yang tidak perlu.


13

Cara tercepat:

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

Ini bukan pendekatan yang paling fleksibel; jika Anda memerlukan kontrol lebih besar atas proses Anda daripada "jalankan sekali, sampai selesai, dan blokir sampai keluar", maka Anda harus menggunakan subprocessmodul sebagai gantinya.


8

Sebagai aturan umum, Anda sebaiknya menggunakan python binding kapan pun memungkinkan (menangkap Pengecualian yang lebih baik, di antara kelebihan lainnya.)

Untuk echoperintah, jelas lebih baik menggunakan python untuk menulis dalam file seperti yang disarankan dalam jawaban @ jordanm.

Untuk iptablesperintah, mungkin python-iptables( halaman PyPi , halaman GitHub dengan deskripsi dan dokumen ) akan memberikan apa yang Anda butuhkan (saya tidak memeriksa perintah spesifik Anda).

Ini akan membuat Anda bergantung pada lib eksternal, jadi Anda harus mempertimbangkan manfaatnya. Menggunakan karya subproses, tetapi jika Anda ingin menggunakan output, Anda harus menguraikan sendiri, dan menangani perubahan output dalam iptablesversi yang akan datang .


Satu hal yang perlu diperhatikan adalah bahwa kode pengujian unit dengan subprocesspanggilan kurang bermanfaat. Ya, Anda dapat mengejek panggilan, tetapi tes harus membuat asumsi tentang hasil pada panggilan eksternal.
jordanm

Jawaban Anda lebih seperti saran. OP secara khusus bertanya bagaimana ia dapat menjalankan perintah sistem linux dari python.
kapad

@ Kapad Ya, tapi dia juga menjelaskan mengapa dia ingin melakukannya dan saya mengusulkan alternatif.
Jérôme

2

Versi python dari shell Anda. Hati-hati, saya belum mengujinya.

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.