Loading... <p><strong><span style="font-size: 24px">一、认识shell</span></strong></p> <p style="text-indent: 2em"><span style="font-size: 14px">什么是shell?shell为单词外壳的意思。那么这是谁的外壳?我们知道一个系统中实际工作的是那些硬件,cpu、内存、磁盘等。我们如何调用这些硬件为我们工作?实际上,硬件是由内核kernel控制的。我们可以通过kernel控制硬件,但我们不能直接和内核kernel交流。我们需要一个外壳,这个外壳就是shell来沟通kernel。何为shell脚本,其实不过是一堆命令写在一个文件中,这个文件具有执行权限。</span></p> <p><span style="font-size: 14px"><strong><span style="font-size: 24px">二、变量</span></strong></span></p> <p style="text-indent: 2em"><span style="font-size: 14px">什么是变量?变量是脚本编程中数据表现的一中方法,变量是系统为了保留数据项在内存空间中分配一个位置或者一组位置的标识或名字。bash变量是不区分类型的,本质上都是字符串。<br /></span></p> <p><span style="font-size: 18px"><strong>2.1 特殊的变量类型</strong></span></p> <p><span style="font-size: 14px">本地变量:只对当前的shell进程有效,对其它shell进程无效,包含当前shell进程的子进程</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ test=string #定义一个本地变量 [leon@localhost ~]$ echo $test string [leon@localhost ~]$ bash #打开一个子shell [leon@localhost ~]$ echo $test [leon@localhost ~]$ #为null值</pre> <p><span style="font-size: 14px">环境变量:对当前shell进程和子进程有效,对其它shell无效</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ export test=string #定义一个环境变量 [leon@localhost ~]$ echo $test string [leon@localhost ~]$ bash [leon@localhost ~]$ echo $test string</pre> <p>局部变量:对shell脚本中某段代码片段有效,通常用于函数本地,通常用local来定义</p> <pre class="brush:bash;toolbar:false">[leon@localhost tmp]$ cat test.sh #!/bin/bash #定义使用哪种shell解析脚本 # function test { #定义一个函数 local a=local #定义一个局部变量 echo $a } test && echo $a [leon@localhost tmp]$ ./test.sh local</pre> <p>位置变量:$0 $1 $2…$n</p> <pre class="brush:bash;toolbar:false">[leon@localhost tmp]$ sh test1.sh 1 [leon@localhost tmp]$ cat test1.sh #!/bin/bash # echo $0 echo $1 echo $2 [leon@localhost tmp]$ sh test1.sh string1 string2 string3 #传递位置参数 test1.sh string1 string2</pre> <p>常用的特殊变量:$? $@ $* $# $$</p> <pre class="brush:bash;toolbar:false">[leon@localhost tmp]$ cat test2.sh #!/bin/bash # echo $* echo $@ echo $# echo $? echo $$ [leon@localhost tmp]$ sh test2.sh string1 string2 string3 string4 string1 string2 string3 string4 string1 string2 string3 string4 4 0 1650</pre> <p>数组 :是特殊的变量,bash支持一维数组。数组由数组名+索引 组成。</p> <p>如:a[1] a[2] a[3] … a[N] a[hello] a[Number] a[string] …</p> <p><span style="font-size: 14px"><strong><span style="font-size: 18px">2.2 变量的声明及赋值</span></strong><br /></span></p> <p><span style="font-size: 14px">1.不能使用系统内置变量<br /></span></p> <p><span style="font-size: 14px">2.以字母,数字,下划线组成,不能以数字开头</span></p> <p><span style="font-size: 14px">3.见名知义</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost tmp]$ PATH=/tmp [leon@localhost tmp]$ ls bash: ls: command not found [leon@localhost ~]$ [leon@localhost ~]$ 1test=test -bash: 1test=test: command not found</pre> <p><span style="font-size: 14px">定义整型的变量</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ declare -i number=23 #使用declare -i定义一个整型变量</pre> <p>定义数组</p> <p>可以使用declare 定义</p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ declare -a a=(1 2 3 4) #定义一个数组 [leon@localhost ~]$ echo ${a[@]} 1 2 3 4 [leon@localhost ~]$ b=(1 2 3 4) [leon@localhost ~]$ echo ${b[@]} 1 2 3 4 [leon@localhost ~]$ declare -A string=([hello]='hello' [day]='sunday') #定义一个关联型数组 [leon@localhost ~]$ echo ${string[@]} sunday hello [leon@localhost ~]$ logs=(/home/*) #给变量赋值 [leon@localhost ~]$ echo ${logs[@]} /home/leon /home/openstack /home/test</pre> <p><strong style="font-size: 24px">三、数组及字符串操作</strong></p> <p><span style="font-size: 16px"><strong>3.1 数组操作</strong></span></p> <p><span style="font-size: 16px"><strong>3.1.1 数组长度</strong></span></p> <p><span style="font-size: 16px"></span></p> <p><span style="font-size: 14px">${#ARRAY[*]}</span></p> <p><span style="font-size: 14px">${#ARRAY[@]}</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ declare -A string=([hello]='hello' [day]='sunday') [leon@localhost ~]$ echo ${#string[@]} && echo ${#string[*]} 2 2</pre> <p><strong>3.1.2 数组中挑选某些元素</strong></p> <p><span style="font-size: 14px">${ARRAY[@]:offset:number}</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ echo ${string[@]} sunday hello [leon@localhost ~]$ echo ${string[@]:1:1} sunday [leon@localhost ~]$ echo ${string[@]:1:2} sunday hello [leon@localhost ~]$ echo ${string[@]:1} sunday hello</pre> <p><strong>3.1.3 数组的删除</strong></p> <p>unset ARRAY<strong><br /></strong></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ echo ${logs[@]} /home/leon /home/openstack /home/test [leon@localhost ~]$ unset logs[1] #删除索引为1的数组 [leon@localhost ~]$ echo ${logs[@]} /home/leon /home/test [leon@localhost ~]$ unset logs [leon@localhost ~]$ echo ${logs[@]} [leon@localhost ~]$</pre> <p><strong style="font-size: 14px"><span style="font-size: 16px">3.2 字符串操作</span></strong></p> <p><strong><span style="font-size: 16px">3.2.1 字符串取子串</span></strong></p> <p><span style="font-size: 14px">${string:offset:length} :从第offset个向右取length个字符串</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ string=a1b2c3d4e5f6 [leon@localhost ~]$ echo ${string} a1b2c3d4e5f6 [leon@localhost ~]$ echo ${string:1:4} 1b2c</pre> <p><span style="font-size: 14px">${string: -length} :从右向左取length个字符串</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ echo ${string} a1b2c3d4e5f6 [leon@localhost ~]$ echo ${string: -2} f6</pre> <p><span style="font-size: 14px">${string#*word} :在string中存储字符串上,自左而右,查找第一次出现word,删除字符开始到此word处的所有内容</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ string=string-hello-myname-is-hello-over [leon@localhost ~]$ echo $string string-hello-myname-is-hello-over [leon@localhost ~]$ echo ${string#*hello} -myname-is-hello-over</pre> <p><span style="font-size: 14px">${string##*word} :在string中存储字符串上,自左而右,查找最后一次出现word,删除字符开始到此word处的所有内容</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ echo $string string-hello-myname-is-hello-over [leon@localhost ~]$ echo ${string#*hello} -myname-is-hello-over [leon@localhost ~]$ echo $string string-hello-myname-is-hello-over [leon@localhost ~]$ echo ${string##*hello} -over</pre> <p><span style="font-size: 14px">${string%word*}在string中存储的字符串上,自右而左,查找第一次出现的word,删除字符开始到此word处的所有内容</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ echo $string string-hello-myname-is-hello-over [leon@localhost ~]$ echo ${string%hello*} string-hello-myname-is-</pre> <p><span style="font-size: 14px">${string%%word*}在string中存储的字符串上,自右而左,查找最后一次出现的word,删除字符开始到此word处的所有内容</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ echo $string string-hello-myname-is-hello-over [leon@localhost ~]$ echo ${string%%hello*} string-</pre> <p><strong>3.2.2 字符串查找替换</strong></p> <p>${string/pattern/substi} :替换第一次出现<span style="font-size: 14px">的字符串</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ echo $string string-hello-myname-is-hello-over [leon@localhost ~]$ echo ${string/hello/hi} string-hi-myname-is-hello-over</pre> <p><span style="font-size: 14px">${sting//pattern/substi} :替换所有出现过的字符串</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ echo $string string-hello-myname-is-hello-over [leon@localhost ~]$ echo ${string//hello/hi} string-hi-myname-is-hi-over ${string/pattern} [leon@localhost ~]$ echo ${string//hello/hi} [leon@localhost ~]$ echo $string string-hello-myname-is-hello-over [leon@localhost ~]$ echo ${string/hello} string--myname-is-hello-over ${string//pattern}[leon@localhost ~]$ echo $string string-hello-myname-is-hello-over [leon@localhost ~]$ echo ${string//hello} string--myname-is--over [leon@localhost ~]$</pre> <p><strong style="font-size: 24px">四、流程控制</strong></p> <p><span style="font-size: 16px"><strong>4.1 选择分支</strong></span></p> <p><span style="font-size: 16px"><strong>4.1.1 条件测试</strong></span></p> <p><span style="font-size: 14px">条件测试中,如果为真,则返回执行状态为0的值,否则返回执行状态为非0的值</span></p> <p><span style="font-size: 14px">整型测试:数值之间比较大小 字符型比较<br /></span></p> <p><span style="font-size: 14px">-gt -lt -eq -ge -le > < == != >= <= -n -z</span></p> <p><span style="font-size: 14px">常用文件测试</span></p> <p><span style="font-size: 14px">-e 文件存在</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ [ -e /tmp/xxxxxxx ] [leon@localhost ~]$ echo $? 1</pre> <p>-d 文件存在且为目录</p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ [ -d /tmp ] [leon@localhost ~]$ echo $? 0</pre> <p>-f 文件存在且为普通文件</p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ [ -f /tmp ] [leon@localhost ~]$ echo $? 1</pre> <p>-r 文件是否具有可读权限</p> <p>[leon@localhost ~]$ [ -r /root ]</p> <p>[leon@localhost ~]$ echo $?</p> <p>1</p> <p>-w 文件是否具有可写权限</p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ [ -w /home/leon ] [leon@localhost ~]$ echo $? 0</pre> <p>-x 文件是否具有可执行权限</p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ [ -x /home/leon ] [leon@localhost ~]$ echo $? 0</pre> <p><span style="font-size: 14px">组合条件测试 :在多个条件间实现逻辑运算</span></p> <p><span style="font-size: 14px">与: [ 条件一 -a 条件二 ]</span></p> <p><span style="font-size: 14px"> 条件一 && 条件二<br /></span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ [ -x /home -a -r /root ] [leon@localhost ~]$ echo $? 1 [leon@localhost ~]$ test -x /home && test -r /root [leon@localhost ~]$ echo $? 1</pre> <p><span style="font-size: 14px">或: [ 条件一 -o 条件二 ]</span></p> <p><span style="font-size: 14px"> 条件一 || 条件二</span> </p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ [ -x /home -o -r /root ] [leon@localhost ~]$ echo $? 0 [leon@localhost ~]$ test -x /home || test -r /tmp [leon@localhost ~]$ echo $? 0</pre> <p><span style="font-size: 14px">非:[ !条件 ]</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ [ ! -r /home/leon ] [leon@localhost ~]$ echo $? 1</pre> <p><strong>4.1.2 if选择分支</strong></p> <p><span style="font-size: 14px">语法: if 测试条件1;then</span></p> <p><span style="font-size: 14px"> 选择分支1</span></p> <p><span style="font-size: 14px"> elif 测试条件2;then</span></p> <p><span style="font-size: 14px"> 选择分支2</span></p> <p><span style="font-size: 14px"> ……</span></p> <p><span style="font-size: 14px"> elif 测试条件n;then</span></p> <p><span style="font-size: 14px"> 选择分支n</span></p> <p><span style="font-size: 14px"> else</span></p> <p><span style="font-size: 14px"> 分支</span></p> <p><span style="font-size: 14px"> fi<br /></span></p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ if true ; then echo true ;else echo false ;fi true[leon@localhost ~]$ [leon@localhost ~]$ if id test1 &>/dev/null ; then echo test1 ;elif id test2 &>/dev/null;then echo test2 ;elif id leon &>/dev/null ;then echo leon ;fi leon [leon@localhost ~]$ if [ $? -eq 0 ] ;then echo ture ;else echo false;fi ture</pre> <p><strong>4.1.3 case选择分支</strong></p> <p><span style="font-size: 14px">语法:case word in</span></p> <p><span style="font-size: 14px"> pattern1)<br /></span></p> <p><span style="font-size: 14px"> 分支1<br /></span></p> <p><span style="font-size: 14px"> ;;<br /></span></p> <p><span style="font-size: 14px"> pattern2)</span></p> <p><span style="font-size: 14px"> 分支2<br /></span></p> <p><span style="font-size: 14px"> ;;<br /></span></p> <p><span style="font-size: 14px"> patternN)<br /></span></p> <p><span style="font-size: 14px"> 分支N<br /></span></p> <p><span style="font-size: 14px"> ;;<br /></span></p> <p><span style="font-size: 14px"> *)<br /></span></p> <p><span style="font-size: 14px"> 分支<br /></span></p> <p> ;;</p> <p> esac</p> <pre class="brush:bash;toolbar:false">[leon@localhost ~]$ case leon in root) id root ;; leon) echo leon ;; *) echo not this user! ;; esac leon [leon@localhost tmp]$ cat testCase.sh #!/bin/bsh # case $1 in 1) echo 1 ;; 2) echo 2 ;; 3) echo 3 ;; *) echo order ;; esac [leon@localhost tmp]$ chmod +x testCase.sh [leon@localhost tmp]$ sh testCase.sh order [leon@localhost tmp]$ ./testCase.sh 1 1</pre> <p><span style="font-size: 14px"></span></p> <p><strong>4.2 循环</strong></p> <p><span style="font-size: 16px"><strong>4.2.1 for循环</strong></span></p> <p><span style="font-size: 14px">语法1: for i in list ;do</span></p> <p><span style="font-size: 14px"> list<br /></span></p> <p><span style="font-size: 14px"> done<br /></span></p> <p><span style="font-size: 14px">语法2: for ((表达式一;条件表达式;表达式二));do</span></p> <p><span style="font-size: 14px"> list</span></p> <p><span style="font-size: 14px"> done</span></p> <pre class="brush:bash;toolbar:false">[leon@localhost tmp]$ for i in {1..5};do echo $i ;done 1 2 3 4 5 [leon@localhost tmp]$ for ((i=1;i<=5;i++));do echo $i ;done 1 2 3 4 5</pre> <p><strong>4.2.2 while循环</strong></p> <p>语法1: while 测试条件; do</p> <p> 循环体</p> <p> done<br />语法2: while read 变量名;do</p> <p> 循环体</p> <p> done < /path/to/somefile</p> <pre class="brush:bash;toolbar:false">[leon@localhost tmp]$ cat testWhile.sh #!/bin/bash # declare -i i=1 while [ $i -le 5 ];do #比较i和5的大小,为真则进入循环,为假则退出循环 echo $i let i++ done [leon@localhost tmp]$ sh testWhile.sh 1 2 3 4 5 [leon@localhost tmp]$ cat testWhile.sh #!/bin/bash # while read userInfo;do echo $userInfo done < /etc/passwd [leon@localhost tmp]$ sh testWhile.sh root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin ...... openstack:x:502:502::/home/openstack:/bin/bash [leon@localhost tmp]$</pre> <p> <strong><span style="font-size: 14px">4.2.3 until循环</span></strong></p> <p><span style="font-size: 14px">语法:</span>until 测试条件; do</p> <p> 循环体</p> <p> done</p> <pre class="brush:bash;toolbar:false">[leon@vm tmp]$ cat testUntil.sh #!/bin/bash # declare -i i=5 until [ $i -lt 1 ];do #比较i和1的大小,为假就进入循环,为真则退出循环 echo $i let i-- done [leon@vm tmp]$ sh testUntil.sh 5 4 3 2 1</pre> <p><strong><span style="font-size: 24px">五、函数及返回值</span></strong></p> <p><span style="font-size: 14px">语法1: function function_name {list}</span></p> <p><span style="font-size: 14px">语法2: function_name () {list}</span></p> <pre class="brush:bash;toolbar:false">[leon@vm tmp]$ cat testFunction.sh #!/bin/bash # function display { #定义一个名为display的函数 cat << NODE ------------------- ------meau--------- 1: install os 2: quit ------------------- NODE return 0 #退出函数并返回状态值0 echo next function_list } view() { display #调用函数 exit 1 #退出shell并返回状态值1 } view [leon@vm tmp]$ sh testFunction.sh ------------------- ------meau--------- 1: install os 2: quit ------------------- [leon@vm tmp]$ echo $? 1</pre> <p><strong style="font-size: 14px"><span style="font-size: 24px">六、循环控制</span></strong></p> <p><span style="font-size: 14px">continue : 提前进入下一轮循环</span></p> <pre class="brush:bash;toolbar:false">[leon@vm tmp]$ cat testContinue.sh #/bin/bash # for (( i=1;i<=2;i++ )) ;do echo outside $i for (( n=1;n<=2;n++ ));do echo inside $n continue #直接进入下一循环 # break echo hello #这个echo语句用于没有将会执行 done done [leon@vm tmp]$ sh testContinue.sh outside 1 inside 1 inside 2 outside 2 inside 1 inside 2</pre> <p><span style="font-size: 14px">break :跳出当前循环</span></p> <pre class="brush:bash;toolbar:false">[leon@vm tmp]$ cat testContinue.sh #/bin/bash # for (( i=1;i<=2;i++ )) ;do echo outside $i for (( n=1;n<=2;n++ ));do echo inside $n # continue break #退出当前循环 echo hello done done [leon@vm tmp]$ sh testContinue.sh outside 1 inside 1 outside 2 inside 1</pre> <p><strong><span style="font-size: 24px">七、信号捕捉</span></strong></p> <p><span style="font-size: 14px">信号捕捉:trap 'COMMAND;COMMAND' SINGNAL</span></p> <pre class="brush:bash;toolbar:false">[leon@vm tmp]$ cat testTrap.sh #!/bin/bash # trap 'echo exit' SIGINT ping -c 100 www.baidu.com [leon@vm tmp]$ sh testTrap.sh #按ctrl+c时,捕捉到信号。 PING www.a.shifen.com (180.97.33.108) 56(84) bytes of data. 64 bytes from 180.97.33.108: icmp_seq=1 ttl=128 time=29.4 ms 64 bytes from 180.97.33.108: icmp_seq=2 ttl=128 time=29.5 ms ^C --- www.a.shifen.com ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1278ms rtt min/avg/max/mdev = 29.489/29.530/29.571/0.041 ms exit #退出脚本时执行echo语句输出</pre> <p><strong><span style="font-size: 24px">八、总结</span></strong></p> <p><span style="font-size: 14px"></span></p> <p><span style="font-size: 14px">shell编程是linux运维人员必须掌握的技能,shell不像其它C、C#、Java等高级编程语言那样有类和对象,面向对象等概念,但是shell可以有强大的命令支撑。毕竟我们是通过shell来沟通内核,不需要运行在虚拟机上。<br /></span></p> 最后修改:2021 年 12 月 10 日 10 : 53 AM © 允许规范转载 赞赏 如果觉得我的文章对你有用,请随意赞赏 赞赏作者 支付宝微信