30

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

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzAxMzE4MDI0NQ%3D%3D&%3Bmid=2650336764&%3Bidx=1&%3Bsn=2f15bd7756b7ee6df4ec0bfbebe9e40d
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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运维,社招,应届生都可以,有意向可后台回复关键词:微信群 ,然后加我微信交流。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK