我们一起来学Shell - 初识shell 2

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 我们一起来学Shell - 初识shell
作业脱机管理
  • 将作业(进程)切换到后台可以避免由于误操作如[ctrl]+c等导致的job被异常中断的情形,而脱机管理主要是针对终端异常断开的情形。
  • 通常使用nohup命令来使得脱机或注销之后,Job依旧可以继续运行。也就是说nohup忽略所有挂断(SIGHUP)信号。
  • 如果该方式命令之后未指定&符号,则job位于前台,指定&符号,则job位于后台。
  • 不加&

不加&,作业会在一个新的终端运行,当前终端是无法通过jobs命令查看到信息,只能通过ps -ef命令查看进程

由于使用的是sleep命令,并且没有加&,所以ps -ef | grep sleep会出现两个进程,父进程pid不会变,子进程pid会一直在变,因为他会不断的打开新的终端执行sleep这个命令,所以,如果要停止这个作业,需要使用kill 父进程pid命令

nohup sleep

使用jobs命令,可以查看到当前作业的运行情况(sleep命令后面的数字单位是秒,如果数字写的小,很快就退出了,jobs会查看不到作业)

不指定日志目录的情况下,会将日志写入到当前目录下的nohup.out文件中

nohup sleep 3000 &

指定日志目录的方法

注释:>& 等同于 2>&1&>,将正确的和错误的日志,都写入到指定的文件中

nohup sleep 3000 >& ./sleep.log &

命令执行的顺序

&& 具备逻辑判断

command1 && command2 只有在 command1 成功执行后才会执行 command2

|| 具备逻辑判断

command1 || command2 在 command1 没有成功执行时执行command2

; (分号)不具备逻辑判断

command1 ; command2 command1无论是否成功执行,执行完成后,都会去执行commadn2

通配符(元字符)表示的不是本意

常见的通配符

注意与正则稍有不同

字符 含义 实例
* 匹配0个或多个任意字符 a*b,a与b之间可以有任意长度的字符,也可以没有。例如:aabcb,ab,azxcb…
? 匹配一个任意字符 a?b,a与b之间必须但也只能存在一个字符,该字符可以是任意字符。例如:aab,abb,acb…
[list] 匹配list中的任意单个字符 a[xyz]b,a与b之间必须但也只能存在一个字符,该字符只能是x或y或z。例如:axb,ayb,azb
[!list] 匹配除list中的任意单个字符 a[!a-z]b,a与b之间必须但也只能存在一个字符,该字符不能是小写字母。例如:aAb,a0b…
[c1-c2] 匹配c1-c2间的任意单个字符 a[0-1]b,a与b之间必须但也只能存在一个字符,该字符只能是数字。例如:a0b,a1b…
{string1,string2,…} 匹配string1、string2等中的一个字符串 a{abc,xyz,opq}b,a与b之间必须但也只能存在一个字符串,字符串只能是abc或xyz或opq。例如:aabcb,axyzb,aopqb…

Shell 脚本规范

Shell脚本绝大部分命令自己平时也经常使用,但是在写成脚本的时候总觉得写的很难看。而且当我在看其他人写的脚本的时候,总觉得难以阅读。毕竟Shell脚本这个东西不算是正经的编程语言,他更像是一个工具,用来杂糅不同的程序供我们调用。因此很多人在写的时候也是想到哪里写到哪里,基本上都像是一段超长的main函数,不忍直视。同时,由于历史原因,Shell有很多不同的版本,而且也有很多有相同功能的命令需要我们进行取舍,以至于代码的规范很难统一。

 考虑到上面的这些原因,我查阅了一些相关的文档,发现这些问题其实很多人都考虑过,而且也形成了一些不错的文章,但是还是有点零散。因此我就在这里把这些文章稍微整理了一下,作为以后我自己写脚本的技术规范。

风格规范

开头有“蛇棒”

所谓shebang其实就是在很多脚本的第一行出现的以”#!”开头的注释,他指明了当我们没有指定解释器的时候默认的解释器,一般可能是下面这样:

#!/bin/bash

上面这种写法可能不太具备适应性,一般我们会用下面的方式来指定:

#!/usr/bin/env bash

除了 bash 之外,可以用下面的命令查看本机支持的解释器:

cat /etc/shells

注释

  • 注释的意义不仅在于解释用途,而在于告诉我们注意事项,就像是一个 README。
  • 具体的来说,对于Shell脚本,注释一般包括下面几个部分:
  • shebang
  • 脚本的参数
  • 脚本的用途
  • 脚本的注意事项
  • 脚本的写作时间,作者,版权等
  • 各个函数前的说明注释
  • 一些较复杂的单行命令注释

