Виконайте команди оболонки в Python


65

Зараз я вивчаю тестування на проникнення та програмування Python. Мені просто хочеться знати, як би я пішов про виконання команди Linux в Python. Команди, які я хочу виконати:

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

Якщо я просто використовую printв Python і запускаю його в терміналі, чи буде це так само, як виконувати його, як якщо б ви ввели його самостійно і натиснули Enter?


5
os.system може це зробити.
пізно

2
і я думав, що bashце роздута оболонка ...
mikeserv

3
Документи, які os.systemрекомендують використовувати subprocessмодуль.
Йорданм

Вам потрібен вихід iptables?
Кіра

3
Це питання слід перенести на Stackoverflow.
www139

Відповіді:


106

Ви можете використовувати os.system(), як це:

import os
os.system('ls')

Або у вашому випадку:

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

Ще краще, ви можете використовувати дзвінок підпроцесу, він безпечніший, потужніший і швидше за все:

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

Або без виклику оболонки:

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

Якщо ви хочете отримати результат, один із способів зробити це такий:

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

Я настійно рекомендую встановлювати timeoutв системі communicate, а також для захоплення виключення ви можете отримати при виклику його. Це дуже схильний до помилок код, тож слід очікувати, що помилки трапляються, і їх обробляти відповідно.

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


23
os.system застаріла з версії 2.6. Підпроцес - це правильний модуль для використання.
binarysubstrate

@binarysubstrate, застарілий як не підтримується чи недоступний? Я нещодавно працюю на машині з 2.7 (не за вибором), і os.systemдосі працює.
openwonk

1
Крім того, якщо ви використовуєте, subprocess.callяк рекомендується, вам може знадобитися вказати shell=True... дивіться тут
openwonk

З Python 3.4 оболонку = True слід вказати, інакше команда виклику не працюватиме. За замовчуванням виклик спробує відкрити файл, вказаний рядком, якщо не встановлено оболонку = True. Так само виглядає, що в Python 3.5 виклик замінюється на run
DLH

Загальний код POSIX, ймовірно, повинен дзвонити decode()із шаблоном із LC_CTYPEзмінної середовища.
Mikko Rantalainen

29

Перша команда просто записує у файл. Ви б не виконували це як команду оболонки, тому що pythonможете читати та записувати у файли без допомоги оболонки:

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

iptablesКоманда що - то ви можете виконати зовні. Найкращий спосіб зробити це - використовувати модуль підпроцесу .

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

Зауважте, що цей метод також не використовує оболонку, що зайве над головою.


13

Найшвидший спосіб:

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

Це не найбільш гнучкий підхід; якщо вам потрібен якийсь більший контроль над вашим процесом, ніж "запустити його один раз, до його завершення та заблокувати, поки він не завершиться", тоді subprocessзамість цього слід використовувати модуль.


8

Як правило, вам краще використовувати прив'язки пітона, коли це можливо (кращий вилучення виключень, серед інших переваг.)

Для echoкоманди, очевидно, краще використовувати python для запису у файл, як це запропоновано у відповіді @ jordanm.

Для iptablesкоманди, може бути python-iptables( сторінка PyPi , GitHub сторінку з описом і док ) забезпечить то , що вам потрібно (я не перевіряв вашу конкретну команду).

Це зробить вас залежними від зовнішньої в'язки, тому вам доведеться зважити переваги. Використання підпроцесу працює, але якщо ви хочете використовувати вихід, вам доведеться самостійно проаналізувати його і вирішити зміни у вихідних iptablesверсіях у майбутніх версіях.


Ще одна річ, що слід зазначити, що код тестування блоку з subprocessдзвінками є менш корисним. Так, ви можете знущатися над дзвінками, але тести повинні робити припущення щодо результатів на зовнішніх дзвінках.
Йорданм

Ваша відповідь більше схожа на пораду. ОП спеціально запитав, як він може запустити системну команду linux з python.
капад

@kapad Так, але він також уточнив, чому він хоче це зробити, і я запропонував альтернативу.
Jérôme

2

Версія пітона вашої оболонки. Будьте обережні, я не перевіряв цього.

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

Якщо ви хочете виконати цю команду в якійсь іншій системі після SSH, можливо, вам доведеться використовувати модуль з іменем Paramiko. Це дійсно корисно.

Якщо виконання команд потрібно виконати з локальної машини, тоді функції модуля os будуть корисними.

Домашня сторінка: https://www.paramiko.org/

Розробка: https://github.com/paramiko/paramiko

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.