linux写shell脚本指令,linux命令与shell脚本编程大全pdf
这八条建议是基于Keychain几年来写shell脚本的经验和教训。其实我开始写的不仅仅是这几篇,然后经过深思熟虑,去掉了几个无关痛痒的东西,最后剩下了八篇。可以说每一个都是精挑细选的。自古以来就说了几点。
指定基本
脚本的第一行,#!那之后是什么?如果你问别人这个问题,答案可能因人而异。
还看过/usr/happy petrel /env bash。我也看过/快乐海燕/巴什。和/usr/happy petrel /bash,和/happy petrel /sh,和/usr/happy petrel /env sh。这就是编程界的“编写‘茴香脑’的四种方法”。
在很多情况下,以上五种写法是等价的。但是写程序的人都知道。“少数情况”往往隐藏着意想不到的漏洞。
如果系统默认shell不是bash怎么办?例如,在Linux发行版中,默认sh不是bash。
如果系统的bash不是/usr/happy petrel /bash怎么办?
推荐/usr/快乐海燕/env bash和/快乐海燕/bash。前者给env增加了一个中间层,使env能够在$PATH中搜索bash。后者得到了官方的认可,巴什将军的位置也得到了认可。/usr/happy petrel /bash只是它的一个符号链接。
2.集合e和集合x
好了,经过讨论,现在决定第一行。接下来我们开始写第二行好吗?
慢点,后视镜!在开始构思和编写具体的代码逻辑之前,请先插入set -e行和set -x行。
Set -x将在每次执行shell脚本中的每一行时输出执行的内容。您可以看到当前的执行状态,与此相关的变量将被实际值替换。
Set -e在出现错误时退出程序,就像其他语言中的“抛出异常”一样。(确切的说,并不是所有的程序出现错误都会退出。请参考以下注释)
注意:set -e程序的退出条件很复杂,在man bash中用它来说明各种情况。大多数运行都会因错误而终止,除非shell命令为:
不属于管道末端的部分,如error OK。
绑定语句结束以外的部分,如ok error other
一系列句子中未结束的部分,如error;完成的
位于判断语句中,包括test,if,while等。
两者结合可以让你在调试的时候节省很多时间。从防御性编程的角度来说,需要先插入第一行的具体代码,然后再写。请扪心自问,写代码的时候能不能一次写正确的次数。大部分代码在提交前都会经历反复调试修改的过程。与其介绍这两种配置,不如一开始就给调试留有余地。当代码最终可以提交时,再考虑是否保留它们也不迟。
3.自带薄壳检查
所以,现在我有三行代码(模板),但是还没有写任何具体的业务逻辑。我该开始写了吗?
慢点,后视镜!如果你想做好一件事,你必须先做好这件事。这次介绍一下shell script做的神器。这是外壳检查。
很尴尬。写shell脚本好几年了,有些语法记不清楚了。这时候就靠壳检请示了。Shell检查可以注意语法问题,也可以检查shell脚本中常见的坏代码。本来我的n个建议中有一部分是关于这些不好的代码的,但是shell check认为这些问题是完全可以发现的,所以勉强排除了。毫无疑问,使用外壳检查带来了外壳创建技能的巨大飞跃。
“站在巨人的肩膀上”是我们新兵的蛋蛋子。虽然他们的技术没有那个老兵高,但是在装备上可以追上对方。动手安装,可以认识被引导好方向的“老师”。为什么会这样?
对了,外壳检查其实是用haskell写的。谁说haskell只能强制使用?
4.变膨胀
在shell脚本中,echo $xxx awk/sed/grep/cut的做法。偶尔会出现。看似一鸣惊人,实际上只是想修正一个变量的值。不需要用hsjdsmt杀鸡吗?Bash内置的变量扩展机制足以满足你的需求!还是老办法,读他妈的manaul!搜索人bash和参数扩展。接下来是你想要的技术。
注意当地
你写的代码越多,你就越开始将重复的逻辑提取到函数中。可能会掉进bash的洞里。在bash中,如果没有指定局部限定符,默认情况下变量是一个全局变量。变量Global ——这个类似于js和lua;然而,bash教程很少一开始就告诉我们这个事实。在顶级范围内,是否是全局变量并不重要。但是,在函数中声明全局变量可能会被其他作用域污染。尤其是如果没有注意到这一点)。因此,记住函数中声明的变量必须有局部限定符。
6.陷波信号
例如
如果你写过稍微复杂一点的后台运行的程序,你应该知道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这样的语言编写脚本。
以上是边肖介绍的关于Shell脚本的8条可靠建议(值得收藏)。希望对你有帮助。如果您有任何问题,请给我留言,边肖将及时回复您。非常感谢您对剧本之家网站的支持!