目录
参考
python3 subprocess.check_output的使用
安全开发 | Python Subprocess库在使用中可能存在的安全风险总结
概要
这几天在做一个发布系统,里面进行前端Node发布的时候,需要执行npm install以及npm run build命令,这两个命令执行的时间很长,尤其是npm run build,经常需要超过4、5分钟,一开始我是使用最简单的os.system命令的话,前期没什么大问题,后期随着前端加载的包越来越多,发布系统经常性的会造成莫名的堵塞,卡死在npm run build之间,npm会一直处于epoll_pwait状态,原因是因为超时导致的,所以用了好几种方案来进行超时的控制
建议先了解一下Python执行命令的相关:【命令】Python中的执行命令【原创】
方案
方案一:os.system
os.system用来执行cmd指令,在cmd输出的内容会直接在控制台输出,返回结果为0表示执行成功
system()函数在执行过程中进行了以下三步操作:
- fork一个子进程
- 在子进程中调用exec函数去执行命令
- 在父进程调用wait(阻塞)去等待子进程结束
对于fork失败,system函数会返回-1
注意: 由于使用该函数经常会莫名其妙地出现错误,但是直接执行命令并没有问题,所以一般建议不要使用。
注意:os.system是简单粗暴的执行cmd指令,如果想获取在cmd输出的内容,是没办法获到的
注意:在Unix,Windows都有效
优点:简单易理解,能够返回执行命令的成功失败,返回0是成功,非0是失败
缺点:会造成堵塞,无法设置超时,不能输出控制台的结果
代码如下:
import os
def run_cmd(cmd_string):
print("命令为:" + cmd_string)
return os.system(cmd_string)
方案二:os.popen
同样是用来执行cmd指令,如果想获取控制台输出的内容,那就用os.popen的方法了,popen返回的是一个file对象,跟open打开文件一样操作了,r是以读的方式打开
popen() 创建一个管道,通过fork一个子进程,然后该子进程执行命令。返回值在标准IO流中,该管道用于父子进程间通信。父进程要么从管道读信息,要么向管道写信息,至于是读还是写取决于父进程调用popen时传递的参数(w或r)
注意:能获取到命令的执行内容,可以打印出来,但是获取不到命令是否执行成功,只是单纯输出了命令的执行结果而已
注意:os.popen() 方法用于从一个命令打开一个管道。在Unix,Windows中有效
优点:简单易理解,能够输出控制台的结果
缺点:无法获取命令是否执行成功,不清楚是否能够设置超时
代码如下:
import os
def run_cmd(cmd_string):
print("命令为:" + cmd_string)
p = os.popen(cmd_string)
x = p.read()
p.close()
return x
方案三:subprocess.check_output
subprocess模块是在2.4版本中新增的,官方文档中描述为可以用来替换以下函数:os.system、os.spawn、os.popen、popen2
参数既可以是string字符串,也可以是list列表
比如:
subprocess.Popen([“cat”,”test.txt”])
subprocess.Popen(“cat test.txt”, shell=True)
对于参数是字符串,需要指定shell=True,官方建议使用list列表