登录  | 加入社区

黑狼游客您好!登录后享受更多精彩

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

查看: 1137|回复: 0

编写可靠 shell 脚本的 8 个发起

[复制链接]

216

主题

1

帖子

0

现金

黑狼菜鸟

Rank: 1

积分
0
发表于 2017-12-4 12:08:43 | 显示全部楼层 |阅读模式 来自 澳大利亚
fFAiNnvII7TfINMI.jpg


这八个发起,泉源于键者几年来编写 shell 脚本的一些履历和教导。究竟上开始写的时间还不止这几条,厥后思考再三,去掉几条无关痛痒的,末了剩下八条。绝不浮夸地说,每条都是精挑细选的,固然有几点算是老生常谈了。


1. 指定bash



shell 脚本的第一行,#!之后应该是什么?假如拿这个题目去问别人,差别的人的答复大概各不雷同。


我见过/usr/bin/env bash,也见过/bin/bash,另有/usr/bin/bash,另有/bin/sh,另有/usr/bin/env sh。这算是编程界的“’茴’字四种写法”了。


在多数环境下,以上五种写法都是等价的。但是,写过步伐的人都知道:“少数环境”里每每隐蔽着意想不到的坑。


假如体系的默认 shell 不是 bash 怎么办?好比某 Linux 发行版的某个版本,默认的 sh 就不是 bash。


假如体系的 bash 不是在 /usr/bin/bash 怎么办?


我保举利用 /usr/bin/env bash 和 /bin/bash。前者通过env添加一个中心层,让env在$PATH中搜刮bash;后者则是官方背书的,约定俗成的 bash 位置,/usr/bin/bash不外是指向它的一个符号链接。


2. set -e 和 set -x



OK,颠末一番讨论,如今第一行定下来了。接下来该开始写第二行了吧?
且慢!在你开始构思并写下详细的代码逻辑之前,先插入一行set -e和一行set -x。


set -x会在实行每一行 shell 脚本时,把实行的内容输出来。它可以让你看到当前实行的环境,内里涉及的变量也会被更换成现实的值。



set -e会在实行堕落时竣事步伐,就像其他语言中的“抛出非常”一样。(正确说,不是全部堕落的时间都会竣事步伐,见下面的注)


注:set -e竣事步伐的条件比力复杂,在man bash内里,足足用了一段话形貌各种景象。大多数实行都会在堕落时退出,除非 shell 下令位于以下环境:



  • 一个 pipeline 的非末端部门,好比 error | ok
  • 一个组合语句的非末端部门,好比 ok && error || other
  • 连续串语句的非末端部门,好比 error; ok
  • 位于判定语句内,包罗test、if、while等等。
这两个组合在一起用,可以在 debug 的时间替你节流很多时间。出于防御性编程的思量,有须要在写第一行详细的代码之前就插入它们。抚心自问,写代码的时间可以或许一次写对的次数有多少?大多数代码,在提交之前,通常都履历过反复调试修改的过程。与其在焦头烂额之际才引入这两个设置,不如一开始就给 debug 留下余地。在代码终于可以提交之后,再思量是否保存它们也不迟。



3. 带上shellcheck



好了,如今我已经有了三行(样板)代码,详细的业务逻辑一行都没写呢。是不是该开始写了?


且慢!工欲善其事,必先利其器。这次,我就先容一个 shell 脚本编写神器:
shellcheck



说来内疚,固然写了几年 shell 脚本,有些语法我照旧记不清晰。这时间就要依仗 shellcheck 辅导一下了。shellcheck 除了可以提示语法题目以外,还能查抄出 shell 脚本编写常见的 bad code。原来我的N条发起内里,另有几条是关于这些 bad code 的,不外思量到 shellcheck 完全可以发掘出这些题目,于是忍痛把它们都剔除在外了。毫无疑问,利用 shellcheck 给我的 shell 编写技能带来了巨大的飞跃。


所谓“站在巨人的肩膀上”,固然我们这些新兵蛋子,技能不如老兵们强,但是我们可以在装备上赶上对方啊!动动手安装一下,就能结识一个谆谆教导的“老师”,何乐而不为?


趁便一提,shellcheck 居然是用 haskell 写的。谁说 haskell 只能用来装逼?



4. 变量睁开



在 shell 脚本中,偶然可以看到如许的做法:echo $xxx | awk/sed/grep/cut... 。看起来大张形势的样子,实在不外是想修改一个变量的值。杀鸡何须用牛刀?bash内建的变量睁开机制已经足以满意你各种需求!照旧老方法, read the f**k manaul! man bash 然后搜刮Parameter Expansion,下面就是你想要的本领。键者也写过一篇相干的文章,盼望能助上一臂之力:玩转Bash变量



5. 留意local



