shell脚本编程

shell俗称壳(用来区别于核),提供使用者使用界面(命令解析器),它接受用户命令,然后调用相应的应用程序。

同时它还是一种程序设计语言,作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设计好的一连串的命令。作为程序涉及语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。

一、shell脚本基础概念

    shell的编程风格是过程式,即以指令为中心,数据服务指令。

    shell程序提供了编程能力,解释执行。

    shell编程语言的基本结构

        数据存储:变量、数组

        表达式:a+b

        语句:if

    shell编程逻辑处理方式

        顺序执行

        循环执行

        选择执行

    shell脚本是包含一些命令或声明,并符合一定格式的文本文件

        格式要求:首行shebang机制

        #!/bin/bash

        #!/usr/bin/python

        #!/usr/bin/perl

    shell脚本的用途

        自动化常用命令

        执行系统管理和故障排除

        创建简单的应用程序

        处理文本或文件

    创建shell脚本

        第一步:使用文本编辑器来创建文本文件

            第一行必须包括shell声明序列:#!

                #!/bin/bash

            添加注释

                注释以#开头

        第二步:运行脚本

            给予执行权限,chmod +x file.sh 在命令行上指定脚本的绝对或相对路径

            直接运行解释器,将脚本作为解释器程序的参数运行

    脚本调试

        bash -n /wang/jiaoben.sh

        检查脚本中的语法错误

        bash -x /wang/jiaoben.sh

        调试执行

[root@localhost wang]# bash -x jiaoben1.sh 
+ wang=100
+ echo 100
100
++ 200
jiaoben1.sh: line 5: 200: command not found
+ laowang=
+ echo ''
注:一边执行,一边检查语法:jiaoben1.sh第五行 200这个命令找不到

二、变量

    命名的内存空间

        数据存储方式

            字符:

            数值:整型,浮点型

    变量类型

        作用

            数据存储格式

            参与的运算

            表示的数据范围

        类型

            字符

            数值:整型,浮点型

    强类型:定义变量时必须指定类型,参与运算必须符合类型要求,调用未声明变量会产生错误

        例:java,python

    弱类型:无须指定类型,默认均为字符型,参与运算会自动进行隐式类型转换,变量无须事先定义可直接调用

        例:bash 不支持浮点数

    变量命名法则:

        不能使用程序中的保留字,例:if,for

        只能使用数字、字母及下划线,且不能以数字开头

        见明知亿

        统一命名规则:驼峰命名发,例:大驼峰SumFile,小驼峰sumFile

    bash中变量的种类

        根据变量的生效范围等标准

        本地变量:生效范围为当前shell进程,对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效。

        环境变量:生效范围为当前shell进程及其子进程

        局部变量:生效范围为当前shell进程中某代码片段(通常指函数)

        位置变量:$1,$2…来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数

        特殊变量:$?,$0,$*,$@,$#

            

    本地变量

         变量赋值:name=‘函数(value)’

        可以使用引用value:

            可以是直接字符串:name=“root”

            变量引用:name=“$USER”

            命令引用:name=`command`或name=$(command)

        变量引用:${name},$name

            "":弱引用,其中的变量引用会被替换为变量值

            '':强引用,其中的变量引用不会被替换为变量值,而保持原字符串

        显示已定义的所有变量:set

        删除变量:unset name

        本地变量不可给子shell进程使用。

[root@localhost wang]# cat jiaoben1.sh 
#!/bin/bash
wang=100
echo $wang
[root@localhost wang]# bash jiaoben1.sh 
100
[root@localhost wang]# echo $wang

[root@localhost wang]#

    环境变量

        变量声明、赋值

            export name=value

            declare -x name=value

        变量引用:${name},$name

        显示所有环境变量

            export

            env

            printenv

        删除环境变量

            unset name

        环境变量可以在当前shell生效,exit退出就不会生效,可以给子进程使用

        bash有许多内建的环境变量:PATH,SHELL,USER,UID,HISTSIZE,HOME,PWD,OLDPWD,HOSTFILE,PS1

[root@localhost wang]# export wang=100
[root@localhost wang]# cat jiaoben1.sh 
#!/bin/bash

echo $wang
[root@localhost wang]# bash jiaoben1.sh 
100

    只读变量

        只能声时,但不能修改和删除

        readonly name

        declare -r name

        定义之后永久保存在缓存中,exit退出即可取消定义

