从零开始的Linux运维屌丝之路,资源免费分享平台   运维人员首选:简单、易用、高效、安全、稳定、社区活跃的开源软件

39、 subprocess模块 os执行命令

发布:蔺要红05-27分类: Python


命令执行的状态码   --表示命令执行是否成功
命令执行的输出结果 --命令执行成功后的输出

 
              函数名 描述
  os.system(command)   返回命令执行状态码,而将命令执行结果输出到屏幕
  os.popen(command).read()   可以获取命令执行结果,但是无法获取命令执行状态码
  commands.getstatusoutput(command)   返回一个元祖(命令执行状态码,命令执行结果)
 

说明:

  1. os.popen(command)函数得到的是一个文件对象,因此除了read()方法外还支持write()等方法,具体要根据command来定;
  2. commands模块只存在于Python 2.7中,且不支持windows平台,因此commands模块很少被使用。另外,commands模块实际上也是通过对os.popen()的封装来完成的
 
subprocess.run 执行简单的命令

>>> import subprocess 
>>> subprocess.run(["df","-h"])  #执行简单的命令
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G  2.5G   35G   7% /
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           1.9G  356K  1.9G   1% /run
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
tmpfs           380M     0  380M   0% /run/user/0
CompletedProcess(args=['df', '-h'], returncode=0)
>>> a = subprocess.run(["df","-h"])  #赋值  获取状态和执行的命令
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G  2.5G   35G   7% /
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           1.9G  328K  1.9G   1% /run
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
tmpfs           380M     0  380M   0% /run/user/0
>>> a
CompletedProcess(args=['df', '-h'], returncode=0)
>>> a.returncode  #获取结果
0
>>> a.args #获取命令
['df', '-h']
>>> a.stdout #结果  拿不到
>>> a.stderr #错误  拿不到

#需要加入下文的参数tderr=subprocess.PIPE,stdout=subprocess.PIPE
 stderr=subprocess.PIPE,stdout=subprocess.PIPE  或者结果和执行的命令
