第一个 Shell 程序

1. Shell 脚本的构成及规范

Shell 脚本有一些约定俗成的规范,大家都遵循这些规则,编写出来的脚本更能被大家接受,Shell 脚本其实不能称为一门编程语言,它更像是一个工具,用来杂糅不同的程序及命令供我们调用来完成自己的预期操作。

1.1 命名规范

  • Shell 脚本在命名方面没有严格的要求,但是我们命名需要遵循见名知意,即可通过 Shell 脚本的名称知道其功能;
  • 文件名约定俗成以 .sh 结尾,方便识别其为 Shell 脚本文件;
  • 文件统一命名风格,写 Shell 一般用小写字母加下划线,例如 install_mysql.sh, 我们看到该名称就能知道其为一个安装 mysql 的脚本文件。

1.2 Shell 脚本结构

Shell 脚本在其中的第一行需要有指明解释器,在上面 CLI Shell 中的那些解释器,都可以写,在以./install_mysql.sh 的时候,此时就是利用脚本中第一行的解释器来运行脚本,其格式为
#!Shell解释器,例如#!/bin/bash, 但是这种方式存在一定的局限性,我们推荐使用 env 环境变量中的 bash,推荐使用这种方式#!/usr/bin/env bash

1.3 编码统一

在编写 Shell 的时候我们尽可能使用 UTF-8 编码,可以支持中文及大多数符号,在其中我们注释使用英文,例如在不支持中文的服务器上,脚本更好的支持。

1.4 作者信息

在编写 Shell 脚本的时候,我们应该尽可能地指定 Shell 的描述信息,以及该脚本的作者,编写该脚本的日期及联系方式,以及脚本的版本,方便后期其他人阅读及联系。
例如在头部添加如下注释信息:

#!/bin/env bash
# Description: /mybin/myvim scripts
# Auth: kaliarch
# Email: kaliarch@163.com
# Date: 2020-02-15 13:36
# Version: 1.0

2. Shell 的运行方式

运行脚本可以归纳为三种方式,注意一般在运行脚本的时候为脚本添加 x 可执行权限

2.1 显式指定解释器执行

[root@shell workspace]# ll
total 4
-rw-r--r-- 1 root root 44 Sep  3 14:16 01-scripts.sh
[root@shell workspace]# cat 01-scripts.sh 
#!/bin/env bash
# Description: /mybin/myvim scripts
# Auth: kaliarch
# Email: kaliarch@163.com
# Date: 2020-02-15 13:36
# Version: 1.0

echo "this is my first script"
cd /
[root@shell workspace]# bash 01-scripts.sh 
this is my first script

在当前 bash 环境下,当前终端登录的 Shell 为父 Shell,此种方式为在当前 Shell 下再启动一个子进程来运行 Shell 脚本。

Tips: 此方法直接在终端指定解释器来执行脚本,此时的解释器为终端指定的,不使用脚本内第一行指定的解释器执行,直接指定解释器,此时不需要为脚本添加可执行权限。

2.2 直接指定脚本文件名称

[root@shell workspace]# ll
total 4
-rw-r--r-- 1 root root 44 Sep  3 14:16 01-scripts.sh
[root@shell workspace]# . ./01-scripts.sh
-bash: ./01-scripts.sh: Permission denied
[root@shell workspace]# chmod +x 01-scripts.sh 
[root@shell workspace]# ll
total 4
-rwxr-xr-x 1 root root 44 Sep  3 14:16 01-scripts.sh
[root@shell workspace]# . ./01-scripts.sh 
this is my first script
[root@shell workspace]# /workspace/01-scripts.sh 
this is my first script

利用直接在终端指定脚本文件名称方式执行,此种方式需要为脚本添加可执行权限,在当前 Shell 来执行,不启动子 Shell,利用此种方式执行脚本的解释器为脚本内的第一行指定的解释器,例如此例中为#!/bin/bash,利用. 命令来执行脚本,一般用在当前目录没有在 PATH 中,所以第二个./ 是用来表示当前目录的。

2.3 source 执行

[root@xuel-transfer workspace]# bash 01-scripts.sh
this is my first script
[root@xuel-transfer workspace]# ./01-scripts.sh
this is my first script
[root@xuel-transfer workspace]# source 01-scripts.sh
this is my first script
[root@xuel-transfer /]# pwd
/

