Python脚本实战汇总&最佳实践
前言:
总体上来说shell能够实现的功能python也能实现,反之亦然,但遗憾的是,很多的项目处于内网的环境,连基本的vim都没有,更不用提安装python编译环境与安装第三方库,和集成好的IDE,当然,如果你能够忍受调试环境的麻烦的话,python也是不错的选择,虽然有这些因素带来的不便,但python脚本自然有它较shell更优秀的地方,比如在数据处理上,图形处理上,能够方便的将需要处理的数据生成表格与图片,再比如在数据库的连接上,直接就有现成的函数可以使用,本篇博客将会长期更新,以记录在日常运维工作中对两种脚本语言不同应用场景的适应性纪实与小技巧。
总体原则,如果shell脚本大于100行的话,在情况允许(方便连接外网)的情况下,建议用python对脚本进行重写。这是谷歌技术社区给出的建议:
If you find you need to use arrays for anything more than assignment of ${PIPESTATUS}, you should use Python.
- If you are writing a script that is more than 100 lines long, you should probably be writing it in Python instead. Bear in mind that scripts grow. Rewrite your script in another language early to avoid a time-consuming rewrite at a later date.
------------------------------------------------分割线----------------------------------------------------------------------
虽然有上述安利python脚本的点,但以博主在日常工作中对python和shell的使用感受来说,python在系统运维,服务器管理方面,远不如shell好用,理由如下:
- python没有管道,在python中使用管道,每次使用管道都需要import,open,read,close。py3管道subprocess.Popen有各种坑,py为了解决这些坑,py有参数10多个,每个参数n个选项。导致在py中使用管道,变得很复杂。用起来很麻烦。啥时候用true,啥时候用false参数?你得duang,duang实验。这个麻烦能直接将人劝退。
- py的中文问题虽然都是可以解决的。但实际场合中,总是有中文问题。常见的,处理中文文件名问题。url中带有中文问题。UTF8的编码问题。
- 强制动态类型的,py版胯骨轴子,太灵活了,太容易闪到腰。py无法锁死变量类型,成为静态变量,真的很不爽。这一点这很重要,甚至有人说py不适合大型项目。
- 路径依赖,py脚本必须使用绝对路径,脚本名还不能起名为ssl,http,request等库名或保留关键字名称。
- python安装麻烦,升级麻烦。第三方库、包对路径有依赖,部署困难,移动困难,简直是癌症。用起来是真麻烦,如果项目还是离线环境,那就更麻烦。py2和py3的兼容性,语法和模块差异较大,基本以py2老版本为主,新版本这个问题逐渐消解了。centos6,centos7,都是python2,centos8默认py3,ubuntu1404,ubuntu1804---默认py2,ubuntu1604默认py3,debian8是python2,debian9又升级成了python3
- 使用批量运维工具ansible完成运维工作其实和是否掌握python无关。因为ansible无法和python进行对象级别的传值。你若说ansible和python有关。那我问你,司机都要会设计车,会造车,会修车吗?
- 最后,从经济学角度讲,精通python的人太贵,运维的工资只能招到py低手。py高手有更挣钱的方向,【高富帅不愿入穷坑】写运维脚本。即便写出来,也很繁琐,不好用。
不过python在数据处理方面的库还是很好用的,如json,xml等数据格式化或数据处理模块,所以,在编写脚本的时候,需要考虑脚本的主要用途,如果是为了系统管理和维护,那shell比python好用且方便,如果是为了处理数据,格式化数据,或通过操作API实现多线程,网络,数据库的操作,那python就更能节省成本。
------------------------------------------------分割线----------------------------------------------------------------------
以下内容是在日常工作中使用python实现shell功能或操作的最佳对照实践:
1.python执行linux命令:python中的sys与system不是同一个东西,system是os模块下的一个函数,可以将字符串转化成命令在服务器上运行;其原理是每一条system函数执行时,其会创建一个子进程在系统上执行命令行,子进程的执行结果无法影响主进程;上述原理会导致当需要执行多条命令行的时候可能得不到预期的结果;最后,针对linux上的常用命令, os.system也有对应的函数与方法调用,如创建/删除文件夹;建议使用方法来实现对linux系统的操作,如使用方法删除文件夹时,如果文件夹不存在,会出现拒绝访问的错误,但使用命令的话,只会无脑执行。
import os
os.system('cd /usr/local')
os.mkdir('aaa.txt)
上述程序运行后会发现txt文件并没有创建在/usr/local文件夹下,而是在当前的目录下;
参考办法:为了保证system执行多条命令可以成功,多条命令需要在同一个子进程中运行;
import os
os.system('cd /usr/local && mkdir aaa.txt')
# 或者
os.system('cd /usr/local ; mkdir aaa.txt')
2.python判断linux命令是否执行成功:python中实现对linux系统执行shell有两种方法:os.system(cmd)或os.popen(cmd)脚本执行过程中的输出内容。实际使用时视需求情况而选择。
两者的区别是:
os.system(cmd)的返回值是脚本的退出状态码,只会有0(成功),1,2
os.popen(cmd)返回脚本执行的输出内容作为返回值
比如计算一个文件的md5值:
os.system(cmd):
该方法在调用完shell脚本后,返回一个信号代码。
>>> os.system('md5sum /root/all.sql')
7735d611ebce91ebb4c7acc4747a8b67 /root/all.sql
0 #返回的信号代码 0(成功)
os.popen(cmd):
这种调用方式是通过管道的方式来实现,函数返回一个file-like的对象,里面的内容是脚本输出的内容(可简单理解为echo输出的内容)。使用os.popen调用脚本的情况:
如:
>>> md5_value = os.popen('md5sum /root/all.sql') #将结果赋值给变量
>>> print(type(md5_value)) #查看类型
<class 'os._wrap_close'>
>>> print(md5_value.read().split()[0]) #取值
7735d611ebce91ebb4c7acc4747a8b67
明显地,像调用”ls”这样的shell命令,应该使用popen的方法来获得内容
3.python判断路径或文件是否存在:os模块有path函数及方法可以来实现判断路径或文件是否存在
>>> import os
>>> os.path.isfile('/root/test')
False
>>> os.path.isfile('/root/test.sh')
True
>>> os.path.isdir('/root/')
True
>>> os.path.isdir('/root/ss')
False
>>>
4.python判断文件读、写、执行权限:os模块中有acces函数来实现
>>> os.access('/root/test.sh',os.X_OK)
True
>>> os.access('/root/test.sh',os.W_OK)
True
>>> os.access('/root/test.sh',os.R_OK)
True
>>>
5.关于commands库,最近接触到一些较老的python脚本,看到有使用commands库来调用shell命令,这个库作为2.x版本的内置库,已经在3.x版本中删除了,由subprocess库兼容功能与用法。
此外,该模块还旨在替换几个较旧的模块和功能:
- 首先应该知道的是,Python2.4版本引入了subprocess模块用来替换os.system()、os.popen()、os.spawn*()等函数以及commands模块;也就是说如果你使用的是Python 2.4及以上的版本就应该使用subprocess模块了。
- 如果你的应用使用的Python 2.4以上,但是是Python 3.5以下的版本,Python官方给出的建议是使用subprocess.call()函数。Python 2.5中新增了一个subprocess.check_call()函数,Python 2.7中新增了一个subprocess.check_output()函数,这两个函数也可以按照需求进行使用。
- 如果你的应用使用的是Python 3.5及以上的版本(目前应该还很少),Python官方给出的建议是尽量使用subprocess.run()函数。
- 当subprocess.call()、subprocess.check_call()、subprocess.check_output()和subprocess.run()这些高级函数无法满足需求时,我们可以使用subprocess.Popen类来实现我们需要的复杂功能。
os.system
os.spawn
os.popen
popen2
commands
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通