参数要规范

  • 这一点很重要,当脚本需要接受参数的时候,一定要先判断参数是否合乎规范,并给出合适的回显,方便使用者了解参数的使用。

变量

  • 一般情况下会将一些重要的环境变量定义在开头,确保这些变量的存在。
  • 一段好的代码通常是不会有很多硬编码在代码里的“魔数”的。如果一定要有,通常是用一个变量的形式定义在开头,然后调用的时候直接调用这个变量,这样方便日后的修改。

缩进

  • 因为很多需要缩进的地方(比如if,for语句)都不长,很多人都懒得去缩进,而且很多人不习惯用函数,导致缩进功能被弱化。
  • 正确的缩进是很重要的,尤其是在写函数的时候,否则在阅读的时候很容易把函数体跟直接执行的命令搞混。
  • 常见的缩进方法主要有"soft tab"和"hard tab"两种:
  • 所谓soft tab就是使用n个空格进行缩进(n通常是2或4)
  • 所谓hard tab当然就是指真实的"\t"字符
  • 对于if和for语句之类的,最好不要把then,do这些关键字单独写一行,这样看上去比较丑。

命名有标准

所谓命名规范,基本包含下面这几点:

  • 文件名规范,以.sh结尾,方便识别
  • 变量名字要有含义,不要拼错
  • 统一命名风格,写 Shell 一般用小写字母加下划线

编码要统一

在写脚本的时候尽量使用 UTF-8 编码,能够支持中文等一些奇奇怪怪的字符。不过虽然能写中文,但是在写注释以及打log的时候还是尽量英文,毕竟很多机器还是没有直接支持中文的,打出来可能会有乱码。

日志和回显

  • 日志的重要性不必多说,能够方便回头纠错,在大型的项目里是非常重要的。
  • 如果这个脚本是供用户直接在命令行使用的,那么最好还要能够在执行时实时回显执行过程,方便用户掌控。
  • 为了提高用户体验,会在回显中添加一些特效,比如颜色啊,闪烁啊之类的。

密码要移除

  • 不要把密码硬编写在脚本里。

太长要分行

  • 在调用某些程序的时候,参数可能会很长,这时候为了保证较好的阅读体验,我们可以用反斜杠来分行:
./configure \
–prefix=/usr \
–sbin-path=/usr/sbin/nginx \
–conf-path=/etc/nginx/nginx.conf

注意:在反斜杠前有个空格。

代码有效率

  • 在使用命令的时候要了解命令的具体做法,尤其当数据处理量大的时候,要时刻考虑该命令是否会影响效率。
  • 比如下面的两个sed命令:
sed -n '1p' file
sed -n '1p;1q' file 12

作用一样,都是获取文件的第一行。

但是第一条命令会读取整个文件,而第二条命令只读取第一行。

当文件很大的时候,仅仅是这样一条命令不一样就会造成巨大的效率差异。

当然,这里只是为了举一个例子,这个例子真正正确的用法应该是使用head -n1 file命令

勤用双引号

  • 几乎所有的大佬都推荐在使用"$"来获取变量的时候最好加上双引号。
  • 不加上双引号在很多情况下都会造成很大的麻烦,
#!/bin/sh
# 已知当前文件夹有一个a.sh的文件
var="*.sh"
echo $var
echo "$var" 

运行结果如下:

a.sh
*.sh

可以解释为它执行了下面的命令

echo *.sh
echo "*.sh"

在很多情况下,在将变量作为参数的时候,一定要注意上面这一点,仔细体会其中的差异。上面只是一个非常小的例子,实际应用的时候由于这个细节导致的问题实在是太多了

学会查路径

  • 很多情况下,会先获取当前脚本的路径,然后以这个路径为基准,去找其他的路径。通常我们是直接用 pwd 以期获得脚本的路径。
  • 不过其实这样是不严谨的,pwd 获得的是当前Shell的执行路径,而不是当前脚本的执行路径。
  • 正确的做法应该是下面这两种
script_dir=$(cd $(dirname $0) && pwd)
script_dir=$(dirname $(readlink -f $0 ))

应当先cd进当前脚本的目录然后再pwd,或者直接读取当前脚本的所在路径。

代码要简短

  • 这里的简短不单单是指代码长度,而是只用到的命令数。原则上我们应当做到,能一条命令解决的问题绝不用两条命令解决。这不仅牵涉到代码的可读性,而且也关乎代码的执行效率。
  • 最最经典的例子如下
