正确的使用python调用shell的姿势

python是一门简洁灵活的语言,也是一门胶水语言,能与很多其他的编程语言进行交互,虽然性能差一点,但易用,入门和上手都比较简单,所以一直以来都被使用广泛。
python天生的优势,用它来开发一些devops的自动化作业是非常方便的,当然在linux上,一般我们用shell就能写一些简单的自动化脚本,但如果自动化作业复杂的话,使用shell脚本就很难搞定了,一方面shell脚本量变大就会比较难以工程化,维护和阅读,另外一个重要的原因是shell不具备正经编程语言所具备的丰富的一些类库,比如说map类型必须得bash版本4.x以上才有,或者有序list什么的也没有,这个时候我们就可以用python来搞定了,python能与shell直接交互,所以两者结合,相互取长补短,就非常适合开发各种自动化作业了。
下面我们看如何使用python与shell交互:
方式一:
使用os.system方法
保存到一个python文件xxx.py里面执行 python xxx.py,或者直接在linux终端上执行
这种方式是最原始的方式,能直接调用shell命令,但是没法获取输出结果,所以仅仅适合一些简单的场景
方式二:
使用os.popen方法
输出123
我们可以看到popen方法可以获取命令执行后到输入结果,但这还是有缺陷的,我们知道在linux里面,有标准的0,1,2来代表标准输入,输出和错误,现在只有stdout没有其他的两个变量还是有限制的,如果仔细看python的方法,会发现popen还有popen2,popen3,popen4同名方法,没错就是后面的版本里面完善了linux的标准输入,输出,错误等信息。
具体点:popen 支持 stdout
popen2 支持stdin, stdout
popen3 支持stdin, stdout, stderr
popen4 支持stdin, stdout and stderr
方式三:看到上面这些这么繁琐的调用,后面就又有了最强大的subprocess模块,subprocess模块的出现是用来替代OS模块中的system()和popen()方法的,官方推荐的是只用subprocess模块来执行系统命令,subprocess 模块允许我们启动一个新进程,并连接到它们的输入/输出/错误管道,从而获取返回值。
Popen 是 subprocess的核心,子进程的创建和管理都靠它处理。

参数介绍如下:args:shell命令,可以是字符串或者序列类型(如:list,元组)
bufsize:缓冲区大小。当创建标准流的管道对象时使用,默认-1。0:不使用缓冲区
1:表示行缓冲,仅当universal newlines=True时可用,也就是文本模式
正数:表示缓冲区大小
负数:表示使用系统默认的缓冲区大小。stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
preexec

fn:只在 Unix 平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令。cwd:用于设置子进程的当前目录。env:用于指定子进程的环境变量。如果 env = None,子进程的环境变量将从父进程中继承。
一个简单的例子:
几个主要方法,介绍:
poll(): 检查进程是否终止,如果终止返回 returncode,否则返回 None。wait(timeout): 等待子进程终止。communicate(input,timeout): 和子进程交互,发送和读取数据。send_signal(singnal): 发送信号到子进程 。terminate(): 停止子进程,也就是发送SIGTERM信号到子进程。kill(): 杀死子进程。发送 SIGKILL 信号到子进程。
这里我已经封装好了2个通用方法,一个是执行命令能够实时获取终端输出的信息,一个是可以执行命令结束后得到结果。
可以实时获取输出的:
为了能够模拟效果,我写了一个简单的shell脚本:test.sh
这个脚本每输出一个数字都会sleep 2秒,用ptyhon调用这个脚本,能够实时在终端上看到和shell一样的效果:
非实时获取输出的,这个脚本适合大部分场景:
ok,同样的调用脚本,这个函数会等整个shell执行结束后,输出结果:
至此,我们已经介绍完了如何使用python和shell交互的方式,通过这种方式我们可以很轻松开发一个自动化作业,比如系统参数初始化,使用yum安装各种软件,各种业务项目的部署,启动,停止等等等等,有很多场景都可以发挥。
内推招聘:
阿里巴巴-阿里云-计算平台事业部,招大数据开发,SRE运维,社招,应届生都可以,有意向可后台回复关键词:微信群 ,然后加我微信交流。