java调用shell获取错误信息_Shell 开发在运维中的经验总结

点击上方“方志朋”,选择“设为星标”

回复”666“获取新整理的面试资料5440a06771c419322ef6cccddfd82626.png

4eddae497f2f36ab4953747c476c4ca9.png

无论是系统运维,还是应用运维,均可分为“纯手工”—> “脚本化”—> “自动化”—>“智能化”几个阶段,其中自动化阶段,主要是将一些重复性人工操作和运维经验封装为程序或脚本,一方面避免重复性操作及风险,另一方面提高执行效率。在自动化运维的转变过程中,经常使用的可能就是shell脚本了,今天主要分享下shell脚本开发在运维工作中的一些经验总结。

小脚本有大智慧,别小看几十行代码,夹杂着系统设计、代码规范和操作经验等等细节,在建设自动化运维的工作中,还是很值得我们研究学习的,下面总结这些也都是源于各位脚本达人和我们在自身工作中“遇到的坑”、“摔过的跟头”和“排过的雷”,与大家共享。

296d182fb6daf11401985f7168318ef1.png

这里主要介绍并参考我行已经形成的一些shell编写规范,编写时严格遵守这些规范,不仅使编写人受益,同时也能提高使用者的执行效率。

1)脚本开头部分应有脚本功能说明、参数使用说明、作者姓名、创建/修改日期、版本信息,格式为:

66b112f191ef17fe5b596eca759857b0.png

2)脚本编写时,注意格式对齐,如所有的循环或者判断语句前后的语句进行对齐,以及case的选取完全,如:

7de0613ea7623f5482a62ff5c02daa72.png

3)脚本开头执行时,执行如下命令,在执行过程中若遇到使用了未定义的变量或命令返回值为非零,将直接报错退出:

a793ca5e8dd70df9c47e3482aefa3aac.png

4)建议将命令行的每个参数放在单引号、双引号中,特别是rm、mv等可能对生产现有数据造成修改的操作,建议使用垃圾箱策略:rm操作转意为mv操作,制定文件保存目录,以防回退,并定期清理:

360d45d8d94c86e08e656828ab269ade.png

5)命令行中参数需要使用‘*’、‘?’通配符的,应依据最精确匹配原则,如能确定文件、目录名称的前缀、后缀、扩展名及其他可识别关键字的,须在参数中包含该信息,如能确定文件、目录的长度应使用‘?’通配符,不得使用‘*’,推荐的使用方式:

8236732ca3b52d09870b2a7e75558107.png

不推荐使用的方式:

6625e3a0cbb6e04131b184a8019e105a.png

禁止使用的方式:

6e0e4f3ebb752ccee769532c19b6874e.png

6)给数值型变量的赋值后,需由手段保证变量的值为数值型,避免在后续的处理中出现异常:

007ffc1ed46e8e643a65e5616fecf74d.png

7)在判断条件中使用的变量,必须包含在双引号中,如:

f4585b87ef68212c151407544b2bed62.png

禁止使用的方式:

b4dee70fd8cbf3ade0dff772480e9c19.png

07764e6d6b0f51cfb989f9adafb5eddb.png

8)对文件进行打包备份时,必须使用相对路径进行打包,如:

22e095da58692d8e2209007ee77e7492.png

严禁将全路径打入tar包, 如:

1a670543d0932ac4c8c59b90fe884011.png

9)对于打包后还需进行压缩的文件,建议使用管道进行处理,如:

14095ef57a43233b33fc1faf612acdfa.png

不建议两部分分开执行:

ba036efec5b9d65c0c1660a5a16f58f9.png

10)使用ps命令筛选进程时,如能确定进程所属用户,必须在参数中指定用户名称,如其输出作为kill命令的输入,则必须指定进程所属用户,如:

7e091e81dba58de406e2842097705760.png

9aebd131bf4376ad32c000b3a1d35aec.png

这里介绍的主要是日常shell编写中遇到比较隐蔽或看似简单,却难以发现的“坑”,编写中应尽量避免使用,使用更优的方法避免重蹈覆辙。

1)更新文件使用>不用cp

使用>修改和回退文件时,保留原文件的属组和权限,避免使用cp时权限属组被修改。

eeddf4d6198bcb287dad75ed5d79596d.png

2)使用kill前确认

关键字用-w 精确匹配字段;

kill前后都保留现场, 两次ps -ef|grep -w 关键字|grep -v grep >>/tmp/kill_进程名_.backup;

删除前要校验,获取进程号是否唯一,避免多杀或误杀的情况。

5855c26c5b4167cca2adc94919366044.png

3)使用rm前确认

删除前备份删除对象信息,避免使用变量,直接使用文件和目录名;

如果必须使用时,删除前,建议检查避免误删,删除目录和文件信息保留:

0175a776a28b543b12669bf8a49bd814.png

建议禁用find遍历根目录进行查找,同时删除前进行确认,避免多删或误删的情况。

4)For循环的坑

for循环的in条件按空格来区分,避免进入不正确或死循环。

e1025bd89299df51b24f81914262f562.png

5)while循环的禁忌

如果还想使用循环中的变量,不要while结合管道使用。

bd98f22aa38a7b52c1b66a7755fb5f0c.png

6)慎用cp

这句话基本上正确,但同样有空格分词的问题。所以应当用双引号:

9b690165a379575a7c229ab65dd53a33.png

但是如果凑巧文件名以 - 开头,这个文件名会被 cp 当作命令行选项来处理。

可以试试下面这个:   

4d6b3c1ed3d563504f242c92d83b8551.png

