博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
老男孩shell实战读书笔记 (6-10章节)
阅读量:7209 次
发布时间:2019-06-29

本文共 10438 字,大约阅读时间需要 34 分钟。

老男孩shell教程 (6-10章节)

shell脚本的条件测试与比较

在bash编程中,条件测试常用的语法形式如下表:

老男孩shell实战读书笔记 (6-10章节)

说明⚠️:

  • 语法1中的test命令和语法2中的[]是等价的。
  • 语法3中的[[]]双中括号为扩展的test命令。
  • 语法4中的(())常用于计算。
  • 在双中括号[[]]中可以使用通配符等进行模式匹配,这是其区别于其他几种语法格式的地方。
  • &&、||、>、<等操作符可以应用于双中括号{[[]]中,但不能应用于单中括号[]中,在[]中一般用-a、-o、-gt(用于整数)、-lt(用于整数)代替上述操作符。
  • 对于整数的关系运算,也可以是使用shell的算术符(())。

条件测试简单语法与运用

test使用

test语法格式:test<测试表达式>

测试文件file是否存在,代码如下:

[root@wtf tmp]# test -s file.txt && echo "true" || echo "false"false[root@wtf tmp]# test -s seq.txt && echo "true" || echo "false"true

说明⚠️:

test命令若执行成功(为真),则执行 && 后面的命令,反之执行 || 后面的命令。

测试字符串的长度是否为0,代码如下:

[root@wtf tmp]# test -z "wutf" && echo "true" || echo "false"false[root@wtf tmp]# test -z " " && echo "true" || echo "false"false[root@wtf tmp]# test -z "" && echo "true" || echo "false"true

[](中括号)使用

语法格式:[ 条件测试表达式 ] ==>中括号两端要有空格

测试file文件是否存在,代码如下:

[root@wtf tmp]# [ -f file.txt ] && echo "true" || echo "false"false[root@wtf tmp]# [ -f seq.txt ] && echo "true" || echo "false"true

[[]](双中括号)使用 (了解即可)

语法格式:[[ 条件测试表达式 ]] ==>双中括号里的两端也要有空格

文件测试表达式

常用的文件测试操作符:

老男孩shell实战读书笔记 (6-10章节)

测试时变量的特殊写法及问题

用 [] 测试变量时,如果被测试的变量不加双引号,那么测试结果可能会是不正确的,如下:

[root@wtf tmp]# unset wutf[root@wtf tmp]# echo $wutf[root@wtf tmp]# [ -f $wutf ] && echo 1 || echo 0  ## $wutf是不存在的,应该返回值0,这就逻辑不对了。1[root@wtf tmp]# [ -f "$wutf" ] && echo 1 || echo 00

如果是文件实体路径,那么加引号与不加引号的结果是一样的:

[root@wtf tmp]# [ -f /etc/services ] && echo 1 || echo 01[root@wtf tmp]# [ -f "/etc/services" ] && echo 1 || echo 01

特殊条件测试表达式案例

以下写法适用于所有的条件测试表达式,是工作中比较常用的替代if语句的方法。

当条件1成立时,同时执行命令1、命令2、命令3,如下:

老男孩shell实战读书笔记 (6-10章节)

上面的判断,相当于下面的if语句的效果,如下:

老男孩shell实战读书笔记 (6-10章节)

字符串测试表达式

字符串测试操作符,如下:

老男孩shell实战读书笔记 (6-10章节)

整数二元比较操作符

整数二元比较操作符使用参考,如下:

老男孩shell实战读书笔记 (6-10章节)

针对上述符号的特殊说明⚠️:

  • “=”和“!=”也可以在[ ]中作比较使用,但在[ ] 中使用包含“>”和“<”的符号时,需要转义,有时不转义,虽然语法不会报错,但是结果可能不对。
  • 也可以在[[]]中使用包含“-gt”和“lt”的符号,但是不建议这样使用。
  • 比较符号两端也要有空格。

逻辑操作符

逻辑操作符介绍如下:

老男孩shell实战读书笔记 (6-10章节)

对于上述操作符,说明⚠️如下几点:

  • “&&”和“||”逻辑操作符号可用于[[]]和(())中,也可以在外部连接多个[]
  • 在[]和[[]]的两端,必须要有空格,但是对于(())不需要

测试表达式test、[]、[[]]、(())的区别总结

老男孩shell实战读书笔记 (6-10章节)

单分支 if 条件语句实践

Linux7版本:

#!/bin/bashFreeMem1=$(free -m|awk 'NR==2 {print $4}')FreeMem2=$(free -m|awk 'NR==2 {print $6}')FreeMem3=$(free -m|awk 'NR==2 {print $7}')# 系统剩余内存FreeMem=$(($FreeMem1+$FreeMem2+$FreeMem3))# 邮件正文内容CHARS="Current memory is $FreeMem"# 判断内存是否达到报警阀值if [ $FreeMem -lt 600 ];then    # 屏幕输出显示,并写入文件    echo $FreeMem|tee /tmp/message.txt    # 发送报警邮件    mail -s "$(date +%F-%T)$CHARS" 175xxxx3745@163.com < /tmp/message.txtfi

Linux6版本:

#!/bin/bash# 系统剩余内存FreeMem=$(free -m|awk 'NR==3 {print $NF}') # 等价于 $(free -m |awk 'NR==3 {print $4}')echo $FreeMem# 邮件正文内容CHARS="Current memory is $FreeMem"# 判断内存是否达到报警阀值if [ $FreeMem -lt 600 ];then    # 屏幕输出显示,并写入文件    echo $FreeMem|tee /tmp/message.txt    # 发送报警邮件    mail -s "$(date +%F-%T)$CHARS" 175xxxx3745@163.com < /tmp/message.txt fi

说明⚠️:

配置下系统mail,/etc/mail.rc,如下形式:

set from=175xxxx3745@163.com # 设置发件人信息,注:如果使用163邮箱,发件人信息必须设置和实际邮箱号一致,不然无法发送。set smtp=smtp.163.com # 设置邮件服务器set smtp-auth-user='175xxxx3745' # 设置验证用户名set smtp-auth-password='xxxxwtf'  # 设置验证密码set smtp-auth=login # 可忽略

多分支 if 条件语句实践

开发rsync服务的启动脚本

脚本要求和说明

老男孩shell实战读书笔记 (6-10章节)

rsync 基本信息

/etc/rsyncd.conf # rsync配置文件rsync --daemon #启动命令netstat -lnp|grep 873 #服务端口pkill rsync #停止rsync服务

说明⚠️:

老男孩shell实战读书笔记 (6-10章节)

rsync服务启动脚本

# cat rsync_test.sh#!/bin/bash# 判断输入的参数个数是否为1个if [ $# -ne 1 ];then    echo $"USAGE:$0 {start|stop|restart}"    exit 1fi# 对输入参数行为进行判断if [ "$1" = "start" ];then    rsync --daemon    sleep 2    if [ $(netstat -lnp|grep rsync|wc -l) -ge 1 ];then        echo "rsyncd is started"        exit 0    fielif [ "$1" = "stop" ];then    killall rsync &>/dev/null    sleep 2    if [ $(netstat -lnp|grep rsync|wc -l) -eq 0 ];then        echo "rsyncd is stopped"        exit 0    fielif [ "$1" = "restart" ];then    killall rsync    sleep 1    killpro=$(netstat -lnp|grep rsync|wc -l)    rsync --daemon    startpro=$(netstat -lnp|grep rsync|wc -l)    if [ $killpro -eq 0 -a $startpro -ge 1 ];then        echo "rsyncd is restart"        exit 0    fielse    echo $"USAGE:$0 {start|stop|restart}"    exit 1fi

脚本执行情况

[root@wtf tmp]# sh rsync_test.sh statusUSAGE:rsync_test.sh {start|stop|restart}[root@wtf tmp]# sh rsync_test.shUSAGE:rsync_test.sh {start|stop|restart}[root@wtf tmp]# sh rsync_test.sh stoprsyncd is stopped[root@wtf tmp]# sh rsync_test.sh startrsyncd is started[root@wtf tmp]# sh rsync_test.sh restartrsyncd is restart[root@wtf tmp]# netstat -lnp|grep 873tcp        0      0 0.0.0.0:873             0.0.0.0:*               LISTEN      10296/rsynctcp6       0      0 :::873                  :::*                    LISTEN      10296/rsync

Shell 函数知识和实践

Linux 系统别名

# alias network="systemctl status network"# network● network.service - LSB: Bring up/down networking   Loaded: loaded (/etc/rc.d/init.d/network; bad; vendor preset: disabled)   Active: active (exited) since 二 2018-10-23 11:16:46 CST; 3h 7min ago

Shell 函数基本实践

创建一个简单的函数

# cat function_test1.sh#!/bin/bash# 定义一个wutf函数wutf(){    echo "this is a test function"}#调用函数wutf

运行这个脚本

# sh function_test1.shthis is a test function

分离函数体和执行函数的脚本文件

首先建立函数库脚本:

# cat >>/etc/init.d/test<
#!/bin/bash> test(){> echo "this company name is datagrand"> }> EOF

赋予函数库文件的执行权限:

chmod 755 /etc/init.d/test

开发执行脚本以调用上述函数:

# cat function_test2.sh#!/bin/bash[ -f /etc/init.d/test ] && source /etc/init.d/test || exit 1# 调用函数test

执行函数:

# sh function_test2.shthis company name is datagrand

带参数的Shell函数

定义函数库文件:# cat /etc/init.d/test2#!/bin/bashdata(){    echo "this company name is $1"}执行脚本调用上面的函数:# cat function_test3.sh#!/bin/bash[ -f /etc/init.d/test2 ] && source /etc/init.d/test2 || exit 1# 调用函数test daguan执行脚本:# sh function_test3.shthis company name is daguan

使用位置参数的Shell函数

定义函数库文件:# cat /etc/init.d/test2#!/bin/bashdata(){    echo "this company name is $1"}执行脚本调用上面的函数:# cat function_test4.sh#!/bin/bash[ -f /etc/init.d/test2 ] && source /etc/init.d/test2 || exit 1# 调用函数test $1执行脚本:# sh function_test4.sh wutfthis company name is wutf

case 条件语句的应用实践

case 语句的应用

常被应用于实现系统服务启动脚本等企业应用场景中

case 条件语句的语法

case "变量" in    值1)        指令1        ;;    值2)        指令2        ;;    *)        指令3esac