cat /etc/passwd | grep root
grep root /etc/passwd

cat 命令最为人不齿的用法就是这样,用的没有任何意义,明明一条命令可以解决,非得加根管道

使用新写法

这里的新写法不是指有多厉害,而是指可能更希望使用较新引入的一些语法,更多是偏向代码风格

  • 尽量使用func( ){ }来定义函数,而不是func{ }
  • 尽量使用[[ ]]来代替[ ]
  • 尽量使用$()将命令的结果赋给变量,而不是反引号
  • 在复杂的场景下尽量使用printf代替echo进行回显

其他小技巧

  • 路径尽量保持绝对路径,不容易出错,如果非要用相对路径,最好用./修饰
  • 优先使用bash的变量替换代替awk sed,这样更加简短
  • 简单的if尽量使用&&||,写成单行。比如[[ x > 2]] && echo x
  • 当export变量时,尽量加上子脚本的namespace,保证变量不冲突
  • 会使用trap捕获信号,并在接受到终止信号时执行一些收尾工作
  • 使用mktemp生成临时文件或文件夹
  • 利用/dev/null过滤不友好的输出信息
  • 会利用命令的返回值判断命令的执行情况
  • 使用文件前要判断文件是否存在,否则做好异常处理
  • 不要处理ls后的数据(比如ls -l | awk '{ print $8 }'),
  • ls的结果非常不确定,并且平台有关
  • 读取文件时不要使用for loop而要使用while read

Shell 脚本调试

Shell脚本的语法调试,使用bash的相关参数进行调试

sh [参数] 文件名.sh
  • -n 不要执行script,仅查询语法的问题
  • -v 在执行script之前,先将script的内容输出到屏幕上
  • -x 将使用的脚本的内容输出到屏幕,该参数经常被使用

脚本运行方式

Linux中Shell脚本的执行通常有4种方式,分别为工作目录执行,绝对路径执行,sh执行,Shell环境执行。

工作目录执行

工作目录执行,指的是执行脚本时,先进入到脚本所在的目录(此时,称为工作目录),然后使用 ./脚本方式执行,这种方式,需要脚本有执行权限,否则会报错Permission denied

绝对路径执行

绝对路径中执行,指的是直接从根目录/到脚本目录的绝对路径,同样也是需要脚本有执行权限

sh 执行

sh执行,指的是用脚本对应的sh或bash来接着脚本执行,所以,脚本不是必须要有执行权限

Shell 环境执行

Shell环境执行,指的是在当前的Shell环境中执行,可以使用 .接脚本 或 source 接脚本

. test.sh

注意,点后面有空格

source test.sh


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1天前
|
Shell
Shell是什么?
2. Shell Shell是用户与操作系统之间的交互界面,接受用户命令并将其传递给内核执行。Shell可以是命令行界面(CLI)或图形用户界面(GUI)。其主要作用包括: 命令解释:解析用户输入的命令。 脚本执行:运行Shell脚本,实现自动化任务。 程序启动:根据用户命令启动应用程序。 环境管理:配置和管理用户环境变量。
7 2
|
30天前
|
Unix Shell Linux
Shell
【10月更文挑战第15天】
17 3
|
6月前
|
存储 Unix Shell
什么是Shell
Shell是用户与操作系统内核之间的接口,允许用户通过命令行或脚本来与操作系统进行交互。 它解释用户输入的命令,并将其转换为操作系统能够理解的指令,然后执行这些指令并将结果返回给用户。
82 4
|
监控 关系型数据库 MySQL
我们一起来学Shell - 初识shell 1
我们一起来学Shell - 初识shell
92 2
我们一起来学Shell - 初识shell 1
|
11月前
|
Shell 程序员
Shell 替代
Shell 替代
39 0
|
11月前
|
Unix Shell
Shell 联机帮助
Shell 联机帮助
52 0
|
安全 Shell Linux
强大好用的shell:什么是shell?
系统内核是操作系统的基本组成部分,它负责管理系统的硬件和软件资源,并提供一组基本的系统服务。内核是操作系统的核心,控制着计算机的所有主要功能,包括内存管理、进程管理、设备驱动程序、系统调用和安全防护等。内核在计算机中扮演着重要的角色,它为用户空间的应用程序提供访问硬件资源的接口,并通过进程间通信机制及系统调用来完成这些操作。内核的设计和实现对于操作系统的性能和稳定性有着至关重要的影响。
|
Shell
如何在shell下面实现a+b
如何在shell下面实现a+b
65 0
下一篇
无影云桌面