[root@localhost wang]# readonly wang=1
[root@localhost wang]# echo $wang
1
[root@localhost wang]# wang=2
-bash: wang: readonly variable
[root@localhost wang]# wang=1
-bash: wang: readonly variable

    位置变量

        在脚本代码中调用通过命令行传递给脚本的参数

        $1,$2…:对应第1,第2等参数,shift[n]换位置

        $0:命令本身

        $*:传递给脚本的所有参数,全部参数合为一个字符串

        $@:传递给脚本的所有参数,每个参数为独立字符串

        $#:传递给脚本的参数的个数

            $@,$*只在被双引号包起来的时候才会有差异

[root@localhost wang]# cat jiaoben1.sh 
#!/bin/bash
echo "第一个参数是$1"
echo "第二个参数是$2"
echo "第三个参数是$3"
echo "所有参数是$*"
echo "所有参数是$@"
echo "参数的个数是$#"
[root@localhost wang]# bash jiaoben1.sh aaa bbb ccc
第一个参数是aaa
第二个参数是bbb
第三个参数是ccc
所有参数是aaa bbb ccc
所有参数是aaa bbb ccc
参数的个数是3
[root@localhost wang]# cat jiaoben1.sh 
#!/bin/bash
maxuid=`cat $1 | cut -d: -f3 |sort -nr | head -n1`
echo "$maxuid" 
[root@localhost wang]# bash jiaoben1.sh /etc/passwd
1000

三、算术运算

    bash中的算术运算:help let

        +,-,*,/,%(取余),**(乘方)

    实现算术运算

        let var=算术表达式

        var=$[算术表达式]

        var=$((算术表达式))

        var=$(expr arg1 arg2 arg3…)

        echo '算术表达式' |bc

        declare -i var=数值

    乘法符号有些场景中需要转义。例:*

    bash有内建的随机数生成器:$RANDOM(0-32767)

[root@localhost ~]# let wang=2*3
[root@localhost ~]# echo $wang
6
[root@localhost ~]# wang=$[3*4]
[root@localhost ~]# echo $wang
12
[root@localhost ~]# wang=$((1+3+4))
[root@localhost ~]# echo $wang
8
[root@localhost ~]# echo "3*(5+6)"|bc
33
[root@localhost ~]# echo $[RANDOM%10]
1
[root@localhost ~]# echo $[RANDOM%10]
6
[root@localhost ~]# echo $[RANDOM%10]
5

四、逻辑运算

    

    true:1    false:0

    与:

        1与1=1

        1与0=0

        0与1=0

        0与0=0

    

        1或1=1

        1或0=1

        0或1=1

        0或0=0

    非:

        

        !1=0

        !0=1

    短路运算

        短路与

            第一个为0,结果必定为0

            第一个为1,第二个必须要参与运算

            command1 command2

            command1成功,执行command2

            command1失败,不执行command2

        短路或||

            第一个为1,结果必定为1

            第二个为0,第二个必须要参加运算

                command1 command2

            command1成功,不执行command2

            command1失败,执行command2

        异或:^

            异或的两个值,相同为假,不同为真

五、聚集命令

    有两种聚集命令的方法

        复合式:date; who|wc -l

            命令会一个接一个的运行

        子shell:(date; who|ec -l)>>/tmp/trace

            所有的输出都被发送给单个输出和输入


[root@localhost sh.log]# date;hostname;who
Thu Aug 11 19:49:53 CST 2016
localhost.localdomain
root     tty1         2016-08-09 17:41
root     pts/0        2016-08-11 18:53 (192.168.1.106)
root     pts/3        2016-08-11 14:06 (192.168.1.106)
[root@localhost sh.log]# date;hostname;who|wc -l
Thu Aug 11 19:50:08 CST 2016
localhost.localdomain
3
[root@localhost sh.log]# (date;hostname;who)|wc -l
5
[root@localhost sh.log]# (date;hostname;who)|wc -l

六、退出状态

    进程使用退出状态来报告成功或失败

        0 代表成功,1-255代表失败

        $?变量保存最近的命令退出状态