老男孩shell实战读书笔记 (6-10章节)

中文形象表述:

老男孩shell实战读书笔记 (6-10章节)

case 条件语句的执行流程逻辑图:

老男孩shell实战读书笔记 (6-10章节)

case 条件语句与函数结合实践

代码如下:

# cat case_test2.sh#!/bin/bash#定义颜色变量RED_COLOR='\E[1;31m'GREEN_COLOR='\E[1;32m'YELLOW_COLOR='\E[1;33m'RES='\E[0m'#定义帮助信息函数function usage(){    echo "USAGE: $0 {1|2|3|4}"    exit 1}#定义菜单函数function menu(){    cat <

代码执行情况

[root@wtf tmp]# sh case_test2.sh    1.apple    2.pear    3.bananaPlease input your choice: 1apples                          #红色字体[root@wtf tmp]# sh case_test2.sh    1.apple    2.pear    3.bananaPlease input your choice: 2peer                            #绿色字体[root@wtf tmp]# sh case_test2.sh    1.apple    2.pear    3.bananaPlease input your choice: 3banana                          #×××字体[root@wtf tmp]# sh case_test2.sh    1.apple    2.pear    3.bananaPlease input your choice: 4USAGE: case_test2.sh {1|2|3|4}

case 生产环境实际运用

