设为首页 收藏本站
查看: 1072|回复: 0

漫谈shell脚本

[复制链接]

尚未签到

发表于 2018-8-24 08:01:18 | 显示全部楼层 |阅读模式
  一. 关于shell
  shell,英文是壳,外壳的意思,至于在计算机中,同样有这样的一层意思,也就是可以将shell看做是计算机系统封装的一层外壳,来供用户使用,因此,用户可以通过操纵shell也就是输入一系列命令来达到各种需要的目的,那么shell也可以被称为命令解释器
  在shell下,用户可以键入一行命令而shell解释一行来使其依次执行不同的任务,这种方式称为交互式,如果在执行命令比较少的情况下交互式还是方便的,而且还使这些命令透明,用户能够分辨出因果关系;
  但是如果想要执行的命令是成批的,并不需要知道过程只是想要知道结果,或者重复度很高,那么一行一行的敲入shell一行一行的解释无疑是很费时费力的,因此就可以使用另外一种处理方式就是批处理,也就是可以编写一个shell脚本,shell脚本和编程语言有些相似,同样都有变量和流程控制语句,但shell脚本是解释行的,也就是shell会将脚本中的命令一行一行的拿出来,相当于用户一行一行地键入,但是和交互式相比较起来就省事多了。
  二. shell执行原理
  由于历史原因,shell的种类有很多,比如bash、sh、cah、ksh、tcsh等,可以在当前路径/etc/shells下面查看系统中所有已知(但不一定安装)的shell:
DSC0000.png

  对于当前的一个shell比如bash来说,当使用交互式键入一条命令的时候,它并不会自身去亲自执行一条命令,因为有可能这条命令是一条恶意的命令会侵犯当前进程,所以它会创建出一个子进程,让子进程去执行这个shell命令,但是对于shell脚本来说,当创建好一个shell脚本运行起来的时候,相当于是一条命令,这时候bash会创建一个子进程来运行shell脚本,而这个子进程同样也是一个bash,因此,当其去执行shell脚本中一条条的命令的时候,也就是相当于再会去创建出一个子进程来执行shell脚本中的一条条命令,可画图如下:
DSC0001.png 因此,在执行shell脚本中的多个命令的时候,也就需要创建出多个进程来一一执行,尽管这样,但仍然比交互式的要简便的多;

  三. shell脚本

  •   运行方式
  在shell脚本的编写中,'#'表示注释,相当于C语言中的‘//’,但是只有在第一行例外,在shell脚本中,第一行必须声明要使用的命令解释器,形式如下:
#!/bin/bash  
echo "this is a shell test"
  '#'的使用,在第一行并不表示注释,它表示该脚本使用后面的解释器/bin/bash解释执行;而'#!'被称为shebang;
  chmod u+x shell脚本
  首先,因为shell脚本并不需要经过编译,但是对于刚创建出来的shell脚本文件,一开始时并没有执行权限的,因此,可以将shell所属者的权限加上可执行,然后运行shell脚本:
DSC0002.png

  命令解释器 shell脚本
  要运行shell脚本,除了在脚本的编写中需要制定使用的命令解释器外,在运行起来的时候,仍然可以指定需要哪一个命令解释器来进行解释执行:
DSC0003.png

  除了指定/bin/bash之外,还可以指定在当前系统中已经安装好的任何一个命令解释器;当然,除去了'/bin/'只使用一个bash来进行解释仍然是可行的,理所应当,其他解释器sh等也是一样:
DSC0004.png


  •   shell变量
  按照惯例,shell变量由全大写字母加下划线组成,有两种类型的shell变量:
  环境变量:
  在进程中提到,子进程会从父进程那里继承来环境变量,因此,对于执行shell脚本和脚本中的命令而创建出的子进程会继承父进程的shell环境变量;
  用printenv命令可以显示当前shell进程的环境变量:
DSC0005.png

  
  本地变量:
  环境变量是所有进程都有的概念,而本地变量是shell特有的概念;本地变量只存在于当前shell进程,用set命令可以显示当前shell进程中定义的所有变量(包括环境变量和本地变量)和函数;
  在shell中定义一个变量格式如下:
  VALNAME=value
  等号的两边是不能有空格的,因为如果用空格隔开,VALNAME就会被解释成一条命令,后面就会被解释为命令的参数;
  一个变量被定以后仅存在于当前shell进程,而用export可以将其导出到环境变量中,而使用unset可以将删除:
DSC0006.jpg

  和语言中定义变量不同的是,在shell中定义变量可以直接赋值定义而不需要指明变量的类型,比如无论是字符串、整型还是浮点型,都一律可用 VALNAME=value 来进行定义;事实上,在shell中,所有变量都是字符串,比如定义 VAL=15,VAL实际是一个字符串“15”而不是一个整数;在shell中如果对一个没有定义的变量取值,则为空字符串:
#!/bin/bash  
echo "this is a shell test"
  

  
VAL1=22       //定义变量VAL1值为22
  
VAL2=11       //定义变量VAL2值为11
  
RES=0
  

  
//$(())表示将变量的值取出变成整数,只支持+-*/和()运算符,且只支持整数运算
  
let RES=$((VAL1+VAL2))
  

  
echo $RES     //符号 $ 表示取出变量的内容
  
echo ${VAL3}  //同样可以使用未定义的变量,只是内容是一个空字符串
  运行结果:
DSC0007.png

  上面程序示例中,取出一个变量的内容可以使用$VALNAME后面直接跟上变量名,也可以使用${VALNAME},但是加上花括号不容易引起歧义,比如:
//本意是想在VAL1的内容后面追加上abc  
echo $VAL1abc   //将VAL1abc看做一个变量
  
echo ${VAL1}abc  //取出VAL1的值后面再跟上abc

  •   反引号 `` 和$()
  大体上来说,反引号``和$()的相同之处是都可用于命令替换,就是将括起来的命令执行完毕后再交给相应的对象或者输出:
#!/bin/bash  

  
echo `pwd`
  
echo $(pwd)
  运行脚本:
DSC0008.png

  这里要注意区分$()和$(()),前者的内容只能是命令,后者用于算术运算;
  但是反引号和$()是有区别的,如下:
VAL=10  
echo `echo \$VAL`
  
echo $(echo \$VAL)
  在C语言中'\'是转义字符,用于除去后面的字符的特殊意义转而取其字面意思,因此,上面的代码中期望输出的是“$VAL”,但是运行程序会发现:
DSC0009.png

  反引号输出的是取出了变量的内容,并没有将后面的'$'转义成字面值,而$()中'\'将'$'转义成字面值不再取出变量的内容,输出了“$VAL”达到了预期值;
  而如果将上面的两句代码中改为:
VAL=10  
echo `echo \\$VAL`
  
echo $(echo \$VAL)
  运行脚本:
DSC00010.png

  因此分析结果:
  虽然同是命令替换,但是反引号中可以看出'\\'相当于一个转义字符'\',而$()是正常一个转义字符'\'转义出后面的字符表示其字面意思;

  •   eval命令
  eval命令用于将其后跟着的参数命令内容进行必要的替换,然后再执行命令,也就是说,eval会对命令行进行两次扫描,第一次将其重新替换,第二次才真正执行命令;
  对于普通的简单的命令来说是看不到什么区别的:
#!/bin/bash  
echo "this is a shell test"
  
echo "hello world"
  
eval echo "hello world"
  运行脚本:
DSC00011.png

  但是对于如下程序:
#!/bin/bash  
echo "this is a shell test"
  

  
VAL=100
  
STR="echo \$VAL"
  
echo ${STR}
  
eval echo ${STR}
  运行程序:
DSC00012.png

  直接echo,会将变量的内容直接输出,其中STR字符串的内容中将'$'符号进行了转义,表示直接echo并不会取出VAL的值;
  但是使用eval命令,首先会将STR的内容进行转义,之后再运行eval后面的命令行,这时候就会将VAL的值按照‘$’符号给提取出来输出,因此,eval命令的作用就可以看做是执行那些一次性并不能完成的,而是需要进行进一步的替换转置之后才能得出正确结论的命令;

  •   单中括号[ ]和双中括号` `
  单中括号[]:
  1. [ 用于条件测试,它并不是一个符号而是一个命令,用于判断后面条件的真假,并设置相应的退出码;和在C语言中的判断成立条件不同的是,使用[进行条件判断,如果为真则退出码为0,如果为假则退出码为1
#!/bin/bash  
echo "this is a shell test"
  
read str
  
//比较字符串时,强烈建议在左右两边都加上相同的字符,以确保当输入为空的时候仍能够进行比较
  
[ "X$str" == "Xred" ]
  
echo $?
  
[ "X$str" == "Xyellow" ]
  
echo $?
  
[ "X$str" == "Xblue" ]
  
echo $?
  
[ "X$str" == "Xpink" ]
  
echo $?
  运行程序:
DSC00013.png

  匹配条件成立退出码为0,不匹配则为1;
  而对于整数的比较,需要使用-gt(大于)、-lt(小于)、-eq(等于)、-ge(大于等于)、-le(小于等于)来进行比较;
  2. [ ]还有另外的一个用途就是作为正则表达式的一部分,描述一个字符的匹配范围;
  双中括号` `:
  ` `同样可用于条件判断,但可以说是[ ]的加强版,因为在其内部的条件判断语句支持‘&&’、‘||’、‘>’和‘ 59 ]];then   //成绩在60到79之间为及格
  
    echo "You are good"
  
else                                         //低于60分不及格
  
    echo "Sorry,you failed"
  
fi
  运行程序:
DSC00014.png

  这里需要强调的是,[ ]和` `在shell中都是命令,因此应该将其后面跟着的参数之间加上空格分开,不然就有可能会报错,同时,在` `中仅支持‘>’和‘=’和‘> /home/lounuo/test_6_12/backups.txt
  在当前用户下用crontab -e命令编写自身的一个crontab,路径为/var/spool/cron,文件名就为用户名:
*/1 * * * * /home/lounuo/test_6_12/test.sh  表示每隔一分钟执行一次命令也就是test.sh脚本;也就是说每隔一分钟将test.text文件的内容备份到backups.txt文件中
  这里需要强调的是,在shell中仍然需要指明路径,不然crond在执行的时候就会默认在用户目录下创建出一个backups.txt文件,至于要拷贝的test.txt文件就当然找不到了,因此只会看到一个时间戳
  使用不管crond是什么状态,service crond restart重启crond任务:
DSC00015.png

  一开始backups.txt的内容为空;每隔一分钟修改test.txt的内容,然后再打开backups.txt,使用
  tail -f backups.txt命令观察如下:
DSC00016.png

  这里为了观察方便将时间设定的比较短,实际使用中可以将时间设定为更加合适的备份时间,如此一来就可以自定义一个备份的机制,每次更改一个文件中的内容都会自动备份一份,这样将shell脚本添加进crond定时任务中,就更加提高了用户与shell进行命令与结果交互的效率。
  《完》



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-555724-1-1.html 上篇帖子: Ubuntu下shell编程基础 下篇帖子: gzexe加密shell脚本
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表