但也可能再碰上一个不支持 -- 选项的系统,所以最好用下面的方法: 

0078183a67e3bd4a64dc46011da3d1eb.png

7)慎用cd

避免使用cd到操作目录再操作的方式,可能导致进入目录失败,误删除,如:

936d01e7a8496ac0d439c8193992225c.png

建议如下:

65be22387f2780f3f45b7e9afba66e6a.png

8)     用[[  ]]代替[ ]

63ef61058aebbade3413a8158f259490.png

当$var为空时,上面的命令就变成了[ ="bar" ]

类似地,当$var包含空格时:

[ space words here = "var" ]两者都会出错。所以应当用双引号将变量括起来:

[ "$var" = var ]  几乎完美了。

但是,当$var以 - 开头时依然会有问题。在较新的bash中你可以用下面的方法来代替,[[ ]]关键字能正确处理空白、空格、带横线等问题。

efee704f2b3584109b28b21aab78763b.png

另注意,[[适用于字符串,如果是数值,要用如:(( $var > 8 ))

9)管道操作中不要同时读写文件

0db950b1b8748f2b2f8b0d59be205c17.png

你不能在同一条管道操作中同时读写一个文件。根据管道的实现方式,file要么被截断成0字节,要么会无限增长直到填满整个硬盘。如果想改变原文件的内容,只能先将输出写到临时文件中再用mv命令。

4e63b08709e80e8fc918986f0559c5b8.png

10)cd的易错问题

cd 有可能会出错,导致要执行的命令就会在你预想不到的目录里执行了。所以一定要记得判断cd的返回值。

6c7f2018d725df28c199949f87e4f34e.png

如果你要根据cd的返回值执行多条命令,可以用 ||。

7c00090605b132e8b8e08b2e485de228.png

关于目录的一点题外话,假设你要在shell程序中频繁变换工作目录,如下面的代码:

84f40bdd20062bcea4efe7864cd37870.png

不如这样写:

9581d9bfe8df9831fb8ea1b9b4a6bbe8.png

括号会强制启动一个子shell,这样在这个子shell中改变工作目录不会影响父shell(执行这个脚本的shell),就可以省掉cd - 的麻烦。

1a93ca46e4a81f549d842573acd43f75.png

目前行里自动化工具越来越多,无论是应用的MAOP或系统的SMDB,自动化实现都还是日常运维脚本的调用,结合日常运维的一些经验,脚本中就更需要考虑周全和控制风险。这里介绍一些结合运维场景的脚本应用,希望规避以前犯过的错,重点在控制风险。

1)     支持交互式脚本的应用

很多脚本中需要进行交互,在规避风险的同时,需要通过自动化工具发布来支持交互,可以使用expect,示例如下:

b628694fc74bf3ab2f3067635f827949.png

也可以使用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)脚本规范执行和日志追溯

直接执行的脚本很危险,要提示用户如何使用脚本,并记录日志以便跟踪。

示例如下:

29e2190d9249613bff7341fc314c287a.png

3)脚本的并发锁控制

避免多人同时执行或并发同时执行的异常问题,建议增加锁机制,示例如下:

dc0f3b10a4b6f4375b8ce1c8d6261dc2.png

4)控制脚本不退出的风险

周期频繁执行的脚本,需要防止脚本hang住不退出,导致后续脚本再次执行。

f251d05ee2cb35eb77da361628591b74.png

5)避免集中发布脚本造成的风险

使用ftp、sftp传输、下载文件,或者集中访问存储端口时,尽量增加发布对象散列,避免集中操作造成存储端口拥堵,跨防火墙流量超限报警等影响。

022d2c8daf159d6576500433241987af.png

6)避免文件无限增长的风险

向一个文件中追加数据时,一定要设置阀值,必要时清空,避免文件无限增大:

967ccd7d90f187304edf81f259dfca20.png

目录增加清理过期文件策略,避免产生的文件越来越多,造成文件节点用尽:

6409d49f628ce6707dfaf14ec895978c.png

目录中的文件过多,会报参数太长错误无法删除,建议放在循环中遍历删除:

d25427f23e9aa4111cf9d864c3158bb5.png

总结:

鉴于以上脚本,我们可以从中汲取一些经验,规避一些风险:

通过增加日志记录输出和脚本执行的方法说明,并自动交互和传递参数,避免执行脚本的操作风险;利用文件锁机制和运维中一些规避风险的方法,使得脚本自动执行起来更便捷更安全。

1. 通过规范类脚本的定义,标准常量定义、清晰的注释、函数和变量大小写用法,细节中可以看出严谨,即使只有几行,也能体现出一名优秀脚本开发人员的素质。

2. 通过易错类脚本中的“坑”,使得 shell面向过程的编写更得心应手,让脚本规范的同时,逻辑也更严谨清晰,避免了错误,也提高了脚本的开发效率。

3. 通过运维场景的脚本应用,规避各种开发和执行过程中的风险,使得shell脚本不仅能支持自动化发布,更可以全面智能化的为运维服务。

来源:良许 Linux

热门内容:         
  •  日均 5 亿查询量的京东订单中心,为什么舍 MySQL 用 ES ?

  • 区块链入门教程

  • Redis 到底是怎么实现“附近的人”这个功能的呢?

  • Java 的 JSP 已经被淘汰了吗?

  • Java:如何更优雅的处理空值?

  • 为什么阿里巴巴要禁用Executors创建线程池?

964cceacdfa4866be6cd780f31b17b7f.png

最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

明天见(。・ω・。)ノ♡

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值