shell脚本的三种元素

● 第一行的脚本声明(#!):指定解释此脚本文件的 Shell 程序;
● 第二行的注释信息(#):对脚本功能和某些命令的介绍信息;
● 第三行的可执行语句:执行的Linux命令。

[root@kylin ~]# vim hello.sh#!/bin/bash#Example of printing "hello world!"echo "Hello World!"

运行脚本的两种方法

● 作为可执行程序

[root@kylin ~]# chmod +x ./hello.sh  #使脚本具有执行权限[root@kylin ~]# ./hello.sh  #执行脚本

● 作为解释器参数

[root@kylin ~]# /bin/bash hello.sh[root@kylin ~]# /bin/sh hello.sh

变量

使用变量

● 变量外的花括号加不加都能正常引用变量,但推荐所有变量都加上{},帮助解释器识别变量的边界,养成好的编程习惯。

[root@kylin ~]# vim company.sh#!/bin/bash#Examples of using variablescompany="kylin"echo $companyecho ${company} 

删除变量

● 使用unset删除变量,变量删除后不能再次使用。以下实例执行后无输出:

[root@kylin ~]# vim unset.sh#!/bin/bash#Example of deleting variablesmyUrl="https://www.kylinos.cn"unset myUrlecho $myUrl

传递参数

● shell脚本内设了接受参数的变量,传递参数时使用空格间隔。常用传参变量如下表:
变量含义
$0当前Shell脚本程序的名称
$#总共有几个参数
$*所有位置的参数值
$?显示上一次命令的执行返回值
$1、$2、$3分别对应着第N个位置的参数值

● 以下实例在运行脚本时,向脚本传递5个参数,在脚本中调用参数:

[root@kylin ~]# vim para.sh#!/bin/bash#Example of passing parametersecho "当前脚本名称为$0"echo "总共有$#个参数,分别是$*。"echo "第1个参数为$1,第5个为$5。"[root@kylin ~]# bash para.sh one two three four five six

给脚本添加执行权限,执行结果如下:

[root@kylin ~]# chmod +x para.sh[root@kylin ~]# ./para.sh

当前脚本名称为para.sh
总共有6个参数,分别是one two three four five six
第1个参数为one,第5个为five

运算符

文件测试运算符

判断文件是否存在或权限是否满足等,常用的参数列表如下:
操作符说明
-d测试文件是否为目录类型,如果是,则返回true
-e检查文件(包括目录)是否存在,如果是,则返回true
-f测试是否为一般文件(既不是目录,也不是设备文件),如果是,则返回true
-r测试当前用户是否有权限读取,如果有,则返回true
-w测试当前用户是否有权限写入,如果有,则返回true
-x测试当前用户是否有权限执行,如果有,则返回true

● 实例:判断/etc/fstab是否为目录类型的文件:返回值为非零值,代表它不是目录,或这个目录不存在

[root@kylin ~]# vim file.sh#!/bin/bashfile="/etc/fstab"if [ -d $file ]then   echo "文件$file是一个目录"else   echo "文件$file不是一个目录或不存在"fi

执行脚本,输出结果如下:
文件/etc/fstab不是一个目录或不存在

逻辑运算符

运算符含义
&&逻辑"与" && 前面的命令执行成功后才会执行它后面的命令
||逻辑"或" || 前面的命令执行失败后才会执行它后面的命令
!逻辑"非" 把条件测试中的判断结果取相反值,之前是正确则变错误,错误则变正确

● 实例1:判断/dev/cdrom文件是否存在,若存在则输出Exist字样

[root@kylin ~]# [ -e /dev/cdrom ] && echo "Exist"Exist

● 实例2:使用环境变量USER,判断当前用户是否为非管理员身份

[root@kylin ~]# echo $USERroot[root@kylin ~]# [ $USER = root ] || echo "user"[root@kylin ~]# su - test [test@kylin ~]$ [ $USER = root ] || echo "user"user

● 实例3:判断当前登录的用户是否为非管理员用户,若条件成立则输出user字样,条件不满足则输出root字样

[root@kylin ~]# [ ! $USER = root ] && echo "user" || echo "root"root
整数比较运算符(关系运算符)
只支持对数字的操作,不能将数字与字符串、文件等内容一起操作。可用的整数比较运算符如表所示:
操作符作用
-eq是否等于
-ne是否不等于
-gt是否大于
-lt是否小于
-le是否等于或小于
-ge是否大于或等于

● 实例1:判断当前剩余内存大小是否小于1024,若小于则提示"Insufficient Memory",否则提示"Sufficient Memory"(使用free -m命令查看内存使用量情况(单位为MB),通过grep Mem:命令过滤出剩余内存量的行,再用awk {print $4}命令只保留第四列,即可得到剩余内存大小)

[root@kylin ~]# vim mem.sh#!/bin/bashFreeMem=`free -m | grep Mem: | awk {print $4}`[ $FreeMem -lt 1024 ] && echo "Insufficient Memory" || echo "Sufficient Memory"[root@kylin ~]# [root@kylin ~]# chmod +x mem.sh[root@kylin ~]# ./mem.shSufficient Memory

字符串运算符

判断字符串是否为空值,或两个字符串是否相同,可用来判断某个变量是否被定义(即内容为空值)。字符串比较中常见的运算符如表所示:
操作符作用
=比较字符串内容是否相同
!=比较字符串内容是否不同
-z判断字符串内容是否为空

● 实例1:通过判断String变量是否为空值,进而判断是否定义了该变量,返回值为0,则未定义该变量

[root@kylin ~]# [ -z $String ][root@kylin ~]# echo $?0

● 实例2:判断当前语言环境变量值LANG是否为非英文(en.US),若是,则输出"Not en.US"字样

[root@kylin ~]# echo $LANG[root@kylin ~]# [ ! $LANG = "en.US" ] && echo "Not en.US"

流程控制

if条件测试语句

单分支结构:if then fi

● 实例1:适用于终端命令提示符的写法,如果10等于10,那么输出"true"

[root@kylin ~]# if [ 10 -eq 10 ]; then echo "true"; fitrue

● 实例2:判断/media/cdrom目录是否存在,若不存在就创建这个目录,反之则结束条件判断和整个Shell脚本

[root@kylin ~]# vim mkcdrom.sh#!/bin/bashDIR="/media/cdrom"if [ ! -d $DIR ]then            mkdir -p $DIRfi 

验证/media/cdrom目录是否已经成功创建:

[root@kylin ~]# bash mkcdrom.sh[root@kylin ~]# ls -ld /media/cdromdrwxr-xr-x. 2 root root 6 Oct 13 21:34 /media/cdrom

双分支结构:if then else fi

● 实例1:验证某台主机是否在线。返回值若为0,显示主机在线信息,否则显示主机不在线信息。(使用ping命令来测试与对方主机的网络联通性,-c参数来规定尝试的次数,-i参数定义每个数据包的发送间隔,-W参数定义等待超时时间。)

[root@kylin ~]# vim chkhost.sh#!/bin/bashping -c 3 -i 0.2 -W 3 $1 &> /dev/nullif [ $? -eq 0 ]then        echo "Host $1 is On-line."else        echo "Host $1 is Off-line."fi

验证脚本的效果:

[root@kylin ~]# bash chkhost.sh 10.1.160.183Host 10.1.160.183 is On-line.[root@kylin ~]# bash chkhost.sh 10.1.160.184Host 10.1.160.184 is Off-line.

多分支结构:if then elif then else fi

● 实例1:判断用户输入的分数在哪个成绩区间内,输出Excellent、Pass、Fail等提示信息。(read用来读取用户输入的信息,把接收到的用户输入信息赋值给后面的指定变量,-p参数给予用户一些提示信息。)
用户输入的分数(GRADE)输出信息
85≤GRADE≤100Excellent
70≤GRADE≤84Pass
othersFail
[root@kylin ~]# vim chkscore.sh#!/bin/bashread -p "Enter your score(0-100):" GRADEif [ $GRADE -ge 85 ] && [ $GRADE -le 100 ] ; then        echo "$GRADE is Excellent"elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ] ; then        echo "$GRADE is Pass"else        echo "$GRADE is Fail" fi[root@linuxprobe ~]# bash chkscore.shEnter your score(0-100):8888 is Excellent[root@linuxprobe ~]# bash chkscore.sh Enter your score(0-100):8080 is Pass

for条件循环语句

● 实例1:批量创建用户
创建用户名列表文件,一行一个用户名:

[root@kylin ~]# vim users.txttest1test2test3test4test5test6

使用read命令读取用户输入的密码值,赋值给PASSWD变量,通过-p参数向用户显示一段提示信息,告诉用户正在输入的内容即将作为账户密码。在执行该脚本后,会自动使用从列表文件users.txt中获取到所有的用户名称,然后逐一使用“id 用户名”命令查看用户的信息,并使用$?判断这条命令是否执行成功,也就是判断该用户是否已经存在。

[root@kylin ~]# vim addusers.sh#!/bin/bashread -p "Enter The Users Password : " PASSWDfor UNAME in `cat users.txt`do        id $UNAME &> /dev/null        if [ $? -eq 0 ]        then                echo "$UNAME , Already exists"        else                useradd $UNAME &> /dev/null                echo "$PASSWD" | passwd --stdin $UNAME &> /dev/null                echo "$UNAME , Create success"        fidone

运行脚本,并检查是否创建成功

[root@kylin ~]# bash addusers.shEnter The Users Password : linuxprobetest1 , Create successtest2 , Create successtest3 , Create successtest4 , Create successtest5 , Create successtest6 , Create success[root@kylin ~]# tail -6 /etc/passwd

while条件循环语句

● 实例1:猜测数值大小
使用$RANDOM变量调取一个随机数(范围为0~32767),将这个随机数对1000进行取余操作,并使用expr命令取得其结果,再用这个数值与用户通过read命令输入的数值进行比较判断。

判断语句分为三种情况,分别是判断用户输入的数值是等于、大于还是小于使用expr命令取得的数值。

while条件循环语句中的条件测试始终为true,因此判断语句会无限执行下去,直到用户输入的数值等于expr命令取得的数值后,运行exit 0命令,终止脚本的执行。

[root@kylin ~]# vim Guess.sh#!/bin/bashPRICE=$(expr $RANDOM % 1000)TIMES=0echo "商品实际价格为0-999之间,猜猜看是多少?"while truedo        read -p "请输入您猜测的价格数目:" INT        let TIMES++        if [ $INT -eq $PRICE ] ; then                echo "恭喜您答对了,实际价格是 $PRICE"                echo "您总共猜测了 $TIMES 次"                exit        elif [ $INT -gt $PRICE ] ; then                echo "太高了!"        else                echo "太低了!"        fidone

运行脚本:

[root@kylin ~]# bash Guess.sh商品实际价格为0-999之间,猜猜看是多少?请输入您猜测的价格数目:500太低了!请输入您猜测的价格数目:800太高了!请输入您猜测的价格数目:650太低了!请输入您猜测的价格数目:720太高了!请输入您猜测的价格数目:690太低了!请输入您猜测的价格数目:700太高了!请输入您猜测的价格数目:695太高了!请输入您猜测的价格数目:692太高了!请输入您猜测的价格数目:691恭喜您答对了,实际价格是 691您总共猜测了 9 次

case条件测试语句

case语句在多个范围内匹配数据,若匹配成功则执行相关命令并结束整个条件测试;如果数据不在所列出的范围内,则去执行星号(*)中所定义的默认命令。

● 实例1:判断用户输入内容的类型
提示用户输入一个字符并将其赋值给变量KEY,根据变量KEY的值向用户显示其值是字母、数字还是其他字符。

[root@kylin ~]# vim Checkkeys.sh#!/bin/bashread -p "请输入一个字符,并按Enter键确认:" KEYcase "$KEY" in        [a-z]|[A-Z])                echo "您输入的是 字母。"                ;;        [0-9])                echo "您输入的是 数字。"                ;;        *)                echo "您输入的是 空格、功能键或其他控制字符。"esac[root@linuxprobe ~]# bash Checkkeys.sh请输入一个字符,并按Enter键确认:6您输入的是 数字。[root@linuxprobe ~]# bash Checkkeys.sh请输入一个字符,并按Enter键确认:p您输入的是 字母。[root@linuxprobe ~]# bash Checkkeys.sh请输入一个字符,并按Enter键确认:^[[15~您输入的是 空格、功能键或其他控制字符。