在Python中执行Shell命令


65

我目前正在研究渗透测试和Python编程。我只想知道如何在Python中执行Linux命令。我要执行的命令是:

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可以做到这一点。
愚蠢的人,2015年

2
我以为bash是个shell肿的贝壳...
mikeserv

3
os.system推荐使用该subprocess模块的文档。
jordanm 2015年

您需要iptables的输出吗?
基拉2015年

3
该问题应迁移到Stackoverflow。
www139

Answers:


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)

或者,不调用shell:

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

强烈建议在中设置timeoutin communicate,并且还应捕获调用它时可能获得的异常。这是一个非常容易出错的代码,因此您应该期望会发生错误并相应地进行处理。

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


23
从2.6版开始不推荐使用os.system。子流程是正确使用的模块。
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环境变量中的charset进行调用。
Mikko Rantalainen

29

第一个命令只是简单地写入文件。您不会将其作为shell命令执行,因为python无需借助shell就可以读写文件:

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

iptables您可能想在外部执行该命令。最好的方法是使用subprocess模块

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命令,按照@jordanm的答案中的建议,使用python写入文件显然更好。

对于iptables命令,也许python-iptablesPyPi页面带有说明和doc的GitHub页面)将提供您所需的内容(我没有检查您的特定命令)。

这将使您依赖于外部库,因此您必须权衡收益。使用子流程是可行的,但是如果要使用输出,则必须自己解析它,并处理将来iptables版本中的输出更改。


需要注意的另一件事是,带有subprocess调用的单元测试代码不太有用。是的,您可以模拟调用,但是测试必须对外部调用的结果进行假设。
jordanm 2015年

您的答案更像是建议。OP特别询问了他如何从python运行linux系统命令。
kapad

@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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.