python调用shell
shell对于文本有比较好的处理功能,python可以直接调用结果,但是处理的速度比较慢
一、os模块
1)os.system 方法
原理:system函数可以将字符串转化成命令在服务器上运行;其原理是每一条system函数执行时,其会创建一个子进程在系统上执行命令行,子进程的执行结果无法影响主进程;但是几条命令同时执行的时候可能获取不到理想的结果
使用方法:
1、直接输入命令执行
>>> import os
>>> os.system('pwd')
/root
0
>>> os.system('pwd && ls')
/root
123 a.txt fsimage1.xml ssh.sh user_id.sh
1.txt bash-4.1.2-29.el6.x86_64.rpm install.log
2、传参执行
os.system("shell command argusFormat" % argus)传参
>>> a='abc'
>>> os.system('python a.py %s' %(a))
haha abc
0 #返回的执行状态值
返回值:os.system('command')的返回结果是脚本的退出状态码只有(0 成功),1,2
注意:os.system中不能使用管道符!!使用管道符号每次都不能执行成功
>>> os.system('echo 'abc' | passwd --stdin test')
File "<stdin>", line 1
os.system('echo 'abc' | passwd --stdin test')
^
SyntaxError: invalid syntax
2)os.popen()方法
原理:popen方法可以得到shell命令的返回值。os.popen(cmd)调用方式是通过管道的方式来实现,函数返回一个file-like的对象,里面的内容是脚本输出的内容(可简单理解为echo输出的内容)
使用方法:os.popen('command')
使用管道符号
>>> os.popen('echo "abc128!" |passwd --stdin test01 ').read()
'Changing password for user test01.\npasswd: all authentication tokens updated successfully.\n'
>>> os.popen('cat /root/user_id|grep 10.17.4 |wc -l').read()
'126\n'
传参数
>>> os.popen('python a.py %s'%(a)).readlines()
['haha abc\n']
os.popen(cmd)返回值是执行结果输出内容,要再调用read()或者readlines()这两个命令
os.popen()如果命令中有' ',就需要使用双引号将其包围起来
>>> getinfo=os.popen('cat %s |grep 'auth required pam_wheel.so use_uid root_only group=wheel''%path).read().strip('\n')
File "<stdin>", line 1
getinfo=os.popen('cat %s |grep 'auth required pam_wheel.so use_uid root_only group=wheel''%path).read().strip('\n')
^
SyntaxError: invalid syntax
>>> getinfo=os.popen("cat %s |grep 'auth required pam_wheel.so use_uid root_only group=wheel'"%path).read().strip('\n')
>>> print(getinfo)
Python中的commands模块专门用于调用Linux shell命令,并返回状态和结果,下面是commands模块的主要函数:
1. commands.getoutput('shell command')执行shell命令,返回结果(string类型)
1. commands.getoutput('shell command')执行shell命令,返回结果(string类型)
>>> commands.getoutput('cat /root/test1137/d.txt |grep John |wc -l')
'2'
脚本---统计文本中某匹配项出现次数
#!/use/bin/env python
import os
import sys
import commands
argvstr=sys.argv
def check(path,a,b):
txt=commands.getoutput('cat %s |grep %s |wc -l'%(path,a))
if eval(txt)==eval(argvstr[1]):
print("%s"%b)
path='/root/test1137/d.txt'
a='John'
b='success'
check(path,a,b)
结果:
[root@master01 ~]# python a.py 2
success
三、subprocess模块
使用subprocess模块能够创建新的进程。能够与新建进程的输入/输出/错误管道连通。并能够获得新建进程运行的返回状态。
使用subprocess模块的目的是替代os.system()、os.popen*()、commands.*等旧的函数或模块。
1、subprocess.call(["some_command","some_argument","another_argument_or_path"])
subprocess.call(command,shell=True)
使用方法:
>>> subprocess.call('ls -l',shell=True)
total 718144
-rw-r----- 1 root root 16 Oct 22 20:22 123
-rw-r--r-- 1 root root 0 Sep 29 20:30 1.txt
-rw-r--r-- 1 root root 183 Sep 27 19:03 a
-rw-r--r-- 1 root root 146 Oct 15 17:32 a1.sh
-rw-r--r-- 1 root root 146 Oct 15 18:46 a2.sh
subprocess.call(command)commands不能使用别名,ls -l 可以,但是ll不行
>>> abc=subprocess.call('ls -l',shell=True)##和shell中命令ls -a显示结果一样
>>> print(abc)
0#返回退出的信息
返回值:父进程等待子进程完成,返回退出信息(returncode,相当于Linux exit code)
2、subprocess.Popen(command,shell=True)
假设command不是一个可运行文件。shell=True不可省。
使用subprocess模块能够创建新的进程,能够与新建进程的输入/输出/错误管道连通。并能够获得新建进程运行的返回状态。使用subprocess模块的目的是替代os.system()、os.popen*()、commands.*等旧的函数或模块。
最简单的方法是使用classsubprocess.Popen(command,shell=True)。Popen类Popen.stdin,Popen.stdout,Popen.stderr三个实用的属性,能够实现与子进程的通信。
subprocess.Popen()
>>> import subprocess
>>> child = subprocess.Popen(['ping','-c','4','blog.linuxeye.com'])
>>> print 'parent process'
实际上,上面的几个函数都是基于Popen()的封装(wrapper)。这些封装的目的在于让我们容易使用子进程。当我们想要更个性化我们的需求的时候,就要转向Popen类,该类生成的对象用来代表子进程。
与上面的封装不同,Popen对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block),举例:
import subprocess
child = subprocess.Popen('ping -c4 blog.linuxeye.com',shell=True)
child.wait()
print 'parent process'
从运行结果中看到,父进程在开启子进程之后并等待child的完成后,再运行print。
此外,你还可以在父进程中对子进程进行其它操作,比如我们上面例子中的child对象:代码如下:
child.poll() # 检查子进程状态
child.kill() # 终止子进程
child.send_signal() # 向子进程发送信号
child.terminate() # 终止子进程
子进程的PID存储在child.pid
二、子进程的文本流控制
子进程的标准输入、标准输出和标准错误如下属性分别表示:
代码如下:
child.stdin
child.stdout
child.stderr
可以在Popen()建立子进程的时候改变标准输入、标准输出和标准错误,并可以利用subprocess.PIPE将多个子进程的输入和输出连接在一起,构成管道(pipe),如下2个例子:
import subprocess
child1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
print child1.stdout.read(),
#或者child1.communicate()
import subprocess
child1 = subprocess.Popen(["cat","/etc/passwd"], stdout=subprocess.PIPE)
out = child2.communicate()
subprocess.PIPE实际上为文本流提供一个缓存区。child1的stdout将文本输出到缓存区,随后child2的stdin从该PIPE中将文本读取走。child2的输出文本也被存放在PIPE中,直到communicate()方法从PIPE中读取出PIPE中的文本。
注意:communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成
subprocess.run():python3.5中新增的函数, 执行指定的命令, 等待命令执行完成后返回一个包含执行结果的CompletedProcess类的实例。
参考链接:https://www.cnblogs.com/pengpp/p/9833349.html