首页 > 编程笔记

什么是Shell,Shell脚本简介

熟练使用 Shell 脚本是每个 Linux 运维工程师的必备技能!不论是面试还是工作,总是会出现它的身影。

Shell 脚本的重要性毋庸置疑,以笔者的“惨痛”经历为例,当初在学 Linux 的时候笔者并没有很看重 Shell 脚本的学习,虽然也能实现简单的需求,但是没有往深处钻研。结果在找工作的时候,十家公司里面有九家的面试重点考察 Shell 脚本知识,最后的下场就可想而知了。

之后笔者花费精力狠狠钻研 Shell 脚本相关知识,在后续求职中总算“一雪前耻”。工作以后,笔者更是真正感受到 Shell 脚本的重要性,熟练使用 Shell 脚本大大提高了工作效率。

想要成为一名 Linux 运维工程师,Shell 脚本肯定会伴随着你的整个职业生涯,而它的作用也非常好理解,用一句通俗易懂的话总结就是,“减少 Linux 运维工程师的重复性工作”。

什么是Shell

大家可以把 Shell 脚本看作是一门编程语言,相比其他编程语言,Shell 更简单易学。现在市面上几乎所有编程语言的教学课程都是从使用著名的“Hello World”开始的,那我们的第一个 Shell 脚本也输出一下“Hello World”。

首先用 touch 命令创建文件,文件名为 hello.sh,扩展名“.sh”表示这是个 Shell 脚本,也就是说看到这个后缀立马就知道这是 Shell 脚本,扩展名并不会影响 Shell 脚本运行,为的就是做到见名知意。

我们输入两行简单的代码:
#!/bin/bash
echo "Hello World" #输出 hello world
第 1 行的“#!”是一个约定标记,用来告诉操作系统这个脚本需要用什么解释器来执行,也就是要使用哪一种 Shell;后面的 /bin/bash 指明了 Shell 解释器的具体位置。在写 Shell 脚本时,脚本的第一行必须是“#!/bin/bash”,如果想用别的解释器,需要在这里就指定别的解释器的位置,但是不能不写,这一行非常重要!

第 2 行的 echo 命令用于向标准输出 Stdout(Standard Output,一般就是指显示器)输出内容。在 .sh 文件中使用命令与在终端中直接输入命令的效果是一样的。

第 2 行的“#”及后面的内容是注释。Shell 脚本中所有以“#”开头的语句都是注释(当然了,以“#!”开头第一行语句除外)。在写 Shell 脚本时,多写注释是非常有必要的,既方便其他人能看懂你写的 Shell 脚本,也方便后期自己维护时看懂自己的脚本——实际上,即便是自己写的脚本,过一段时间后也很容易忘记。所以,一定要养成写注释的习惯。

Shell脚本的运行

写完 Shell 脚本后,下面就让它运行起来。运行 Shell 脚本的方式有两种:一种在新进程中运行,另一种是在当前进程中运行。

Shell 脚本执行类型:
1) 在新进程中运行:
./ 脚本名称;/bin/bash 脚本名称

2) 在当前进程中运行:
source脚本名称;.脚本名称
有朋友可能会问:“直接介绍执行 Shell 脚本的命令不就得了,那么简单的命令还需要做分类吗?”但笔者的初衷是希望大家能懂得更多,理解得更深、更透彻,而不是“知其然却不知其所以然”。

我们先看第一种类型:在新进程中运行 Shell 脚本,这种类型又分为两种执行方式。

1) 第一种执行方式是将 Shell 脚本作为软件程序来运行,Shell 脚本也是一种能够直接执行的程序,可以在终端直接调用(前提是使用 chmod 命令给 Shell 脚本加上执行权限),具体操作如下:
[root@noylinux opt]# ll
-rw-r--r--. 1 root root 32 11月 7 17:3 hello.sh
[root@noylinux opt]# chmod +x hello.sh #先赋予执行权限
[root@noylinux opt]# ll
-rwxr-xr-x. 1 root root 32 11月 7 17:3 hello.sh
[root@noylinux opt]# ./hello.sh #执行脚本
Hello World!
“chmod+x hello.sh”表示给 hello.sh 赋予执行权限,在最后一条命令中,“./”表示当前目录,整条命令的意思是执行当前目录下的 hello.sh 脚本文件,如果不写“./”,Linux 操作系统会找不到 hello.sh 脚本文件的位置,导致报错,无法执行该脚本。

通过这种执行方式来运行 Shell 脚本,那 Shell 脚本文件第一行的“#!/bin/bash”一定要写,而且要写对,这样 Linux 操作系统就能按位置找到指定的 Shell 解释器。

