理解subprocess模块接口的shell参数

Last Updated: 2023-10-04 07:31:41 Wednesday

-- TOC --

常常用subprocess模块在Python中创建子进程,但关于shell参数的理解和使用,一直都错了!不管是使用阻塞同步的subprocess.run接口,还是异步非阻塞的subprocess.Popen接口,都有shell这个参数。这个参数到底是什么意思?

shell=True

shell=True的时候,cmd参数就应该是一个完整的命令字符串,Python的subprocess模块会先用/bin/sh创建一个shell子进程,然后在此子进程中,再执行cmd命令字符串所代表的命令。此时,cmd命令字符串可以包含shell特有的符号,比如重定向和管道符号。

好处:

  1. cmd命令字符串可以比较复杂,可以在此充分利用shell本身的特性,比如多命令,管道,重定向,shell的各种扩展,function和alias等等;
  2. 程序编写简单,cmd是一个完整的命令字符串,一目了然。

坏处:

  1. 多开了一个shell进程,在shell中执行命令又会继续创建命令进程,资源消耗大了一点点;
  2. 潜在的shell injection攻击!因为cmd是一个字符串,当此字符串有一部分来自用户的输入时,要特别小心。(injection攻击都是来自用户的刻意和恶意的输入)

可以用执行exec命令的方式,直接在shell进程中替换执行命令,来规避坏处(1),但应该也会有一点overhead;而要规避坏处(2),就要仔细检查用户的输入了!

shell=False

shell=False的时候,这是shell参数的默认值,cmd参数就不再是一个完整的命令字符串,而是一个tuple或list,命令和其参数被按空格拆分开来。

好处:

  1. 不会创建shell进程,subprocess直接创建命令进程;
  2. 当存在用户输入时,不容易出现shell injection攻击,相对安全。

坏处:

  1. shell本身的特性就不能用了,比如重定向等,但Python有提供相同功能的一组模块;
  2. 可能程序的编写会稍微复杂一点。

现在搞懂了!^___^

当然了,用非shell的方式启动bash,也是可以的。

subprocess官网介绍:https://docs.python.org/3/library/subprocess.html

find命令的-exec或者xargs命令,都是以非shell的方式直接启动命令进程。

本文链接:https://cs.pynote.net/sf/python/202112082/

-- EOF --

-- MORE --