随着代码越写越多,你开始把重复的逻辑提炼成函数。有大概你会掉到bash的一个坑里。在bash,假如不加 local 限定词,变量默认都是全局的。变量默认全局——这跟 js 和 lua 相似;但相较而言,很少有 bash 教程一开始就告知你这个究竟。在顶级作用域里,是否是全局变量并不紧张。但是在函数内里,声明一个全局变量大概会污染到其他作用域(尤其在你根本没有留意到这一点的环境下)。以是,对于在函数内声明的变量,请务必记得加上 local 限定词。



6. trap信号



假如你写过轻微复杂点的在背景运行的步伐,应该知道 posix 尺度内里“信号”是什么一回事。假如不知道,直接看下一段。像其他语言一样,shell 也支持处置惩罚信号。trap sighandler INT可以在吸收到 SIGINT 时调用 sighandler 函数。捕捉其他信号的方式以此类推。


不外 trap 的重要应用场景可不是捕捉哪个信号。trap 下令支持“捕捉”很多差别的流程——正确来说,答应用户给特定的流程注入函数调用。此中最为常用的是trap func EXIT和trap func ERR。


trap func EXIT答应在脚本竣事时调用函数。由于无论正常退出抑或非常退出,所注册的函数都能得以调用,在必要调用一个清算函数的场景下,我都是用它注册清算函数,而不是简朴地在脚本末端调用清算函数。


trap func ERR答应在运行堕落时调用函数。一个常用的技法是,利用全局变量ERROR存储错误信息,然后在注册的函数中根据存储的值完成对应的错误陈诉。把本来四分五裂的错误处置惩罚逻辑会合到一处,有时间会起奇效。不外要记着,步伐非常退出时,既会调用EXIT注册的函数,也会调用ERR注册的函数。



7. 三思后行



以上几条都是详细的发起,剩下两条比力务虚。


这条发起的名字叫“三思而行”。实在无论写什么代码,哪怕只是一个辅助脚本,都要三思而行,切忌粗心大意。不,写脚本的时间更要记着这点。究竟很多时间,一个复杂的脚本发端于几行小小的下令。一开始写这个脚本的人,大概以为它只是一次性使命。代码里不免对一些外部条件有些假定,在其时大概是正常的,但是随着外部情况的变革,这些就成了隐蔽的暗礁。落井下石的是,险些没有人会给脚本做测试。除非你去运行它,否则不知道它是否还能正常利用。


要想减缓脚本代码的腐烂速率,必要在编写的时间辨清哪些是会变的依靠、哪些是脚本正常运行所不可或缺的。要有得当的抽象,编写可变动的代码;同时要有防御性编程的意识,给本身的代码一道护城河。



8. 扬长避短



有些时间,利用 shell 写脚本就意味着难以移植、难以同一地举行错误处置惩罚、难以利索地处置惩罚数据。


固然利用外部的下令可以方便快捷地实现各种复杂的功能,但作为硬币的反面,不得不依赖grep、sed、awk等各种工具把它们粘合在一起。


假如有兼容多平台的需求,还得警惕规避诸如BSD和GNU coreutils,bash版本差别之类奇希奇怪的陷阱。


由于缺乏美满的数据布局以及同等的API,shell 脚本在处置惩罚复杂的逻辑上力有未逮。


办理特定的题目要用符合的工具。知道什么时间用 shell,什么时间切换到别的一门更通用的脚本语言(好比ruby/python/perl),这也是编写可靠 shell 脚本的诀窍。假如你的使命可以组合常见的下令来完成,而且只涉及简朴的数据,那么 shell 脚本就是得当的锤子。假如你的使命包罗较为复杂的逻辑,而且数据布局复杂,那么你必要用ruby/python之类的语言编写脚本。

泉源:spacewander   
链接:segmentfault.com/a/1190000006900083


Linux云盘算5天免费课程11月23日火热开讲运维干货内容免费听,点击文末“阅读原文”即可免费听运维课速速来抢~~~~

    PS:记得查收小编送你的免费大礼包呦~
    免费送 | 1000多套简历模板免费拿,附赠简历制作教程!
    免费领 | 《Shell脚本 100例》电子书免费拿,运维必备干货~

      UO83w5DE1d355X28.jpg ZAI3P1A3M111AisA.jpg ▼▼点击【阅读原文】,免费听5天Linux运维干货分享课,火热开讲中,速来抢!





上一篇:扣丁学堂​PHP​培训之​php​底子知识总结
下一篇:​PHP ​7.2:统统只为更好的安全性和代码处置惩罚
您需要登录后才可以回帖 登录 | 加入社区

本版积分规则

 

QQ|申请友链|小黑屋|手机版|Hlshell Inc. ( 豫ICP备16002110号-5 )

GMT+8, 2024-5-16 00:53 , Processed in 0.063962 second(s), 47 queries .

HLShell有权修改版权声明内容,如有任何爭議,HLShell將保留最終決定權!

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表