现在好多企业喜欢使用Svn,随着公司业务和人员的增加,运维人员需要对公司的svn平台有个比较直观的认识,如人员的增删,人员查询等。

下面的代码的作用是:一键添加、查找和查找人员信息

代码如下:

#!/bin/bash#create by wutf#加载系统函数库. /etc/init.d/functions#定义文件路径FILE_PATH="/tmp/passwd"[ ! -f $FILE_PATH ] && touch  $FILE_PATH#定义帮助函数function usage(){    echo "USAGE: $0 {-add|-del|-search} username"    exit 1}#定义判断执行账户函数function user(){    if [ $UID -ne 0 ];then        echo "you are not root"        exit 2    fi}#定义执行脚本参数的个数function arg_num(){    if [ $# -ne 2 ];then        usage        exit 3    fi}#定义case语句判断function case_info(){    case "$1" in        -a|-add)            shift            if grep "^$1" $FILE_PATH >/dev/null 2>&1                then                    action "svnuser $1 is exist" /bin/false                    exit 4            else                /bin/cp $FILE_PATH $FILE_PATH.$(date +%F%T)                htpasswd $FILE_PATH $1                [ $? -eq 0 ] && action "Add $1 is success" /bin/true            fi            ;;        -d|-del)            shift            if [ $(grep "$1" $FILE_PATH | wc -l) -lt 1 ];then                action "svnuser $1 is not exist" /bin/false                exit 5            else                /bin/cp $FILE_PATH $FILE_PATH.$(date +%F%T)                sed -i "/^$1/d" $FILE_PATH                [ $? -eq 0 ] && action "Del $1" /bin/true || exit 6            fi            ;;        -s|-search)            shift            if [ $(grep "^$1" $FILE_PATH | wc -l) -lt 1 ];then                echo "svnuser $1 is not exist"                exit 7            else                echo "svnuser $1 is exist"            fi            ;;        *)            exit 8    esac}#定义主函数function main(){    user    arg_num $1 $2    case_info $1 $2}main $*

