4.3 Linux Shell 脚本

目录

编写简单的脚本 

接收用户的参数

判断用户的参数

可以将 Shell 终端解释器当作人与计算机硬件之间的“翻译官”,它作为用户与 Linux 系统内部的通信媒介,除了能够支持各种变量与参数外,还提供了诸如循环、分支等高级编程语言才有的控制结构特性。要想正确使用 Shell 中的这些功能特性,准确下达命令尤为重要。Shell 脚本命令的工作方式有两种:交互式和批处理。

  • 交互式(Interactive):用户每输入一条命令就立即执行。
  • 批处理(Batch):由用户事先编写好一个完整的 Shell 脚本,Shell 会一次性执行脚本中诸多的命令。
Shell 脚本中不仅会用到很多 Linux 命令以及正则表达式、管道符、数据流重定向等语法规则,还需要把内部功能模块化后通过逻辑语句进行处理,最终形成日常所见的 Shell 脚本。

查看 SHELL 变量可以发现当前系统已经默认使用 Bash 作为命令行终端解释器了:

[root@localhost ~]# echo $SHELL
/bin/bash

编写简单的脚本 

        上文指的是一个高级 Shell 脚本的编写原则,其实使用 Vim 编辑器把 Linux 命令按照顺序依次写入到一个文件中,这就是一个简单的脚本了。例如,如果想查看当前所在工作路径并列出当前目录下所有的文件及属性信息,实现这个功能的脚本应该类似于下面这样:(为了避免被误以为是普通文件,建议将.sh 后缀加上)

[root@localhost ~]# cat example.sh
#!/bin/bash        #第一行的脚本声明(#!)用来告诉系统使用哪种 Shell 解释器来执行该脚本;
#For Example BY Linux    #第二行的注释信息(#)是对脚本功能和某些命令的介绍信息;
pwd
ls -al

[root@localhost ~]# bash example.sh    #运行脚本
/root
total 64
dr-xr-x---. 14 root root 4096 Aug 11 22:44 .
drwxr-xr-x. 17 root root 4096 Aug 12  2021 ..
-rw-------.  1 root root 1039 Aug  9 09:54 anaconda-ks.cfg
-rw-r--r--.  1 root root   18 Dec 28  2013 .bash_logout
-rw-r--r--.  1 root root  176 Dec 28  2013 .bash_profile

 除了上面用 bash 解释器命令直接运行 Shell 脚本文件外,第二种运行脚本程序的方法是通过输入完整路径的方式来执行。但默认会因为权限不足而提示报错信息,此时只需要为脚本文件增加执行权限即可

[root@localhost ~]# ./example.sh    #默认没有可执行权限
-bash: ./example.sh: Permission denied
[root@localhost ~]# chmod u+x example.sh    #给予脚本可执行权限
[root@localhost ~]# ./example.sh
/root
total 64
dr-xr-x---. 14 root root 4096 Aug 11 22:44 .
drwxr-xr-x. 17 root root 4096 Aug 12  2021 ..
-rw-------.  1 root root 1039 Aug  9 09:54 anaconda-ks.cfg
-rw-r--r--.  1 root root   18 Dec 28  2013 .bash_logout

接收用户的参数

        像上面这样的脚本程序只能执行一些预先定义好的功能,未免太过死板了。为了让 Shell 脚本程序更好地满足用户的一些实时需求,以便灵活完成工作,必须要让脚本程序能够像之前执行命令时那样,接收用户输入的参数。

Linux 系统中的 Shell 脚本语言早就考虑到了这些,已经内设了用于接收参数的变量,变量之间可以使用空格间隔。例如$0 对应的是当前 Shell 脚本程序的名称,$#对应的是总共 有几个参数,$*对应的是所有位置的参数值,$?对应的是显示上一次命令的执行返回值,而$1、$2、$3……则分别对应着第 N 个位置的参数值。

 尝试编写一个脚本程序示例,通过引用上面的变量参数来看下真实效果:

[root@localhost ~]# cat 1.sh
#!/bin/bash
echo “当前脚本名称为$0”
echo "总共有$#个参数,分别是$*"
echo "第一个参数为$1,第5个参数为$5"
[root@localhost ~]# bash 1.sh one two three four five six
“当前脚本名称为1.sh”
总共有6个参数,分别是one two three four five six
第一个参数为one,第5个参数为five

判断用户的参数

        系统在执行 mkdir 命令时会判断用户输入的信息,即判断用户指定的文件夹名称是否已经存在,如果存在则提示报错;反之则自动创建。Shell 脚本中的条件测试语法可以判断表达式是否成立,若条件成立则返回数字 0,否则便返回其他随机数值。条件测试语法的执行格式如图 4-16 所示。切记,条件表达式两边均应有一个空格。

 按照测试对象来划分,条件测试语句可以分为 4 种:

  • 文件测试语句;
  • 逻辑测试语句;
  • 整数值比较语句;
  • 字符串比较语句。

 

