shell脚本二

本文发布时间: 2019-Mar-22
在shell脚本一中,我讨论了shell脚本的语法规范,shell脚本的变量,以及shell脚本的测试语句。仅仅懂得这些只能写简单的脚本,在简单的脚本中各条语句按顺序执行,从而实现自动化的管理,顺序单一执行太过机械化,不够“智能”,难以实现更加灵活的系统任务。甚至一个简单的场景:现有100台linux服务器,其中有50台安装过某软件,有50台没有安装过某软件。如果没有流程控制及循环方面的脚本知识,如此简单的问题,也变得非常低效。所以本文带你走进shell脚本的流程控制及循环的世界。一、多重条件判定1、逻辑测试  逻辑测试指的是判断两个或多个条件之间的依赖关系,当系统取决于多个条件时,根据这些条件或其中的一个条件成立等情况来判断系统是否执行或有效。常用的逻辑测试&&:逻辑与,“并且而且”的意思 满足两个条件||:逻辑或,“或者”的意思 满足两个条件中的一个! 逻辑否逻辑与 “&&” 是指并且而且的意思,只有前后两个条件都成立时才会返回值为0(成立)否则就是非0(不成立)使用test进行测试的时候可以改成-a逻辑或 “||” 只要前后两个条件有一个成立时,则整个侧示命令的返回值即为0使用test进行测试可以写成 -o 但是在rhel的系统中不支持逻辑非 “!” 表示不,只有当条件不成立时返回值才会为0否则为非0逻辑与和逻辑或通常也用于间隔不同的命令操作补充:1. 格式:test 测试条件注意:在使用'['简写test时,左中括号后面的空格和右括号前面的空格是必需的,如果没有空格,Shell不可能辨别表达式何时开始何时结束.2. 测试范围: 整数,字符串,文件a.文件状态的检测 (测试时变量应加双引号)test -e: 目标是否存在(exist)test -d: 是否为目录(directory)test -f: 是否为文件(file)test -x: 文件存在并且可执行test -r file: 文件存在并且可读test -w file: 文件存在并且可写test -s file 测试大小是为空。是否为空文件test File1 –ef File2 两个文件具有同样的设备号和i结点号test File1 –nt File2 文件1比文件2 新test File1 –ot File2 文件1比文件2 旧test –b File 文件存在并且是块设备文件test –c File 文件存在并且是字符设备文件test –f File 文件存在并且是正规文件test –g File 文件存在并且是设置了组IDtest –G File 文件存在并且属于有效组IDtest –h File 文件存在并且是一个符号链接(同-L)test –k File 文件存在并且设置了sticky位test –b File 文件存在并且是块设备文件test –L File 文件存在并且是一个符号链接(同-h)test –o File 文件存在并且属于有效用户IDtest –p File 文件存在并且是一个命名管道test –t FD 文件描述符是在一个终端打开的test –u File 文件存在并且设置了它的set-user-id位b. 权限的检测test -r:是否有读取(read)权限test -w:是否有写入(write)权限 root对所有者w例外test -x:是否有可执行(excute)权限c. 整数值比较test -eq:等于(equal)test -ne:不等于(Not equal)test -gt:大于(greater than)test -lt:小于(lesser than)test -ge:大于或等于(greater or equal)test -le:小于或等于(lesser or equal)说明:也可以省略test 写成: [ int1 -lt int2 ]-eq == 等于(equal)-ne != 不等于(Not equal)-gt > 大于(greater than)-ge >= 大于或等于(greater or equal)-lt < 小于(lesser than)-le <= 小于或等于(lesser or equal)提示:“<”和“>””=”分别为小于 大于 等于,并且在[]中“<”“>”都要使用转义字符,在[[]]中不需要。d 字符串和变量test $str1 == $str2 是否相等test $str1!= $str2 是否不相等test $str1 如果$str1不为空,则返回结果为真test -n $str1 如果字符串长度为非零,则返回结果为真test -z $str1 如果字符串长度为零,则返回结果为真举例1:通过逻辑表达判断一下两个变量的值2、数值的比较 数值的比较指的是根据给定的两个整数判断第一个数值与第二个数值的关系 第一个数是否大于小于第二个数-eq:等于(Equal) Eq-ne:不等于(Not Equal)-gt:大于(Greater Than)-lt:小于(Lesser Than) -le:小于或等于(Lesser or Equal)-ge:大于或等于(Greater or Equal)格式 [ 数值1 操作符 数值2 ]实战:我们可以通过数值的比较来判断当前的登录用户数量3.字符串比较字符串比较通常用来检查用户输入、系统环境是否满足条件、在提供交互式操作的shell脚本中也可以判断用户输入位置参数是否符合要求,字符串的常用操作如下= 字符串内容相同!= 字符串内容不同-z 字符串内容为空实战1:若要判断当前系统的语言环境,当发现不是en.US时输出提示信息“$LANG”$LANG变量是定义当前系统的语言属于环境变量取反就是不等于的意思实战2:-z 判断一个变量的值是否为空二、if语句  if语句是循环语句中的一种又称为控制语句.通过制定条件进行判断执行; 只有条成立的时候才会执行相对应的代码,否则不会进行任何操作1.单分支if语句的格式if 条件测试操作then 命令序列fi单分支执行结构图:单分支的结构非常简单,条件成立就执行then命令序列,条件不成立则fi结束实战1:如果 /media/cdrom ,目录不存在则 创建这个目录then根据判断的结果是否执行如果返回值为0则执行then的命令序列如果不为0则直接结束[root@xiaolyu ~]# vim file.sh这就是单分支的应用比较简单。2.双分支IF语句 双分支的选择结果,要求针对条件成立,条件不成立两种情况分别执行不同的操作语法结构:if 条件测试操作then(条件成立执行) 命令序列1else(否则,条件不成立,则执行) 命令序列2fi双分支执行结构图:首先通过if进行条件测试。如果条件成立则执行命令序列1如果不成立则进行命令序列2之后fi结束判断实战1:我们编写一个连通性测试脚本通过位置参数$1提供目标主机地址,然后根据ping检测结果给出相应提示[root@xiaolyu ~]# vim pinghost.sh将网络关闭,再次执行该脚本:[root@xiaolyu ~]# systemctl stop network注释:-c ping包的次数-i ping包的间隔-w 超时的时间间隔脚本解释:如果if判断为0则接下来执行then输出目标主机up如果不为0则执行else输出目标主机down这就是双分支的优势 --- 成立执行成立的操作,不成立则执行不成立的操作;3-多分支if语句由于if语句可以根据测试结果的成立,不成立分别执行,所以可以嵌套使用,进行多次判断.多分支语法格式:if 条件测试操作1then 命令序列1elif 条件测试操作2then 命令序列2else 命令序列3fi多分支if语句的执行流程首先判断条件测试操作1的结果,如果条件1成立,则执行then命令序列1 ,然后跳转至fi结束判断.如果条件1不成立,则继续判断条件测试2的结果.如果条件序列2成立则执行命令序列2,然后跳至fi结束判断.如果所有的条件都不满足则执行else后面的命令序列3直到遇到fi结束其实多分支的if语句不是很常用,循环语句case这种语句更加简单方便。实战:1、编写脚本程序用于监视系统服务httpd的运行状态,要求如下当服务状态失败时在'/var/log/httpderr.log'文件中记入日志信息。自动将状态失败的httpd服务重新启动。若重启httpd服务失败,测尝试重新启动服务器主机[root@xiaolyu ~]# yum -y install httpd[root@xiaolyu ~]# vim monitorHttpd.sh#!/bin/bashsystemctl status httpdif  [ $? -eq 0 ]then  echo 'httpd server is running ' >>/dev/nullelif  [ $? -ne 0 ]then  echo ' httpd server running fail. Try to restart' >>/var/log/httpderr.log  systemctl restart httpdelse  echo ' server begin restart'  /sbin/shutdown -r nowfi2、编写uname.sh脚本判断当前系统的内核主版本若大于或等于3 ,则输出当前版本./否则输出提示当前版本太低.过滤主版本号uname -r | awk -F . '{print $1}'过滤出次版本号uname -r | awk -F . '{print $2}'显示主次版本号uname -r | awk -F . '{print $1 $2 }'vim kernel.sh#!/bin/bashprimary=$(uname -r | awk -F . '{print $1}')if[ $primary -ge 3 ]thenecho '$(uname -r | awk -F . '{print $1 $2 }')'else echo 'your kernel is to low!'fi三、for循环语句的结构使用for循环语句时,需要指定一个变量及可能的取值列表。跟对不同的取值,执行相同的命令序列直到变量的值取完遍退出循环。取值列表称为for语句的执行条件for语句执行的语法结构for 变量名 in 取值列表do 命令序列donefor语句的执行流程 首先将列表的中的第一个值赋予变量,并执行do…done循环体中的命令序列,然后将取值列表中的第二个值赋予变量…列表中的所…一次类推知道有值取完,然后跳到done结束循环为了进一步理解for语句的结构和流程,掌握for语句在脚本中的实际应用,实战1: 批量添加用户有些时候我们的系统需要多个用户的时候,并且用员工姓名的拼音为用户名。这时也可以使用for循环进行创建并设置初始密码,批量创建用户。1.先将要创建的用户保存到一个文件中。vim users.txt查看创建成功的用户2.编辑一个脚本,添加用户:vim adduser.sh首先定义一个变量作为取值列表将取值列表赋予变量user嵌套一个if语句判断用户是否存在,如果存在则输出用户已存在,否则执行else的命令序列进行添加用户并且设置密码实现取值循环代码如下:#!/bin/bashuserlist=$(cat /root/user.txt)for user in $userlistdouseradd $user > /dev/null 2>&1if[ $? -eq 0 ]thenecho '123456' | passwd --stdin $userecho 'user $user has added successfully ---!'elseecho 'the user $user has already exists'fidone执行该脚本: . useradd.sh查看新添加的用户:再次执行该脚本 . useradd.sh若要删除刚刚创建的用户可以编写脚本vim userdel.sh执行删除用户的脚本: . userdel.sh实战2:根据ip地址列表检测主机状态建立一个ip地址取值列表vim ip.txt将前面的pinghost.sh的脚本改造成for循环的形式如下:这就是简单的for循环语句的应用。


(以上内容不代表本站观点。)
---------------------------------
本网站以及域名有仲裁协议。
本網站以及域名有仲裁協議。

2024-Mar-04 02:08pm
栏目列表