Python Linux系统管理之Python中执行外部命令

一、简介

有很多需求需要在Python中执行shell命令、启动子进程,并捕获命令的输出和退出状态码,类似于Java中的Runtime类库。本文将介绍subprocess模块的定位,然后介绍subprocess模块提供的便利函数,最后介绍Popen这个类的使用方法。

二、subprocess模块的使用

1、call

call函数的定义如下:

subprocess.call(args,*,stdin=None,stout=None,stderr=None,shell=False)

call函数将允许由args参数制定的命令直到命令结束。call函数的返回值是命令的退出状态码,工程师可以通过退出状态码判断命令是否执行成功。如下所示:

In [1]: import subprocess
In [2]: subprocess.call([‘ls’,’-l’])
total 8
-rw-r–r–. 1 root root 0 Sep 24 10:52 1.txt

 

-rw-r–r–. 1 root root 0 Sep 24 10:52 2.txt

-rw-r–r–. 1 root root 3736 Sep 24 10:51 demo.tar.gz

-rw-r–r–. 1 root root 929 Sep 24 10:52 demo.zip

Out[2]: 0

In [3]: subprocess.call(“exit 1”,shell = True)

Out[3]: 1

注:如果设置shell=True,Python会先运行一个shell,再用shell解释字符串,而不是传递一个列表。

2、check_call

check_all与call类似,只是遇到异常情况返回的形式不同。如果命令执行成功,下面会返回0;如果命令执行失败,它会抛出subprocess.CalledProcessError异常,相关案例如下所示:

In [5]: subprocess.check_call([“ls”,”-l”])
total 8
-rw-r–r–. 1 root root 0 Sep 24 10:52 1.txt
-rw-r–r–. 1 root root 0 Sep 24 10:52 2.txt

 

-rw-r–r–. 1 root root 3736 Sep 24 10:51 demo.tar.gz

-rw-r–r–. 1 root root 929 Sep 24 10:52 demo.zip

Out[5]: 0

In [6]: subprocess.check_call(“exit 1”,shell = True)

—————————————————————————

CalledProcessError Traceback (most recent call last)

<ipython-input-6-f13e6678cc55> in <module>()

—-> 1 subprocess.check_call(“exit 1”,shell = True)

/usr/local/lib/python3.7/subprocess.py in check_call(*popenargs, **kwargs)

326 if cmd is None:

327 cmd = popenargs[0]

–> 328 raise CalledProcessError(retcode, cmd)

329 return 0

330

CalledProcessError: Command ‘exit 1’ returned non-zero exit status 1.

3、check_output

从上面的输出结果可以看到,call和check_call函数直接将命令的输出结果输出到命令行终端,这种返回结果的形式很有可能是你不想要的。在实际工作过程中,一般会对获取命令的结果进行进一步处理,或者将命令的输出打印到日志文件中。如下所示:

In [1]: import subprocess
In [2]: output = subprocess.check_output([‘df’,’-h’])
In [3]: print(output)
b’Filesystem Size Used Avail Use{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} Mounted on\n/dev/mapper/centos-root 50G 1.7G 49G 4{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /\ndevtmpfs 1.9G 0 1.9G 0{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /dev\ntmpfs 1.9G 0 1.9G 0{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /dev/shm\ntmpfs 1.9G 12M 1.9G 1{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /run\ntmpfs 1.9G 0 1.9G 0{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /sys/fs/cgroup\n/dev/mapper/centos-home 106G 246M 105G 1{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /home\n/dev/sda1 1014M 184M 831M 19{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /boot\ntmpfs 378M 0 378M 0{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /run/user/0\n’

 

In [4]: lines = output.split(b’\n’)

In [5]: lines

Out[5]:

[b’Filesystem Size Used Avail Use{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} Mounted on’,

b’/dev/mapper/centos-root 50G 1.7G 49G 4{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /’,

b’devtmpfs 1.9G 0 1.9G 0{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /dev’,

b’tmpfs 1.9G 0 1.9G 0{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /dev/shm’,

b’tmpfs 1.9G 12M 1.9G 1{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /run’,

b’tmpfs 1.9G 0 1.9G 0{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /sys/fs/cgroup’,

b’/dev/mapper/centos-home 106G 246M 105G 1{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /home’,

b’/dev/sda1 1014M 184M 831M 19{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /boot’,

b’tmpfs 378M 0 378M 0{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b} /run/user/0′,

b”]

In [6]: for line in lines[1:-1]:

…: if line:

…: print(line.split()[-2])

…:

b’4{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b}’

b’0{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b}’

b’0{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b}’

b’1{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b}’

b’0{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b}’

b’1{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b}’

b’19{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b}’

b’0{815ac408a99669c280d890a3c1592527154068adde55fb55fc5b84dc9fd9f61b}’

 

 

 

 

如果想要捕捉退出状态码,可以通过抛出的subprocess.CalledProcessError异常。

import subprocess
try:
output = subprocess.check_output(‘cmd’,’arg1′ ,’arg2′)
except subprocess.CalledProcessError as e:

 

output = e.output

code = e.returncode

默认情况下,check_output命令只会捕捉命令的标准输出。如果想捕捉命令的错误输出,需要将错误输出重定向到标准输出。如下所示:

output = subprocess.check_output([‘cmd’,’arg1′ ,’arg2′],stderr= subprocess.STDOUT)
posted @ 2020-08-11 14:37  星火撩原  阅读(287)  评论(0编辑  收藏  举报