下面使用文件测试语句来判断 /etc/fstab 是否为一个目录类型的文件,然后通过 Shell 解释器的内设$? 变量显示上一条命令执行后的返回值。如果返回 值为 0,则目录存在 ;如果返回值为非零的值,则意味着目录不存在:
[root@localhost ~]# [ -d /etc/fstab ]
[root@localhost ~]# echo $?
1
再使用文件测试语句来判断 /etc/fstab 是否为一般文件,如果返回 值为 0,则代表文件存在 ,且为一般文件:
[root@localhost ~]# [ -f /etc/fstab ]
[root@localhost ~]# echo $?
0

逻辑语句用于对测试结果进行逻辑分析,根据测试结果可实现不同的效果。例如在Shell终端中逻辑“与”的运算符号是&&,表示当前面的命令执行成功后才会执行它后面的命令,因此可以用来判断/dev/cdrom 文件是否存在,若存在则输出 yes 字样。

[root@localhost ~]# [ -e /dev/cdrom ] && echo "yes"
yes

除了逻辑“与”外还有逻辑“或”,它在 Linux 系统中的运算符号为||,表示当前面的命令执行失败后才会执行它后面的命令,因此可以用来结合系统环境变量 USER 来判断当前登录的用户是否为非管理员身份:

[root@localhost ~]# echo $USER
root
[root@localhost ~]# [ $USER = root ] || echo "user"
[root@localhost ~]# su zhangxu
[zhangxu@localhost root]$ [ $USER = root ] || echo "user"
user
第三种逻辑语句是“非”,在 Linux 系统中的运算符号是一个叹号( !) 它表示把条件测试中的判断结果取相反值。 也就是说,如果原本测试的结果是正确的,则将其变成错误的;原本测试错误的结果则将其变成正确的。现在切换到一个普通用户的身份,再判断当前用户是否为一个非管理员的用户。由于判断结果因为两次否定而变成正确,因此会正常地输出预设信息:
[zhangxu@localhost root]$ exit
exit
[root@localhost ~]# [ ! $USER = root ] || echo "administrator"
administrator

 当前我们正在登录的即为管理员用户—root。下面这个示例的执行顺序是,先判断当前登录用户的 USER 变量名称是否等于 root,然后用逻辑运算符“非”进行取反操作,效果就变成了判断当前登录的用户是否为非管理员用户了。最后若条件成立则会根据逻辑“与”运算符输出 user 字样;或条件不满足则会通过逻辑“或”运算符输出 root 字样,而如果前面的&&不成立才会执行后面的||符号。

[root@localhost ~]# [ ! $USER = root ]  && echo "user" || echo "root"
root
整数比较运算符仅是对数字的操作,不能将数字与字符串、文件等内容一起操作,而且不能想当然地使用日常生活中的等号、大于号、小于号等来判断。因为等号与赋值命令符冲突,大于号和小于号分别与输出重定向命令符和输入重定向命令符冲突。因此一定要使用规范的整数比较运算符来进行操作。可用的整数比较运算符如下表。

 先测试一下 10 是否大于 10 以及 10 是否等于 10(通过输出的返回值内容来判断):

[root@localhost ~]# [ 10 -gt 10 ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# [ 10 -eq 10 ]
[root@localhost ~]# echo $?
0
经讲过 free 命令,它可以用来获取当前系统正在使用及可用的内存量信息。接下来先使用 free -m 命令查看内存使用量情况(单位为 MB ),然后通过 grep Mem: 命令过滤出剩余内存量的行,再用 awk '{print $4}' 命令只保留第四列,最后用 FreeMem=` 语句 `的方式把语句内执行的结果赋值给变量。
[root@localhost ~]# free -m
             total       used       free     shared    buffers     cached
Mem:          1826       1157        669         10          1        500
-/+ buffers/cache:        655       1171
Swap:         2063          0       2063
[root@localhost ~]# free -m | grep Mem
Mem:          1826       1157        669         10          1        500
[root@localhost ~]# free -m | grep Mem: | awk '{print $4}'
669
[root@localhost ~]# FreeMem=`free -m | grep Mem: | awk '{print $4}'`
[root@localhost ~]# echo $?
0
[root@localhost ~]# echo $Freemem

[root@localhost ~]# echo $FreeMem
668
接下来使用整数运算符来判断内存可用量的值是否小于 1024 ,若小于则会提示“Insufficient Memory ”(内存不足)的字样:
[root@localhost ~]# [ $FreeMem -lt 1024 ]  && echo "Insufficient Memory"
Insufficient Memory

字符串比较语句用于判断测试字符串是否为空值,或两个字符串是否相同。它经常用来判断某个变量是否未被定义(即内容为空值),理解起来也比较简单。字符串比较中常见的运算符如表所示。

 接下来通过判断 String 变量是否为空值,进而判断是否定义了这个变量:

[root@localhost ~]# [ -z $String ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ -z $FreeMem ]
[root@localhost ~]# echo $?
1

再尝试引入逻辑运算符来试一下。当用于保存当前语系的环境变量值 LANG 不是英语(en.US)时,则会满足逻辑测试条件并输出“Not en.US”(非英语)的字样:

[root@localhost ~]# echo $LANG
en_US.UTF-8
[root@localhost ~]# [ $LANG != "en.US" ] && echo "Not en.US"
Not en.US

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值