[root@localhost sh.log]# ping -c1 -W1 192.168.1.1 &> /dev/null
[root@localhost sh.log]# echo $?
0
[root@localhost sh.log]# ping -c1 -W1 192.168.1.256 &> /dev/null
[root@localhost sh.log]# echo $?
2
[root@localhost sh.log]# useradd wang
[root@localhost sh.log]# grep -q "laowang" /etc/passwd
[root@localhost sh.log]# echo $?
1
[root@localhost sh.log]# grep -q "wang" /etc/passwd
[root@localhost sh.log]# echo $?
0

    退出状态码

        bash自定义退出状态码

        exit[n]:自定义退出状态码

        注:脚本中一旦遇到exit命令,脚本会立即终止,终止退出状态取决与exit命令后面的数字

        注:如果未给脚本制定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

七、条件测试

    判断某需求是否满足,需要由测试机制来实现

    专用的测试表达式需要由测试命令辅助完成测试过程

    评估布尔声明,以便用在条件性执行中

        若真,则返回0

        若假,则返回1

    测试命令

        test expression

        [ expression ]

        [[ expression ]]

        注:expression前后必须有空白字符

    条件性的执行操作符

        根据退出状态而定,命令可以有条件地运行

            &&代表条件性的and then

            ||代表条件性的or else

[root@localhost sh.log]# ping -c1 -W1 192.168.1.1 &> /dev/null && echo "能ping通" || echo “不能ping通”
能ping通
[root@localhost sh.log]# ping -c1 -W1 192.168.1.256 &> /dev/null && echo "能ping通" || echo "不能ping通"
不能ping通

    bash测试类型

        数值测试

        -gt:是否大于

        -ge:是否大于等于

        -eq:是否不等于

        -ne:是否小于

        -le:是否小于等于

    字符串测试

        ==:是否等于

        >:ascii码是否大于ascii码

        <:是否小于

        !=:是否不等于

        =~:左侧字符串是否能够被右侧的pattern所匹配

            注:此表达式一半用于[[]]中

        -z‘string’:字符串是否为空,空为真,不空为假

        -n‘string’:字符串是否不空,不空为真,空为假

            注:用于字符比较时的用到的操作数都应该使用引号

[root@localhost wang]# cat jiaoben1.sh 
#!/bin/bash

maxdisk=`df|grep "^tmpfs"|tr -s " " "%" |cut -d% -f5|sort -nr|head -n1`
maxshiyonglv=80
[ $maxdisk == $maxshiyonglv ] && echo "磁盘空间要爆满" || echo "磁盘空间没爆满"

[root@localhost wang]# bash jiaoben1.sh 
磁盘空间没爆满
[root@localhost wang]# cat jiaoben2.sh 
#!/bin/bash
maxdisk=`df|grep "^tmpfs"|tr -s " " "%" |cut -d% -f5|sort -nr|head -n1`
maxshiyonglv=80
[ $maxdisk -gt $maxshiyonglv ] && echo "磁盘空间要爆满" || echo "磁盘空间没爆满"
[root@localhost wang]# bash jiaoben2.sh 
磁盘空间没爆满

    文件测试

        存在性测试

            -a file:同-e

            -e file:文件存在性测试,存在为真,否则为假

        存在性及类别测试

            -b file:是否存在且为块设备文件

            -c file:是否存在且为字符设备文件

            -d file:是否存在且为目录文件

            -f file:是否存在且为普通文件

            -z file:文件是否存在

            -h file 或-L file :存在且为符号链接文件

            -p file:是否存在且为命名管道文件

            -S file:是否存在且为套接字文件

        文件权限测试

            -r file:是否存在且可读

            -w file:是否存在且可写

            -x file:是否存在且可执行

        文件特殊权限测试

            -g file:是否存在且拥有sgid权限

            -u file:是否存在且拥有suid权限

            -k file:是否存在且拥有sticky权限

        文件大小测试

            -s file:是否存在且非空

        文件是否打开

            -t fd:fd表示文件描述符是否已经打开且与某终端相关

            -N file:文件自动上一次被读取之后是否被修改过

            -O file:当前有效用户是否为文件属主

            -G file:当前有效用户是否为文件属组

        双目测试

            file1 -ef file2:file1与file2是否指向同一个设备上的相同inode

            file1 -nt file2:file1是否新于file2

            file1 -ot file2:file1是否旧于file2

        组合测试条件

            第一种方式

                command1 && aommand2 并且

                command1 || aommand2 或者

                !command 非

                如:[ -e file ] && [ -r file ]

            第二种方式

                expression1 -a expression2 并且

                expression1 -o rxpression2 或者

                !expression

                必须使用测试命令进行