>>> a = subprocess.run(['df','-h'],stderr=subprocess.PIPE,stdout=subprocess.PIPE)
>>> a.stdout  #执行结果
b'Filesystem      Size  Used Avail Use% Mounted on\n/dev/vda1        40G  2.5G   35G   7% /\ndevtmpfs        1.9G     0  1.9G   0% /dev\ntmpfs           1.9G     0  1.9G   0% /dev/shm\ntmpfs           1.9G  328K  1.9G   1% /run\ntmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup\ntmpfs           380M     0  380M   0% /run/user/0\n'
>>> a.stderr
b''    #错误为空
当命令错误的时候,不加check=True的时候、不返回错误,可以通过stderr得到错误结果
>>> a = subprocess.run(['df','aaa-h'],stderr=subprocess.PIPE,stdout=subprocess.PIPE)
>>> a.stdout  #输出结果为空
b''
>>> a.stderr  #拿到错误结果
b'df: \xe2\x80\x98aaa-h\xe2\x80\x99: No such file or directory\n'
当命令错误的时候,加check=True的时候、会立即返回错误
>>> a = subprocess.run(['df','aaa-h'],stderr=subprocess.PIPE,stdout=subprocess.PIPE,check=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/python3/lib/python3.5/subprocess.py", line 708, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['df', 'aaa-h']' returned non-zero exit status 1
 
>>> a.stdout
b''
>>> a.stderr
b'df: \xe2\x80\x98aaa-h\xe2\x80\x99: No such file or directory\n'
 subprocess.run 执行带管道的命令
>>> subprocess.run('df -h|grep dev',shell=True)  #最后一行会显示args和returncode
/dev/vda1        40G  2.4G   35G   7% /
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           1.9G     0  1.9G   0% /dev/shm
CompletedProcess(args='df -h|grep dev', returncode=0)
>>> subprocess.run('df -h|grep dev',shell=True).stdout #只显示结果
/dev/vda1        40G  2.4G   35G   7% /
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           1.9G     0  1.9G   0% /dev/shm

>>> subprocess.run('df -h|grep dev',shell=True).returncode  #returncode
/dev/vda1        40G  2.4G   35G   7% /
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           1.9G     0  1.9G   0% /dev/shm
0
>>> subprocess.run('df -h|grep dev',shell=True).args       #args
/dev/vda1        40G  2.4G   35G   7% /
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           1.9G     0  1.9G   0% /dev/shm
'df -h|grep dev'

其他用法

>>> subprocess.call(["df","-h"]) #执行命令,返回命令执行状态,0或者非0
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G  2.4G   35G   7% /
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           1.9G  328K  1.9G   1% /run
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
tmpfs           380M     0  380M   0% /run/user/0
0

>>> subprocess.check_call(["df","-h"]) #执行命令,如果命令结果为0,就正常返回,否则显示异常
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G  2.4G   35G   7% /
devtmpfs        1.9G     0  1.9G   0% /dev
tmpfs           1.9G     0  1.9G   0% /dev/shm
tmpfs           1.9G  328K  1.9G   1% /run
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
tmpfs           380M     0  380M   0% /run/user/0
0

>>> subprocess.getstatusoutput('df -h') #接收字符串格式命令,不用加[],返回元祖形式,第一个元素为执行状态,第二个是命令结果
(0, 'Filesystem      Size  Used Avail Use% Mounted on\n/dev/vda1        40G  2.4G   35G   7% /\ndevtmpfs        1.9G     0  1.9G   0% /dev\ntmpfs           1.9G     0  1.9G   0% /dev/shm\ntmpfs           1.9G  328K  1.9G   1% /run\ntmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup\ntmpfs           380M     0  380M   0% /run/user/0')

>>> subprocess.getoutput('df -h') #接收字符串格式命令,不用加[],直接返回结果
'Filesystem      Size  Used Avail Use% Mounted on\n/dev/vda1        40G  2.4G   35G   7% /\ndevtmpfs        1.9G     0  1.9G   0% /dev\ntmpfs           1.9G     0  1.9G   0% /dev/shm\ntmpfs           1.9G  328K  1.9G   1% /run\ntmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup\ntmpfs           380M     0  380M   0% /run/user/0'

>>> res = subprocess.check_output(['df','-h']) #执行命令,返回结果,错误则直接报错
>>> res
b'Filesystem      Size  Used Avail Use% Mounted on\n/dev/vda1        40G  2.5G   35G   7% /\ndevtmpfs        1.9G     0  1.9G   0% /dev\ntmpfs           1.9G     0  1.9G   0% /dev/shm\ntmpfs           1.9G  328K  1.9G   1% /run\ntmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup\ntmpfs           380M     0  380M   0% /run/user/0\n'
  
subprocess.Popen

先看run和Popen的区别:Popen会是一个单独的进程
 
#5秒执行完成
>>> a = subprocess.run('sleep 5',shell=True,stdout=subprocess.PIPE)
..1
..2
..3
..4
..5
..END结束
#也是5秒内执行完成
>>> a = subprocess.Popen('sleep 5',shell=True,stdout=subprocess.PIPE)
...不需要等待5秒
>>> a.poll()  #查看是否执行完成
>>> a.poll()
>>> a.poll()
>>> a.poll() #返回0、执行完成
0
>>> a.poll()
0

#wait

>>> a = subprocess.Popen('echo $PWD;sleep 10',shell=True,cwd="/tmp",stdout=subprocess.PIPE)
>>> a.wait()
..
..
程序会一直等待执行完毕






图解


 



图片实验:
>>> a = subprocess.Popen('for i in $(seq 1 100);do sleep 1 ;echo $i >>sleep.log;done',shell=True,stdout=subprocess.PIPE)  #执行一个for循环、
>>> a.pid  #执行的pid为24729
24895
[root@zabbix ~]# ps -ef|grep echo  #打开另外一个窗口测试
root     24895 24505  0 17:37 pts/0    00:00:00 /bin/sh -c for i in $(seq 1 100);do sleep 1 ;echo $i >>sleep.log;done
root     24904 24834  0 17:37 pts/1    00:00:00 grep --color echo

#当执行
>>> a.terminate()
[root@zabbix ~]# ps -ef|grep echo
root     22899 22263  0 22:50 pts/1    00:00:00 grep --color echo
#经过试验
>>> a.kill()
也会终止
扩展杀死进程
>>> a = subprocess.Popen('for i in $(seq 1 100);do sleep 1 ;echo $i >>sleep.log;done',shell=True,stdout=subprocess.PIPE)
>>> a.pid
23148
>>> import os
>>> import signal
>>> os.kill(23148,signal.SIGTERM)
>>> a.poll()
-15


>>> a = subprocess.Popen('for i in $(seq 1 100);do sleep 1 ;echo $i >>sleep.log;done',shell=True,stdout=subprocess.PIPE)
>>> a.pid
23213
>>> a.poll()
>>> import signal
>>> a.send_signal(signal.SIGKILL) #给进程发信号
>>> a.poll()
-9
 
args:                      shell命令,可以是字符串或者序列类型(如:list,元祖)
stdin,stdout,stderr:    分别表示程序的标准输入、输出,错误句柄
preexec_fn:               用于执行一个可执行的对象,在程序运行前被调用
shell:                    同上
cwd:                     用于设置子进程的当前目录
evn:                     用于指定子进程的环境变量,如果env=None、子进程的环境变量从父进程中继承

preexec_fn
 
#run
>>> def sayhi():
...    print("run...sayhai")
... 
>>> a = subprocess.run('echo $PWD',shell=True,stdout=subprocess.PIPE,preexec_fn=sayhi)
>>> a.stderr
>>> a.stdout  #先执行了函数、又执行了echo $PWD命令
b'run...sayhai\n/root\n'
>>> a.returncode  #返回执行的状态
0
>>> a.args
'echo $PWD'

#Popen
>>> a = subprocess.Popen('echo $PWD',shell=True,stdout=subprocess.PIPE,preexec_fn=sayhi)
>>> a.stdout.read()
b'run...sayhai\n/root\n'
>>> a.args #返回执行的命令
'echo $PWD'
>>> a.returncode  #不会返回执行状态


cwd
 
>>> a = subprocess.run('echo $PWD',shell=True,cwd="/tmp",stdout=subprocess.PIPE)
>>> a.stdout     #设置了cwd为 /tmp  所有执行显示当前路径的时候为 /tmp
b'/tmp\n'
>>> a = subprocess.Popen('echo $PWD',shell=True,cwd="/tmp",stdout=subprocess.PIPE)
>>> a.stdout.read()
b'/tmp\n'  #设置了cwd为 /tmp  所有执行显示当前路径的时候为 /tmp

>>> a = subprocess.Popen('echo $PWD',shell=True,stdout=subprocess.PIPE)
>>> a.stdout.read()  #当不设置cwd的时候显示为当前路径 root下
b'/root\n' 

如果执行多个命令可以用 ; 和Linux连续执行命令一样
 
[root@zabbix ~]# echo $PWD;echo haha
/root
haha

#python下

>>> a = subprocess.Popen('echo $PWD;echo haha',shell=True,cwd="/tmp",stdout=subprocess.PIPE)
>>> a.stdout.read()
b'/tmp\nhaha\n'



 
温馨提示如有转载或引用以上内容之必要,敬请将本文链接作为出处标注,如有侵权我会在24小时之内删除!

欢迎使用手机扫描访问本站