详谈python中subprocess shell=False与shell=True的区别

shell=True参数会让subprocess.call接受字符串类型的变量作为命令,并调用shell去执行这个字符串,当shell=False是,subprocess.call只接受数组变量作为命令,并将数组的第一个元素作为命令,剩下的全部作为该命令的参数。

举个例子来说明

from subprocess import call
import shlex
cmd = "cat test.txt; rm test.txt"
call(cmd, shell=True)

上述脚本中,shell=True的设置,最终效果是执行了两个命令

cat test.txt 和 rm test.txt

把shell=True 改为False,

from subprocess import call
import shlex
cmd = "cat test.txt; rm test.txt"
cmd = shlex(cmd)
call(cmd, shell=False)

则调用call的时候,只会执行cat的命令,且把 "test.txt;" "rm" "test.txt" 三个字符串当作cat的参数,所以并不是我们直观看到的好像有两个shell命令了。

也许你会说,shell=True 不是很好吗,执行两个命令就是我期望的呀。但其实,这种做法是不安全的,因为多个命令用分号隔开,万一检查不够仔细,执行了危险的命令比如 rm -rf / 这种那后果会非常严重,而使用shell=False就可以避免这种风险。

总体来说

看实际需要而定,官方的推荐是尽量不要设置shell=True。

补充: python subprocess模块的shell参数问题

昨天调试其他同学的代码时,发现对于subprocess模块所传的args变量,与shell变量存在关联,传值不当会有各种问题。比较有趣,就记录一下。

根据subprocess模块的args定义如下:

args is required for all calls and should be a string, or a sequence of program arguments. Providing a sequence of arguments is generally preferred, as it allows the module to take care of any required escaping and quoting of arguments (e.g. to permit spaces in file names). If passing a single string, either shell must be True (see below) or else the string must simply name the program to be executed without specifying any arguments.

对于args,可传string,也可传list,但当传string时,shell的值必须设为True。

当shell为True时

If shell is True, the specified command will be executed through the shell. This can be useful if you are using Python primarily for the enhanced control flow it offers over most system shells and still want convenient access to other shell features such as shell pipes, filename wildcards, environment variable expansion, and expansion of ~ to a user's home directory.

就是调用了系统的 sh 来执行命令(args的string),这样会导致一些猥琐的安全问题,类似于SQL Injection攻击:

from subprocess import call
filename = input("What file would you like to display?\n")
What file would you like to display?
non_existent; rm -rf / #
call("cat " + filename, shell=True) # Uh-oh. This will end badly...

