; 认识shell | Linux运维部落

认识shell

一、认识shell

什么是shell?shell为单词外壳的意思。那么这是谁的外壳?我们知道一个系统中实际工作的是那些硬件,cpu、内存、磁盘等。我们如何调用这些硬件为我们工作?实际上,硬件是由内核kernel控制的。我们可以通过kernel控制硬件,但我们不能直接和内核kernel交流。我们需要一个外壳,这个外壳就是shell来沟通kernel。何为shell脚本,其实不过是一堆命令写在一个文件中,这个文件具有执行权限。

二、变量

什么是变量?变量是脚本编程中数据表现的一中方法,变量是系统为了保留数据项在内存空间中分配一个位置或者一组位置的标识或名字。bash变量是不区分类型的,本质上都是字符串。

2.1 特殊的变量类型

本地变量:只对当前的shell进程有效,对其它shell进程无效,包含当前shell进程的子进程

[leon@localhost ~]$ test=string                                    #定义一个本地变量
[leon@localhost ~]$ echo $test
string
[leon@localhost ~]$ bash                                            #打开一个子shell
[leon@localhost ~]$ echo $test
[leon@localhost ~]$                                                  #为null值

环境变量:对当前shell进程和子进程有效,对其它shell无效

[leon@localhost ~]$ export test=string                            #定义一个环境变量
[leon@localhost ~]$ echo $test
string
[leon@localhost ~]$ bash
[leon@localhost ~]$ echo $test
string

局部变量:对shell脚本中某段代码片段有效,通常用于函数本地,通常用local来定义

