Выполнять команды оболочки в 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

Если я просто использую printPython и запускаю его в терминале, будет ли он выполнять то же самое, что и выполнение, как если бы вы печатали его самостоятельно и нажимали 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 необходимо указать shell = True, иначе команда call не будет работать. По умолчанию вызов будет пытаться открыть файл, указанный в строке, если не установлен shell = True. Также похоже, что в Python 3.5 вызов заменен на run
DLH

Общий код POSIX, вероятно, должен вызываться decode()с набором символов из LC_CTYPEпеременной среды.
Микко Ранталайнен

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

Как правило, лучше использовать привязки Python, когда это возможно (среди прочего, лучше ловить исключения).

Для echoкоманды, очевидно, лучше использовать python для записи в файл, как предложено в ответе @ jordanm.

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

Это заставит вас зависеть от внешней библиотеки, поэтому вам придется взвесить все преимущества. Использование подпроцесса работает, но если вы хотите использовать выходные данные, вам придется проанализировать их самостоятельно и заняться изменениями выходных данных в будущих iptablesверсиях.


Следует также отметить, что код модульного тестирования с subprocessвызовами менее полезен. Да, вы можете смоделировать вызовы, но тесты должны делать предположения о результатах внешних вызовов.
Иордания

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

@kapad Да, но он также уточнил, почему он хотел это сделать, и я предложил альтернативу.
Жером

2

Python-версия вашей оболочки. Будьте осторожны, я не проверял это.

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.