所以,安心用shell=False吧,记得args传list。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • 通过实例解析python subprocess模块原理及用法

    一.subprocess以及常用的封装函数 运行python的时候,我们都是在创建并运行一个进程.像Linux进程那样,一个进程可以fork一个子进程,并让这个子进程exec另外一个程序.在Python中,我们通过标准库中的subprocess包来fork一个子进程,并运行一个外部的程序. subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所以我们可以根据需要来从中选取一个使用.另外subprocess还提供了一些管理标准流(standard stream)

  • 解决python subprocess参数shell=True踩到的坑

    0x01 问题现象 写的程序使用subprocess创建子进程运行其他程序,判断其他程序运行完后进行处理. 在subprocess使用了shell=True,判断用户程序退出的代码如下 while self.proc.poll() is None: do_something 判断子进程是否运行结束,程序在子进程运行结束后,代码未向下继续运行,而是卡在了这个循环中. 0x02 原因分析 百度后对shell参数的解释如下: shell=True参数会让subprocess.Popen接受字符串类型的

  • 使用python执行shell脚本 并动态传参 及subprocess的使用详解

    最近工作需求中 有遇到这个情况 在web端获取配置文件内容 及 往shell 脚本中动态传入参数 执行shell脚本这个有多种方法 最后还是选择了subprocess这个python标准库 subprocess这个模块可以非常方便的启动一个子进程,并且控制其输入和输出 Class Popen(args,bufsize = 0,executable=None, stdin =None,stdout =None,stderr =None, preexec_fn = None,close_fds =

  • Python中判断subprocess调起的shell命令是否结束

    前言 最近在使用subprocess遇到个问题,折腾了好半天才找到简单的解决办法,在这里记录下. 环境 Python:2.7.10 库:subprocess, logging 问题 使用subprocess的Popen类来执行shell命令,要怎么样才能知道命令执行结束了,以此来执行回调方法. 解决办法 使用subprocess.Popen.poll方法来获取命令的执行情况. poll方法的返回值有两种情况    1. 当命令未运行结束的时候,返回None    2. 当命令结束时,返回命令的返

  • python subprocess pipe 实时输出日志的操作

    * test11.py import time print "1" time.sleep(2) print "1" time.sleep(2) print "1" time.sleep(2) print "1" * test.py import subprocess p = subprocess.Popen("python test11.py", shell=True, stdout=subprocess.

  • python3通过subprocess模块调用脚本并和脚本交互的操作

    因工作需要,需实现如题所示功能.查阅网上博客,资料,大多都是针对python2的,而且很多地方不明所以,所以自己整理了一下查阅的结果,重新写一篇博客. 预备知识 1.python3的默认字符串类型 Python 2.x 同时支持ASCII和 Unicode字符串,默认情况下是ASCII编码.而 Python 3中这种支持刚好调换:Unicode现在变成了默认类型,而 ASCII 字符串现在称为 bytes. bytes 数据结构包含字节值,并且它 不应该再被视为一个字符串,因为它是一个包含数据的

  • python中的subprocess.Popen()使用详解

    从python2.4版本开始,可以用subprocess这个模块来产生子进程,并连接到子进程的标准输入/输出/错误中去,还可以得到子进程的返回值. subprocess意在替代其他几个老的模块或者函数,比如:os.system os.spawn* os.popen* popen2.* commands.* 一.subprocess.Popen subprocess模块定义了一个类: Popen class subprocess.Popen( args, bufsize=0, executable

  • 详谈python中subprocess shell=False与shell=True的区别

    shell=True参数会让subprocess.call接受字符串类型的变量作为命令,并调用shell去执行这个字符串,当shell=False是,subprocess.call只接受数组变量作为命令,并将数组的第一个元素作为命令,剩下的全部作为该命令的参数. 举个例子来说明 from subprocess import call import shlex cmd = "cat test.txt; rm test.txt" call(cmd, shell=True) 上述脚本中,sh

  • 在python 中实现运行多条shell命令

    使用py时可能需要连续运行多条shell 命令 1. # coding: UTF-8 import sys reload(sys) sys.setdefaultencoding('utf8') import subprocess import os import commands #os.system('cmd1 && cmd2') cmd1 = "cd ../" cmd2 = "ls" cmd = cmd1 + " &&

  • python中subprocess批量执行linux命令

    可以执行shell命令的相关模块和函数有: os.system os.spawn os.popen --废弃 popen --废弃 commands --废弃,3.x中被移除 以上执行shell命令的相关的模块和函数的功能均在 subprocess 模块中实现,并提供了更丰富的功能. subprocess call 执行命令,返回状态码 >>> import subprocess >>> ret = subprocess.call(["ls", &q

  • python中subprocess实例用法及知识点详解

    1.subprocess这个模块来产生子进程,并且可以连接到子进程的标准输入.输出.错误中,还可以获得子进程的返回值. 2.subprocess提供了2种方法调用子程序. 实例 # coding:utf-8 import os # popen返回文件对象,同open操作一样 f = os.popen(r"ls", "r") l = f.read() print(l) f.close() Python subprocess知识点扩充 使用subprocess模块的目的

  • Python中subprocess模块用法实例详解

    本文实例讲述了Python中subprocess模块用法.分享给大家供大家参考.具体如下: 执行命令: >>> subprocess.call(["ls", "-l"]) 0 >>> subprocess.call("exit 1", shell=True) 1 测试调用系统中cmd命令,显示命令执行的结果: x=subprocess.check_output(["echo", "

  • 一文搞懂Python中subprocess模块的使用

    目录 简介 常用方法和接口 subprocess.run()解析 subprocess.Popen()解析 Popen 对象方法 subprocess.run()案例 subprocess.call()案例 subprocess.check_call()案例 subprocess.getstatusoutput()案例 subprocess.getoutput()案例 subprocess.check_output()案例 subprocess.Popen()综合案例 简介 subprocess

  • 详谈Python中列表list,元祖tuple和numpy中的array区别

    1.列表 list是处理一组有序项目的数据结构,即你可以在一个列表中存储一个序列的项目.列表中的项目.列表中的项目应该包括在方括号中,这样python就知道你是在指明一个列表.一旦你创建了一个列表,你就可以添加,删除,或者是搜索列表中的项目.由于你可以增加或删除项目,我们说列表是可变的数据类型,即这种类型是可以被改变的,并且列表是可以嵌套的. 列表是可以改变的,能够增加或减少,(append和del函数) 2.元组 元祖和列表十分相似,不过元组是不可变的.即你不能修改元组.元组通过圆括号中用逗号

  • 详谈python中冒号与逗号的区别

    注意if\while\for等(或函数定义)语句在结尾处包含一个冒号--我们通过它告诉python下面跟着一个语句块. --------------冒号的用法 if guess == number: print 'Congratulations, you guessed it.' # New block starts here print "(but you do not win any prizes!)" # New block ends here elif guess < c

  • python中urllib.request和requests的使用及区别详解

    urllib.request 我们都知道,urlopen()方法能发起最基本对的请求发起,但仅仅这些在我们的实际应用中一般都是不够的,可能我们需要加入headers之类的参数,那需要用功能更为强大的Request类来构建了 在不需要任何其他参数配置的时候,可直接通过urlopen()方法来发起一个简单的web请求 发起一个简单的请求 import urllib.request url='https://www.douban.com' webPage=urllib.request.urlopen(

  • Python中的None与 NULL(即空字符)的区别详解

    1.首先要了解Python的对象的概念: Python中,万物皆对象,所有的操作都是针对对象的,那什么是对象,5是一个int对象,'oblong'是一个str对象,异常也是一个对象,抽象一点是,人,猫,够也是一个对象 那对于一个对象,它就有包括两方面的特征:  属性:去描述它的特征  方法: 它所具有的行为 所以,对象=属性+方法 (其实方法也是一种属性,一种区别于数据属性的可调用属性 把具有相同属性和方法的对象就可以归为一类,即Classl.类就好比是一张蓝图,使用一个类可以创建多个对象实例

随机推荐