[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

位置变量:$0  $1  $2…$n

[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

常用的特殊变量:$? $@ $* $# $$

[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

数组  :是特殊的变量,bash支持一维数组。数组由数组名+索引 组成。

如:a[1] a[2] a[3] … a[N]  a[hello]  a[Number]  a[string] …

2.2 变量的声明及赋值

1.不能使用系统内置变量

2.以字母,数字,下划线组成,不能以数字开头

3.见名知义

[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

定义整型的变量

[leon@localhost ~]$ declare -i number=23                #使用declare -i定义一个整型变量

定义数组

可以使用declare 定义

[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

三、数组及字符串操作

3.1 数组操作

3.1.1 数组长度

${#ARRAY[*]}

${#ARRAY[@]}

[leon@localhost ~]$ declare -A string=([hello]='hello' [day]='sunday')
[leon@localhost ~]$ echo ${#string[@]} && echo ${#string[*]}
2 2

3.1.2 数组中挑选某些元素

${ARRAY[@]:offset:number}

[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

3.1.3 数组的删除

unset ARRAY

[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 ~]$

3.2 字符串操作

3.2.1 字符串取子串

${string:offset:length}  :从第offset个向右取length个字符串

[leon@localhost ~]$ string=a1b2c3d4e5f6
[leon@localhost ~]$ echo ${string}
a1b2c3d4e5f6
[leon@localhost ~]$ echo ${string:1:4}
1b2c

${string: -length}    :从右向左取length个字符串

[leon@localhost ~]$ echo ${string}
a1b2c3d4e5f6
[leon@localhost ~]$ echo ${string: -2}
f6

${string#*word} :在string中存储字符串上,自左而右,查找第一次出现word,删除字符开始到此word处的所有内容

[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

${string##*word} :在string中存储字符串上,自左而右,查找最后一次出现word,删除字符开始到此word处的所有内容

[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

${string%word*}在string中存储的字符串上,自右而左,查找第一次出现的word,删除字符开始到此word处的所有内容

[leon@localhost ~]$ echo $string
string-hello-myname-is-hello-over
[leon@localhost ~]$ echo ${string%hello*}
string-hello-myname-is-

${string%%word*}在string中存储的字符串上,自右而左,查找最后一次出现的word,删除字符开始到此word处的所有内容

[leon@localhost ~]$ echo $string
string-hello-myname-is-hello-over
[leon@localhost ~]$ echo ${string%%hello*}
string-

3.2.2 字符串查找替换

${string/pattern/substi} :替换第一次出现的字符串

[leon@localhost ~]$ echo $string
string-hello-myname-is-hello-over
[leon@localhost ~]$ echo ${string/hello/hi}
string-hi-myname-is-hello-over

${sting//pattern/substi} :替换所有出现过的字符串

[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 ~]$

四、流程控制

4.1 选择分支

4.1.1 条件测试

条件测试中,如果为真,则返回执行状态为0的值,否则返回执行状态为非0的值

整型测试:数值之间比较大小     字符型比较

-gt  -lt  -eq  -ge  -le    >   <  ==  !=  >=  <=  -n  -z

常用文件测试

-e    文件存在

[leon@localhost ~]$ [ -e /tmp/xxxxxxx ] 
[leon@localhost ~]$ echo $?
1

-d    文件存在且为目录

[leon@localhost ~]$ [ -d /tmp ] 
[leon@localhost ~]$ echo $?
0

-f    文件存在且为普通文件

[leon@localhost ~]$ [ -f /tmp ] 
[leon@localhost ~]$ echo $?
1

-r    文件是否具有可读权限

[leon@localhost ~]$ [  -r /root ]

[leon@localhost ~]$ echo $?

1

-w    文件是否具有可写权限

[leon@localhost ~]$ [ -w /home/leon ]
[leon@localhost ~]$ echo $?
0

-x    文件是否具有可执行权限

[leon@localhost ~]$ [ -x /home/leon ]
[leon@localhost ~]$ echo $?
0

组合条件测试 :在多个条件间实现逻辑运算

与: [ 条件一 -a 条件二 ]

    条件一 && 条件二

[leon@localhost ~]$ [ -x /home -a -r /root ]
[leon@localhost ~]$ echo $?
1

[leon@localhost ~]$ test -x /home &&  test -r /root
[leon@localhost ~]$ echo $?
1

或: [ 条件一 -o 条件二 ]

    条件一 || 条件二 

[leon@localhost ~]$ [ -x /home -o -r /root ]
[leon@localhost ~]$ echo $?
0

[leon@localhost ~]$ test -x /home ||  test -r /tmp
[leon@localhost ~]$ echo $?
0

非:[ !条件 ]

[leon@localhost ~]$ [ ! -r /home/leon ]
[leon@localhost ~]$ echo $?
1

4.1.2 if选择分支

语法: if 测试条件1;then

    选择分支1

   elif 测试条件2;then

    选择分支2

   ……

   elif 测试条件n;then

    选择分支n

   else

    分支

   fi

[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

4.1.3 case选择分支

语法:case word  in

    pattern1)

    分支1

    ;;

    pattern2)

    分支2

    ;;

    patternN)

     分支N

    ;;

    *)

      分支

    ;;

    esac

[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

4.2 循环

4.2.1 for循环

语法1: for i in  list ;do

       list

    done

语法2: for ((表达式一;条件表达式;表达式二));do

       list

    done

[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

4.2.2 while循环

语法1: while 测试条件; do

        循环体

    done
语法2: while read 变量名;do

        循环体

    done < /path/to/somefile

[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]$

 4.2.3 until循环

语法:until 测试条件; do

        循环体

    done

[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

五、函数及返回值

语法1: function function_name {list}

语法2: function_name () {list}

[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

六、循环控制

continue : 提前进入下一轮循环

[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

break  :跳出当前循环

[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

七、信号捕捉

信号捕捉:trap 'COMMAND;COMMAND'  SINGNAL

[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语句输出

八、总结

shell编程是linux运维人员必须掌握的技能,shell不像其它C、C#、Java等高级编程语言那样有类和对象,面向对象等概念,但是shell可以有强大的命令支撑。毕竟我们是通过shell来沟通内核,不需要运行在虚拟机上。

原创文章,作者:成吉思汗,如若转载,请注明出处:/8026

评论列表(1条)

  • stanley
    stanley 2015-09-22 09:35

    总结的非常不错,文档功底很深

联系我们

400-080-6560

在线咨询:点击这里给我发消息

邮件:1660809109@qq.com

工作时间:周一至周五,9:30-18:30,节假日同时也值班

友情链接:万达招商QQ  万达娱乐招商  万达直属QQ  万达注册  华宇招商  guoqibee.com  万达招商QQ  万达娱乐主管  万达开户  测试