代码执行情况

# sh management_svn.sh -a wutfNew password:Re-type new password:Adding password for user wutfAdd wutf is success                                        [  确定  ]# sh management_svn.sh -s wutfsvnuser wutf is exist# sh management_svn.sh -s wangyiwensvnuser wangyiwen is not exist# sh management_svn.sh -d wangyiwensvnuser wangyiwen is not exist                             [失败]# sh management_svn.sh -d wutfDel wutf                                                   [  确定  ]

while 循环和 until 循环的应用实践

Shell脚本语言的循环语句常见的有while、until、for 和 select 循环语句。

当型和直到型循环语法

while 循环语句

基本语法:

while 
<条件表达式>
do 指令。。 #注意代码缩进done

说明⚠️:

while循环语句会对紧跟在while命令后的条件表达式进行判断,如果该条件表达式成立,则执行while循环体里的命令或语句(即语法中do和done之间的指令),

每一次执行到done时就会重新判断while条件表达式是否成立,直到条件表达式不成立时才会跳出while循环体。

如果一开始条件表达式就不成立,那么程序就不会进入循环体中执行命令。

可用手机充值形象说明:

老男孩shell实战读书笔记 (6-10章节)

while循环执行流程对应的逻辑图:

老男孩shell实战读书笔记 (6-10章节)

until循环语句

基本语法:

until 
<条件表达式>
do 指令。。done

说明⚠️:

until表达式是在条件表达式不成立时,进入循环执行指令,条件表达式成立时,终止循环。

until应用场景很罕见,了解即可。

当型和直到型循环实战

shell中两个休息命令:

sleep 1usleep 1000000均表示休息1秒
while true #可以使用while [ 1 ] 代替do    uptime    sleep 2done

关于后台运行的命令

让shell脚本在后台运行的用法和说明

老男孩shell实战读书笔记 (6-10章节)

while 用于监控网站

开发要求

使用while守护进程的方式监控网站,每隔10秒确定一次网站是否正常

脚本代码

# cat while_test2.sh#!/bin/bash#引入系统函数库. /etc/init.d/functions#判断参数的数量if [ $# -ne 1 ];then    echo "usage $0 url"    exit 1fi#定义while循环while truedo    if [ $(curl -o /dev/null --connect-timeout 5 -s -w "%{http_code}" $1|egrep -w "200|301|302"|wc -l) -ne 1 ];then        action "this is URL $1 not normal" /bin/false    else        action "this is URL $1 normal" /bin/true    fi    sleep 10done

脚本执行情况

# sh while_test2.sh www.wutf.comthis is URL www.wutf.com normal                            [  确定  ]this is URL www.wutf.com not normal                        [失败]this is URL www.wutf.com normal                            [  确定  ]# sh while_test2.sh daguan.comthis is URL daguan.com not normal                          [失败]this is URL daguan.com not normal                          [失败]

写在最后

喜欢读技术书籍,喜欢做读书笔记,以上为本人在读《跟老男孩学Linux运维之shell编程实战》这本书时的笔记,如有任何版权问题,请联系留言。

转载于:https://blog.51cto.com/wutengfei/2308998

你可能感兴趣的文章
2011年 Linux 故事 Top 5
查看>>
ARouter 源码历险记 (五)
查看>>
优化Angular应用的性能
查看>>
php字符串函数
查看>>
[IOS] 自颁发证书不合法问题
查看>>
MYSQL常用命令
查看>>
Java中使用Jedis操作Redis
查看>>
play2.0实现新浪OAuth2.0
查看>>
QT:使用“状态模式”绘制界面 参考的一种面向对象的绘制图片的方法
查看>>
for 循环 里面 save 的问题
查看>>
常用 arm 汇编指令
查看>>
如何用_R_语言的_Shiny_库编写_web_程序
查看>>
mysql初步入门
查看>>
你对C++语言的理解到了哪一步呢
查看>>
JEECMS中FreeMarker的Macro
查看>>
高性能JavaScript(您值得一看)
查看>>
工作记录
查看>>
MySQL修改默认字符集
查看>>
HTTP Keep-Alive是什么?如何工作?
查看>>
maven 异常解决
查看>>