Thực thi các lệnh shell trong Python


65

Tôi hiện đang nghiên cứu thử nghiệm thâm nhập và lập trình Python. Tôi chỉ muốn biết làm thế nào tôi sẽ thực hiện một lệnh Linux trong Python. Các lệnh tôi muốn thực hiện là:

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

Nếu tôi chỉ sử dụng printtrong Python và chạy nó trong thiết bị đầu cuối, nó sẽ làm tương tự như thực thi nó như thể bạn đang tự gõ nó và nhấn Enter?


5
os.system có thể làm điều này.
fooot

2
và tôi nghĩ đó bashlà một cái vỏ
sần sùi

3
Các tài liệu cho os.systemđề nghị sử dụng subprocessmô-đun.
jordanm

Bạn có cần đầu ra của iptables không?
Kira

3
Câu hỏi này nên được chuyển sang Stackoverflow.
www139

Câu trả lời:


106

Bạn có thể sử dụng os.system(), như thế này:

import os
os.system('ls')

Hoặc trong trường hợp của bạn:

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

Tốt hơn nữa, bạn có thể sử dụng cuộc gọi của quy trình con, nó an toàn hơn, mạnh mẽ hơn và có khả năng nhanh hơn:

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

Hoặc, không cần gọi shell:

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

Nếu bạn muốn chụp đầu ra, một cách thực hiện là như sau:

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

Tôi đánh giá cao đề nghị thiết lập một timeouttrong communicate, và cũng để nắm bắt những trường hợp ngoại lệ, bạn có thể nhận được khi gọi nó. Đây là một mã rất dễ bị lỗi, vì vậy bạn nên mong đợi các lỗi xảy ra và xử lý chúng cho phù hợp.

https://docs.python.org/3/l Library / sub process.html


23
os.system không dùng nữa kể từ phiên bản 2.6. Sub process là mô-đun phù hợp để sử dụng.
nhị phân

@binarysubstrate, không dùng nữa vì không được hỗ trợ hay không có sẵn? Gần đây tôi đã làm việc trên máy với 2.7 (không phải do lựa chọn) và os.systemvẫn hoạt động.
openwonk

1
Ngoài ra, nếu sử dụng subprocess.callnhư được đề xuất, bạn có thể cần chỉ định shell=True... xem tại đây
openwonk

Với Python 3.4, shell = True phải được nêu nếu không lệnh gọi sẽ không hoạt động. Theo mặc định, cuộc gọi sẽ cố gắng mở một tệp được chỉ định bởi chuỗi trừ khi shell = True được đặt. Có vẻ như trong cuộc gọi Python 3.5 được thay thế bằng chạy
DLH

Mã POSIX chung có lẽ nên gọi decode()với bộ ký tự từ LC_CTYPEbiến môi trường.
Mikko Rantalainen

29

Lệnh đầu tiên chỉ cần ghi vào một tập tin. Bạn sẽ không thực thi điều đó như một lệnh shell bởi vì pythoncó thể đọc và ghi vào các tệp mà không cần sự trợ giúp của shell:

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

Các iptableslệnh là một cái gì đó bạn có thể muốn thực hiện bên ngoài. Cách tốt nhất để làm điều này là sử dụng mô đun quy trình con .

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

Lưu ý rằng phương pháp này cũng không sử dụng shell, đó là chi phí không cần thiết.


13

Cách nhanh nhất:

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

Đây không phải là cách tiếp cận linh hoạt nhất; nếu bạn cần bất kỳ quyền kiểm soát nào đối với quy trình của mình hơn là "chạy một lần, để hoàn thành và chặn cho đến khi thoát", thì bạn nên sử dụng subprocessmô-đun thay thế.


8

Theo nguyên tắc chung, bạn nên sử dụng các ràng buộc python bất cứ khi nào có thể (bắt ngoại lệ tốt hơn, trong số các lợi thế khác.)

Đối với echolệnh, rõ ràng tốt hơn là sử dụng python để ghi vào tệp như được đề xuất trong câu trả lời của @ jordanm.

Đối với iptableslệnh, có thể python-iptables( trang PyPi , trang GitHub với mô tả và tài liệu ) sẽ cung cấp những gì bạn cần (Tôi không kiểm tra lệnh cụ thể của bạn).

Điều này sẽ làm cho bạn phụ thuộc vào một lib bên ngoài, vì vậy bạn phải cân nhắc lợi ích. Sử dụng quy trình con hoạt động, nhưng nếu bạn muốn sử dụng đầu ra, bạn sẽ phải tự phân tích cú pháp và xử lý các thay đổi đầu ra trong các iptablesphiên bản trong tương lai .


Một điều cần lưu ý là mã kiểm tra đơn vị với subprocesscác cuộc gọi ít hữu ích hơn. Có, bạn có thể giả lập các cuộc gọi, nhưng các bài kiểm tra phải đưa ra các giả định về kết quả của các cuộc gọi bên ngoài.
jordanm

Câu trả lời của bạn giống như lời khuyên. OP đã hỏi cụ thể làm thế nào anh ta có thể chạy một lệnh hệ thống linux từ python.
kapad

@kapad Có, nhưng anh ấy cũng chỉ định lý do tại sao anh ấy muốn làm như vậy và tôi đã đề xuất một giải pháp thay thế.
Jérôme

2

Một phiên bản python của vỏ của bạn. Hãy cẩn thận, tôi đã không kiểm tra nó.

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

0

Nếu bạn muốn thực thi lệnh này trong một số hệ thống khác sau SSH thì bạn có thể phải sử dụng mô-đun có tên Paramiko. Nó thực sự hữu ích.

Nếu việc thực thi lệnh phải được thực hiện từ máy cục bộ thì các chức năng mô-đun os sẽ hữu ích.

Trang chủ: https://www.paramiko.org/

Phát triển: https://github.com/paramiko/paramiko

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.