七年老运维实战中的 Shell 开发经验总结【转】
无论是系统运维,还是应用运维,均可分为“纯手工”—> “脚本化”—> “自动化”—>“智能化”几个阶段,其中自动化阶段,主要是将一些重复性人工操作和运维经验封装为程序或脚本,一方面避免重复性操作及风险,另一方面提高执行效率。在自动化运维的转变过程中,经常使用的可能就是shell脚本了,今天主要分享下shell脚本开发在运维工作中的一些经验总结。
小脚本有大智慧,别小看几十行代码,夹杂着系统设计、代码规范和操作经验等等细节,在建设自动化运维的工作中,还是很值得我们研究学习的,下面总结这些也都是源于各位脚本达人和我们在自身工作中“遇到的坑”、“摔过的跟头”和“排过的雷”,与大家共享。
这里主要介绍并参考我行已经形成的一些shell编写规范,编写时严格遵守这些规范,不仅使编写人受益,同时也能提高使用者的执行效率。
1)脚本开头部分应有脚本功能说明、参数使用说明、作者姓名、创建/修改日期、版本信息,格式为:
2)脚本编写时,注意格式对齐,如所有的循环或者判断语句前后的语句进行对齐,以及case的选取完全,如:
3)脚本开头执行时,执行如下命令,在执行过程中若遇到使用了未定义的变量或命令返回值为非零,将直接报错退出:
4)建议将命令行的每个参数放在单引号、双引号中,特别是rm、mv等可能对生产现有数据造成修改的操作,建议使用垃圾箱策略:rm操作转意为mv操作,制定文件保存目录,以防回退,并定期清理:
5)命令行中参数需要使用‘*’、‘?’通配符的,应依据最精确匹配原则,如能确定文件、目录名称的前缀、后缀、扩展名及其他可识别关键字的,须在参数中包含该信息,如能确定文件、目录的长度应使用‘?’通配符,不得使用‘*’,推荐的使用方式:
不推荐使用的方式:
禁止使用的方式:
6)给数值型变量的赋值后,需由手段保证变量的值为数值型,避免在后续的处理中出现异常:
7)在判断条件中使用的变量,必须包含在双引号中,如:
禁止使用的方式:
8)对文件进行打包备份时,必须使用相对路径进行打包,如:
严禁将全路径打入tar包, 如:
9)对于打包后还需进行压缩的文件,建议使用管道进行处理,如:
不建议两部分分开执行:
10)使用ps命令筛选进程时,如能确定进程所属用户,必须在参数中指定用户名称,如其输出作为kill命令的输入,则必须指定进程所属用户,如:
这里介绍的主要是日常shell编写中遇到比较隐蔽或看似简单,却难以发现的“坑”,编写中应尽量避免使用,使用更优的方法避免重蹈覆辙。
1)更新文件使用>不用cp
使用>修改和回退文件时,保留原文件的属组和权限,避免使用cp时权限属组被修改。
2)使用kill前确认
关键字用-w 精确匹配字段;
kill前后都保留现场, 两次ps -ef|grep -w 关键字|grep -v grep >>/tmp/kill_进程名_.backup;
删除前要校验,获取进程号是否唯一,避免多杀或误杀的情况。
3)使用rm前确认
删除前备份删除对象信息,避免使用变量,直接使用文件和目录名;
如果必须使用时,删除前,建议检查避免误删,删除目录和文件信息保留:
建议禁用find遍历根目录进行查找,同时删除前进行确认,避免多删或误删的情况。
4)For循环的坑
for循环的in条件按空格来区分,避免进入不正确或死循环。
5)while循环的禁忌
如果还想使用循环中的变量,不要while结合管道使用。
6)慎用cp
这句话基本上正确,但同样有空格分词的问题。所以应当用双引号:
但是如果凑巧文件名以 - 开头,这个文件名会被 cp 当作命令行选项来处理。
可以试试下面这个:
但也可能再碰上一个不支持 -- 选项的系统,所以最好用下面的方法:
7)慎用cd
避免使用cd到操作目录再操作的方式,可能导致进入目录失败,误删除,如:
建议如下:
8) 用[[ ]]代替[ ]
当$var为空时,上面的命令就变成了[ ="bar" ]
类似地,当$var包含空格时:
[ space words here = "var" ]两者都会出错。所以应当用双引号将变量括起来:
[ "$var" = var ] 几乎完美了。
但是,当$var以 - 开头时依然会有问题。在较新的bash中你可以用下面的方法来代替,[[ ]]关键字能正确处理空白、空格、带横线等问题。
另注意,[[适用于字符串,如果是数值,要用如:(( $var > 8 ))
9)管道操作中不要同时读写文件
你不能在同一条管道操作中同时读写一个文件。根据管道的实现方式,file要么被截断成0字节,要么会无限增长直到填满整个硬盘。如果想改变原文件的内容,只能先将输出写到临时文件中再用mv命令。
10)cd的易错问题
cd 有可能会出错,导致要执行的命令就会在你预想不到的目录里执行了。所以一定要记得判断cd的返回值。
如果你要根据cd的返回值执行多条命令,可以用 ||。
关于目录的一点题外话,假设你要在shell程序中频繁变换工作目录,如下面的代码:
不如这样写:
括号会强制启动一个子shell,这样在这个子shell中改变工作目录不会影响父shell(执行这个脚本的shell),就可以省掉cd - 的麻烦。
目前行里自动化工具越来越多,无论是应用的MAOP或系统的SMDB,自动化实现都还是日常运维脚本的调用,结合日常运维的一些经验,脚本中就更需要考虑周全和控制风险。这里介绍一些结合运维场景的脚本应用,希望规避以前犯过的错,重点在控制风险。
1) 支持交互式脚本的应用
很多脚本中需要进行交互,在规避风险的同时,需要通过自动化工具发布来支持交互,可以使用expect,示例如下:
也可以使用curl工具来替代简单的交互:
#FTP SFTP下载
curl-u ftpuser:ftppassword -O "sftp://ftp_ip:ftp_port/pathfile"
#FTP SFTP上传
curl-u ftpuser:ftppassword --ftp-create-dirs-T upfile "sftp://ftp_ip:ftp_port/filepath/upfile"
2)脚本规范执行和日志追溯
直接执行的脚本很危险,要提示用户如何使用脚本,并记录日志以便跟踪。
示例如下:
3)脚本的并发锁控制
避免多人同时执行或并发同时执行的异常问题,建议增加锁机制,示例如下:
4)控制脚本不退出的风险
周期频繁执行的脚本,需要防止脚本hang住不退出,导致后续脚本再次执行。
5)避免集中发布脚本造成的风险
使用ftp、sftp传输、下载文件,或者集中访问存储端口时,尽量增加发布对象散列,避免集中操作造成存储端口拥堵,跨防火墙流量超限报警等影响。
6)避免文件无限增长的风险
向一个文件中追加数据时,一定要设置阀值,必要时清空,避免文件无限增大:
目录增加清理过期文件策略,避免产生的文件越来越多,造成文件节点用尽:
目录中的文件过多,会报参数太长错误无法删除,建议放在循环中遍历删除:
总结:
鉴于以上脚本,我们可以从中汲取一些经验,规避一些风险:
通过增加日志记录输出和脚本执行的方法说明,并自动交互和传递参数,避免执行脚本的操作风险;利用文件锁机制和运维中一些规避风险的方法,使得脚本自动执行起来更便捷更安全。
1. 通过规范类脚本的定义,标准常量定义、清晰的注释、函数和变量大小写用法,细节中可以看出严谨,即使只有几行,也能体现出一名优秀脚本开发人员的素质。
2. 通过易错类脚本中的“坑”,使得 shell面向过程的编写更得心应手,让脚本规范的同时,逻辑也更严谨清晰,避免了错误,也提高了脚本的开发效率。
3. 通过运维场景的脚本应用,规避各种开发和执行过程中的风险,使得shell脚本不仅能支持自动化发布,更可以全面智能化的为运维服务。
转自
https://www.toutiao.com/a6763489980900704771/
loginhttp://10.72.8.76/?res=notyet&uamip=1.1.1.1&uamport=3990&challenge=a9d9918db4288fac5623433f25ef022e&called=B4-82-C5-50-F0-F0-hna-idc-1&apmac=B4-82-C5-58-80-B0&apname=R2AP-000E2F-idc&vendor=relay2&nasid=R2AP-000E2F-idc&agent=Mozilla%2f5.0%20%28Windows%20NT%2010.0%3b%20WOW64%29%20AppleWebKit%2f537.36%20%28KHTML%2c%20like%20Gecko%29%20Chrome%2f61.0.3163.79%20Safari%2f537.36%20Maxthon%2f5.2.7.5000&mac=C4-9D-ED-AE-90-59&ip=192.168.35.28&ssid=hna-idc-1&userurl=http%3a%2f%2fgo.maxthon.cn%2fredir%2fmx5%2fpc%2fstatic.htm%3fv%3d5.2.7.5000%26lang%3dzh-cn&md=C1369E74068EB738A5F14EC22D2DAE51
七年老运维实战中的 Shell 开发经验总结【转】的更多相关文章
- 运维实战案例之“Too many open files”错误与解决方法
运维实战案例之"Too many open files"错误与解决方法 技术小甜 2017-11-16 15:02:00 浏览869 服务器 shell tomcat 脚本 o ...
- 运维工作中sed常规操作命令梳理
sed是一个流编辑器(stream editor),一个非交互式的行编辑器.它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为"模式空间",接着用sed命令处理缓冲 ...
- Python 开发个人微信号在运维开发中的使用
一.主题:Python 开发个人微信号在运维开发中的使用 二.内容: 企业公众号 介绍开发微信公众号的后台逻辑,包括服务器验证逻辑.用户认证逻辑 个人微信号 面对企业微信的种种限制,可以使用 Itch ...
- Linux 运维工作中的经典应用ansible(批量管理)Docker容器技术(环境的快速搭建)
一 Ansible自动化运维工具 Python 在运维工作中的经典应用 ansible(批量管理操作) .安装ansible(需要bese epel 2种源) wget -O /etc/yum.rep ...
- DevSecOps 运维模式中的安全性
本文想从技术的角度谈谈我对云计算数据中心 DevSecOps 运维模式中的安全性的理解,和过去几年我在云服务业务连续性管理方面的探索. 现在公有云服务商都不约而同地转向 DevSecOps 模式.De ...
- 网易OpenStack部署运维实战
OpenStack自2010年项目成立以来,已经有超过200个公司加入了 OpenStack 项目,目前参与 OpenStack 项目的开发人员有 17,000+,而且这些数字还在增加,作为一个开源的 ...
- 《Splunk智能运维实战》——1.7 为本书加载样本数据
本节书摘来自华章计算机<Splunk智能运维实战>一书中的第1章,第1.7节,作者 [美]乔史·戴昆(Josh Diakun),保罗R.约翰逊(Paul R. Johnson),德莱克·默 ...
- CentOS7系统管理与运维实战
CentOS7系统管理与运维实战 下载地址 https://pan.baidu.com/s/1KFHVI-XjGaLMrh39WuhyCw 扫码下面二维码关注公众号回复100007 获取分享码 本书目 ...
- Istio 运维实战系列(2):让人头大的『无头服务』-上
本系列文章将介绍用户从 Spring Cloud,Dubbo 等传统微服务框架迁移到 Istio 服务网格时的一些经验,以及在使用 Istio 过程中可能遇到的一些常见问题的解决方法. 什么是『无头服 ...
随机推荐
- adb shell get/setprop, setenforce...
adb shell getprop <key> 获取设备参数信息adb shell setprop <key> <value> 设置设备参数信息 例子1:>C ...
- 5.1 dex文件解析
1.DexHeader结构体占用0x70字节,源码位置 dalvik\libdex\DexFile.h文件中269/* 270 * Direct-mapped "header_item&qu ...
- Mac 编译报错 symbol(s) not found for
查看静态库文件支持的arm64指令集架构的方法 root# lipo -info libname.a Architectures in the fat file: libname.a are: arm ...
- prometheus学习系列三:node_exporter安装部署
node_exporter简介 node_exporter安装部署 [root@node00 ~]# cd /usr/src/ [root@node00 src]# wget https://gith ...
- Odoo中的模型继承、视图继承、Qweb模板继承详解
转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826114.html 在实际开发过程中,经常会遇到需要修改Odoo原生逻辑的情况.然而,直接修改Odoo底 ...
- 【转】大众点评CAT开源监控系统剖析
https://www.cnblogs.com/yeahwell/p/cat.html 参考文档: 大众点评的实时监控系统分析(一) CAT_source_analyze 透过CAT,来看分布式实时监 ...
- 2019年杭电多校第二场 1008题Harmonious Army(HDU6598+最小割+建图)
题目链接 传送门 题意 有\(n\)个士兵,要你给他们分配职业.有\(m\)对关系,对于某一对关系\(u,v\),如果同为勇士则总能力增加\(a\),同法师则增加\(c\),一个勇士一个法师增加\(\ ...
- ie6下标签定义的高失效,显示的高不受设定的height值影响
今天又碰到一个奇葩的ie6兼容bug,忍不住抱怨下这个后妈生的鬼东西!! 看图这个是在非ie6下的浏览器效果
- maven 查看依赖树结构命令mvn dependency:tree
使用maven 管理项目的依赖,可以使用如下命令查看依赖树结构: mvn dependency:tree 如下图是使用idea的终端执行命令的局部图: 也可以使用如下命令将输出定向到某个文件,这样就可 ...
- C#中RadioButton选中和取消选中(一种没办法选中和未选中切换)
今天在做Winform 中RadioButton控件时,遇到一个小坑,虽然很简单,但是浪费我十分钟,感觉需要记录一下共勉. 问题描述:(RadioButton控件名为rbTime) 本来以为判断一下是 ...