[wang@www wang]$ ll
total 16
----------. 1 root root    0 Aug 11 23:36 file1
-rwxrwxrwx. 1 root root   16 Aug 11 11:21 file2
drwxr-xr-x. 2 root root 4096 Aug 11 10:11 jiaoben
-rwxr-xr-x. 1 root root  111 Aug 12 00:30 jiaoben1.sh
-rw-r--r--. 1 root root  110 Aug 11 23:28 jiaoben2.sh
[wang@www wang]$ cat jiaoben1.sh 
#!/bin/bash

[ -r $1 -o -x $1 ] && echo "该文件有读或写权限" || echo "该文件没有读或写权限"
[wang@www wang]$ bash jiaoben1.sh file1
该文件没有读或写权限
[wang@www wang]$ bash jiaoben1.sh file2
该文件有读或写权限
[wang@www wang]$ cat jiaoben2.sh 
#!/bin/bash

[ -r $1 -a -x $1 ] && echo "这个文件有读写权限" ||echo "这个文件没有读写权限"
[wang@www wang]$ bash jiaoben2.sh file1
这个文件没有读写权限
[wang@www wang]$ bash jiaoben2.sh file2
这个文件有读写权限

    使用read来输入值分配给一个或多个shell变量

        -p 指定要显示的提示

        -t timeout

    read 从标准输入中读取值,给每个单词分配一个变量

    所有剩余单词都被分配给最后一个变量

        read -p “Enter a filename:” FILE

[root@www wang]# cat jiaoben1.sh 
#!/bin/bash
read -p "input a number:"
[root@www wang]# bash jiaoben1.sh 
input a number:laowang

    流程控制

        过程是编程语言

        顺序执行

        选择执行

        循环执行

原创文章,作者:DYW,如若转载,请注明出处:http://www.178linux.com/34064

(0)
DYWDYW
上一篇 2016-08-15
下一篇 2016-08-16

相关推荐

  • 磁盘分区和脚本练习

    1、创建一个10G分区,并格式为ext4文件系统 (1)要求其block大小为2048,预留空间百分比为2,卷标为MYDATA,默认挂载属性包含acl; mke2fs -t ext4 -b 2048 -m 2 -L MYDATA /dev/sdb5 tune2fs -o acl /dev/sdb5 (2)挂载至/etc/mydate目录,要求挂载时禁止自动运…

    Linux干货 2017-08-21
  • 高级文件系统管理(swap,RAID,LVM)

    交换分区wasp swap文件系统:     linux上的交换分区必须使用独立的文件系统;         其文件系统的system ID必须为82 创建swap设备,文件系统,使用mkswap命令 创建步骤:   &…

    Linux干货 2016-08-30
  • 高可用集群部署文档

    同学们都很活跃,自己好久没写了,也动动笔,下面文章写着玩的,如有错误请联系(NET7-粤-义薄云天) 高可用集群部署文档   目录: 目录: 1 项目需求: 2 实现方式: 2 拓扑图: 3 系统及软件版本: 3 安装步骤: 4 IP分配: 4 LVS和keepalived的安装和配置: 4 LVS主配置: 4 LVS2备 配置: 7 w…

    Linux干货 2015-08-11
  • 系统管理之系统安装及自动化安装

    概述:     上篇我们讨论了下关于Linux系统的启动流程和grub相关的内容,本篇将介绍一下Linux的系统安装相关的内容,具体分为:     1、系统安装程序anaconda的介绍     2、kickstart文件的介绍 &nbsp…

    Linux干货 2016-09-16
  • N27_第十三周作业

    1、建立samba共享,共享目录为/data,要求:描述完整的过程 1)共享名为shared,工作组为magedu 2)添加组develop,添加用户gentoo,centos和Ubuntu,其中gentoo和centos以develop为附加组,Ubuntu不属于develop组,密码均为用户名 3)添加samba用户gentoo,centos和Ubunt…

    2017-11-20