那怎么才能判断自己写的 Shell 解释器的位置对不对呢?比如我们常用 Bash 作为 Shell 脚本的解释器,which bash 命令就能得到 Bash 解释器所在的位置(which 是专门用来查找命令所在位置的)。

2) 第二种执行方式是将 Shell 脚本文件作为参数传递给 Bash 解释器,也可以理解为直接运行 Bash 解释器,将脚本文件作为参数传递给 Bash 解释器,具体操作如下:
[root@noylinux opt]# ll
-rwxr-xr-x. 1 root root 32 11 月 7 17:03 hello.sh
[root@noylinux opt]# chmod -x hello.sh #先将之前赋予的执行权限去掉
[root@noylinux opt]# ll
-rw-r--r--. 1 root root 32 11 月 7 17:03 hello.sh
[root@noylinux opt]# /bin/bash hello.sh #执行脚本
Hello World!
[root@noylinux opt]# bash hello.sh #简洁的写法
Hello World!
[root@noylinux opt]# ./hello.sh #再用第一种方式执行,看一下结果
-bash: ./hello.sh:权限不够
通过这种执行方式运行脚本,不需要在脚本文件的第一行指定解释器信息,也不需要赋予执行权限,但是笔者建议写上,虽然可能不太经常用到,但是不用等到用到时再写,编程一定要养成良好的习惯,方便的是我们自己。

这两种方式在本质上其实是一样的:第一种是通过脚本文件中指定好的 Bash 解释器(#!/bin/bash)来运行,第二种则是通过 Bash 命令找到 Bash 解释器所在的位置,让Bash解释器运行并将脚本文件作为参数传递进去,两者之间其实就是多了一个查找的过程而已。

接下来看第二种脚本执行类型:在当前进程中运行脚本,这里需要引入一个新的命令——source 命令。

source 命令是 Shell 的内置命令,它会读取脚本文件中的代码,并依次执行所有语句。可以理解为 source 命令会强制执行脚本文件中的全部命令,而忽略脚本文件本身的权限。

source 命令的语法格式为:
source 脚本名称
或者简写为:
. 脚本名称

【实例】使用 source 命令运行 hello.sh 脚本文件。
[root@noylinux opt]# ll
-rw-r--r--. 1 root root 32 11 月 7 17:03 hello.sh
[root@noylinux opt]# source hello.sh #第一种
Hello World!
[root@noylinux opt]# . hello.sh #第二种
Hello World!
使用 source 命令不用给脚本文件赋予执行权限,相比较而言会方便一些。

我们把上述两种类型称为“在新进程中运行脚本”和“在当前进程中运行脚本”,那如何知道当前进程到底是在“新进程中运行”还是在“当前进程中运行”呢?

接下来就带大家学习一下如何检测 Shell 脚本运行时是在当前进程中还是在新进程中。

在 Linux 操作系统中,每一个进程都有一个唯一的 ID 号,称为 PID。上文介绍过,使用“$$”变量就可以获取当前进程的 PID。“$$”是 Shell 中的特殊变量,这里大家先熟悉如何使用即可。

查看 Shell 脚本运行状态的步骤如下:
1) 修改 hello.sh 脚本。
[root@noylinux opt]# vim hello.sh
#!/bin/bash
echo "Hello World!"
echo "当前的 PID 为:[$$]"

2) 通过两种脚本执行类型分别运行,看看到底有没有区别?
[root@noylinux opt]# chmod +x hello.sh #赋予执行权限
[root@noylinux opt]# ll
-rwxr-xr-x. 1 root root 62 11 月 7 18:27 hello.sh
[root@noylinux opt]# echo $$ #当前 Shell 终端的 P1D
2835
[root@noylinux opt]# source hello.sh #在当前进程中运行 Shell 脚本方式一
Hello World!
当前的PID为:[2835]
[root@noylinux opt]# .hello.sh #在当前进程中运行Shell脚本方式二
Hello World!
当前的PID为:[2835]
[root@noylinux opt]# ./hello.sh #在新进程中运行 Shell 脚本方式一
Hello World!
当前的PTD为:[4873]
[root@noylinux opt]# bash hello.sh #在新进程中运行 Shell 脚本方式二
Hello World!
当前的PTD为:[4884]
可以明显看到,在当前进程中运行 Shell 脚本所获取到的进程 ID 号与当前 Shell 终端的 PID 相同,而在新进程中运行 Shell 脚本所获取到的进程 ID 号与当前 Shell 终端的 PID 不同。

推荐阅读

副业交流群 关注微信公众号,加入副业交流群,学习变现经验,交流各种打法。