利用此种方式也可执行脚本,此方式在当前上下文中执行脚本,不会生成新的子进程。脚本执行完毕,回到当前 Shell,脚本内如果有 cd 命令脚本退出后会影响当前的环境上下文,此种方式运行 Shell,脚本也可以没有可执行权限。

3. 调试

在我们执行 Shell 脚本的时候为了方便排除异常,我们可以利用 -x 来开启调试,例如

[root@xuel-transfer workspace]# bash -x 01-scripts.sh
+ echo 'this is my first script'
this is my first script
+ cd /

通过上面例子可以看出 + 后面为脚本的内容,没有 + 的为脚本执行的输出

同时我们为了方便查看脚本打印正在执行的命令,可以还可以利用 -v 参数。

4. 实例

4.1 第一个 Shell 需求

在此我们也不写 Hello Shell 了,举一个非常实用的例子,里面涉及的一些语法在后期的文章中大家都能学到,可以先按照操作步骤实现。
经过上面的学习,我们知道我们在写 Shell 脚本的时候最好写一些作者的信息,如果每次编写都手动添加一次就很麻烦,如果是 IDE 一般工具都可以自定义配置添加首部 banner,但是在 Linux 系统内部编写简单 Shell 或文本,我们可以自定义小工具来实现。

4.2 思路

我们可以修改新增一个脚本将其添加进 PATH 中,如果利用此命令打开已存在的文件,利用 vim 直接打开,不对原内容作出更改,如果之前文件未存在,就在文件首部自动添加 banner 并用 vim 打开。

4.3 实现

  • 创建文件
    首先创建个文件 myvim
  • 编写内容
#!/bin/env bash
# Description: /mybin/myvim scripts
# Auth: kaliarch
# Email: kaliarch@163.com
# function: auto generate banner
# Date: 2020-02-15 13:36
# Version: 1.0


# file not exist
[ $# -eq 0 ] && echo "$0 [file],At least one parameter!" && exit 1

# add banner
add_banner() {
cat > $1 << EOF
#!/bin/env bash
# Description: $0 scripts
# Auth: $USER
# Date: $(date +%F" "%H:%M)
# Version: 1.0
EOF
}

# exist file
for file in $*;
do
    if [ -f ${file} ];then
        vim ${file} && exit 0
    else
        touch ${file} && add_banner ${file} && vim ${file} && exit 0
    fi
done
  • 添加进 PATH 中
[root@devops-server mybin]# chmod +x myvim     # 添加可执行权限
[root@devops-server mybin]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@devops-server mybin]# echo "export PATH=\$PATH:/mybin" >> /etc/profile       # 将mybin添加进PATH中
[root@devops-server mybin]# source /etc/profile
[root@devops-server mybin]# echo $PATH
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/mybin

4.4 效果

利用 myvim 来编辑脚本可以自动生成 banner,再次打开可以继续编辑,这样就免去了我们每次手动编写 banner 的麻烦。有兴趣的同学可以进行尝试,是不是感觉 Shell 可以为我们带来无穷的乐趣。

5. 注意事项

  • 再次注意编写 Shell 需要遵守其规范,这些约定俗成的规则能在日后的生产环境中为我们避免很多不必要的坑;
  • 学习 Shell 需要多动手实践,实践出真理,多写勤练,针对结果多思考,熟练运用 man 指令来查看 Shell 脚本中常用的命令的参数及选项;
  • 举一反三,针对一个脚本如何能无状态,更健壮,更灵活易维护,需要多次的修改,反复的执行验证,针对不同的应用场景,将数据抽象为参数进行传递,可以达到是事半功倍的效果。

6. 经验分享

例如上面的我的第一个 Shell 脚本例子,再次只是抛砖引玉作用,我们还可以举一反三思考更多的用处,例如,可以获取天气,利用自制小工具来进行 Shell 下快速翻译等。

7. 小结

目前 Shell 的内容非常多,其作为用户和系统内核的桥梁,其功能强大不言而喻,我们需要将有限的精力放在热点知识上,好钢用在刀刃上,注意学习方法学会举一反三,这样在后期的 Shell 学习中能够更加地快速高效。