Shell脚本编程入门

认识Shell

Shell原意为贝壳

Linux系统中的shell是一个特殊的应用程序,它介于操作系统内核与用户之间,充当一个命令解释器的角色,负责接收用户输入的操作指令(命令)并进行解释,将需要执行的操作传递给内核执行,并输出执行结果。

可以使用命令查看当前使用的是哪种shell以及当前Linux系统中都支持哪些shell种类。

 

查看当前系统使用的shell

Shell脚本编程入门

 

查看当前Linux系统所支持的shell种类

Shell脚本编程入门

其中/bin/bash是目前大多数Linux版本采用的默认shellBash的全称为Bourne Again Shell,是最受欢迎的开源软件项目之一。

常见的shell解释器程序有很多种,使用不同的shell时,其内部指令、命令行提示等方面会存在一些区别。

 

Shell脚本

只要将平时使用的各种Linux命令按顺序保存到一个文本文件,然后添加可执行权限,这个文件就成为一个shell脚本了。

编写一个恰到好处的shell脚本程序,可以批量处理、自动化地完成一系列维护任务、大大减轻管理员的负担。

周期性的任务可以通过Crond服务来管理,而步骤复杂、操作繁琐的任务可以使用Shell脚本来批量处理,两相结合就可以非常灵活、自主地完成各种系统运维工作。Shell脚本负责具体的备份操作,Crond服务负责控制备份周期。

 

1、脚本的编写

Shell脚本编程入门

Shell脚本主要由开头部分、注释部分以及语句部分组成

1)开头

“#!/bin/bash”是一行特殊的脚本声明,表示此行以后的语句通过/bin/bash程序来解释执行。

符号“#!”用来告诉系统它后面的参数是用来执行该文件的程序。

2)注释

其它以”#”开头的语句表示注释信息,建议在程序中使用注释,即使过了长时间也能很快的了解脚本的用途。

3)语句

Linux各种命令的集合

 

2、脚本的执行

编写完成shell脚本后,需要赋予执行权限

Shell脚本编程入门

执行此脚本文件后,输出结果与依次执行这两条命令是相同的,从而实现了批量处理的自动化过程。

Linux还提供了执行shell脚本的方式——指定某个shell来解释脚本语句,或者通过内部命令source(或点号”.”)来加载文件的源代码执行。

例如,使用”sh first.sh”“. first.sh”都可以执行firsh.sh脚本中的语句。

Shell脚本编程入门

注意:以上三种执行方式不添加执行权限也可以执行文件

 

3、脚本调试

bash -n /path/to/scriptfile    检测脚本中的语法错误

bash -x /path/to/scriptfile    调试执行

 

Shell变量

Shell变量用来存放系统和用户需要使用的特定参数(值)。而且这些参数可以根据用户的设定或系统环境的变化而相应变化。

常见的Shell变量的类型包括自定义变量、环境变量、预定义变量、位置变量。

1、自定义变量

自定义变量是由系统用户自己定义的变量,只在用户自己的Shell环境中有效,因此又称为本地变量。

 

1)定义新的变量

定义变量的基本格式为变量名=变量值,等号两边没有空格。

[root@localhost ~]# name=tom

[root@localhost ~]# age=20

Shell脚本编程入门

 

变量名称命名规则:

a.不能使程序中的保留字:例如if, for

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

c.见名知义

d.统一命名规则:驼峰命名法

 

2)查看和引用变量的值

Shell脚本编程入门

 

2、环境变量

环境变量指的是出于运行需要而由Linux系统提前创建的一类变量,主要用于设置用户的工作环境,包括用户宿主目录、命令替换路径、用户当前目录、登录终端等。环境变量的值由linux系统自动维护,会随着用户状态的改变而改变。

使用env命令可以查看当前工作环境下的环境变量,对于常见的一些环境变量应了解其各自的用途。

例如USER表示用户标识、HOME表示用户的宿主目录、LANG表示语言和字符集、PWD表示当前所在的工作目录、PATH表示命令搜索路径….

 

查看当前Linux系统中所有的环境变量

   blob.png

可以用命令修改环境变量的搜索路径,这样写完shell脚本以后可以直接输入脚本名称直接执行,不用每次输入文件的路径。

 

临时修改:只对当前终端有效

Shell脚本编程入门

 

永久修改:永久有效

修改家目录下的隐藏文件.bash_profile,添加指定的搜索路径即可,搜索路径之间用“:”分隔,添加完成后需要重新读取该配置文件让其生效。

Shell脚本编程入门

 

重新读取配置文件使其立即生效

Shell脚本编程入门

Shell脚本编程入门

 

将搜索路径添加完成后直接输入文件名即可运行成功

Shell脚本编程入门

 

PATH的搜索顺序:从左到右依次搜索,

Shell脚本编程入门

同样在/usr/bin下面写一个同名的脚本文件,执行时依然执行/testdir/script目录下的文件,当把hash缓存清空后,即执行了/usr/bin目录下的first.sh文件,如果把缓存再次清空,执行脚本文件报错,清空缓存后,有可以执行了。

从此可见,缓存(hash)中的命令优先于搜索路径,如果缓存中有这条命令,就不去搜索PATH变量,文件不存在也执行hash,会报错;清空缓存后,按照PATH变量的搜索顺序依次查找,当PATH变量有多个可以匹配,执行先匹配到,匹配到第一个脚本时不再往下搜索。

 

环境变量的配置文件

全局配置文件:/etc/.bash_profile

个人配置文件:~/.bash_profile

 

3、预定义变量

预定义变量是由Bash程序预先定义好的一类特殊变量,用户只能使用预定义变量,而不能创建新的预定义变量,也不能直接为预定义变量赋值。预定义变量使用$符号和另一个符号组合表示,较常用的几个预定义变量如下:

$#:表示命令行中位置参数的个数。

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

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

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

$?:表示前一条命令执行后的返回状态,0表示成功,非0表示失败。

$0:表示当前执行的脚本或程序的名称。

 

示例:备份目录数据,并显示备份信息

Shell脚本编程入门

 

4、位置变量

 位置变量:位置变量也称为位置参数,在脚本代码中调用通过命令行传递给脚本的参数

当执行命令行操作时,第一个字符表示命令名或脚本程序名,其余的字符串参数按照从左到右的顺序依次赋值给位置变量。

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

 

示例:计算两个数值的和

Shell脚本编程入门

 

示例:判断给出的文件的行数

Shell脚本编程入门

 

   定义只读变量

只读变量:只能声明,但不能修改和删除

readonly name

declare -r name

 

示例:定义只读变量

Shell脚本编程入门

注意:只读变量同样只在当前终端中有效

 

变量赋值的特殊操作

1)双引号(

双引号主要起了一个界定字符串的作用,特别是当要赋值的内容中包含空格时,必须以双引号括起来,否则会报错;其他情况下双引号通常可以省略。

Shell脚本编程入门

在双引号范围内,使用“$”符号可以引用其他变量的值(变量引用),从而能够直接调用现有变量的值来赋值给新的变量。

Shell脚本编程入门

Shell脚本编程入门

2)单引号(

当要赋值的内容中包含$ \等具有特殊含义的字符时,应使用单引号括起来。在单引号的范围内,将无法引用其他变量的值,任何字符均作为普通字符看待。但赋值内容中包含单引号时,需使用“\’”符号进行转义,以免冲突。

Shell脚本编程入门

 

3)反撇号(`

反撇号主要用于命令替换,允许将执行某个命令的屏幕输出结果赋值给变量。反撇号括起来的范围内必须是能够执行的命令行,否则将会出错。

Shell脚本编程入门

需要注意的是,使用反撇号难以在一行命令中实现嵌套命令替换操作,这时可以改用“$()”来代替反撇号操作,以解决嵌套的问题。

Shell脚本编程入门

 

变量的作用范围

1、设置局部变量

默认情况下,新定义的变量只在当前的Shell环境中有效,因此成为局部变量。当进入子程序或新的子Shell环境时,局部变量将无法再使用。

Shell脚本编程入门

 

2、设置全局变量

为了使用户定义的变量在所有的子Shell环境中能够继续使用,减少重复设置工作,可以通过内部命令export将指定的变量导出为全局变量可以同时制定多个变量名称作为参数(不需使用$符合),变量名之间以空格分隔。

Shell脚本编程入门

 

使用export导出全局变量的同时,也可以为变量进行赋值,这样在新定义全局变量时就不需要提前进行赋值了,也可以将之前的局部变量设置使用export命令设置为全局变量,使其在子shell中可以调用。

Shell脚本编程入门

注意:设置全局变量后,子进程可以调用父进程的变量,反之则不可以。

 

条件测试

使用专门的测试工具test命令,可以对特定条件进行测试,并根据返回值来判断条件是否成立(返回值0表示条件成立)。

test 条件表达式

[ 条件表达式 ]

 

两种方式作用完全相同,但后者更为常用,也更贴近编程习惯。需要注意的是,方括号与表达式之间需要至少一个空格进行分割。

根据需要测试的条件类别不同,条件表达式也不一样。比较常用的条件操作包括文件测试、整数值比较、字符串比较,以及针对多个条件的逻辑测试。

执行条件测试操作后,通过预定义变量”$?“可以获得测试命令的返回状态值,从而判断该条件是否成立。echo $?查看返回状态值。

 

1、文件测试

    存在性测试

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

    -a FILE:同-e

     

    存在性及类别测试

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

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

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

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

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

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

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

     

    文件权限测试

    -r  测试当前用户是否有权限读取(Read

    -w         测试当前用户是否有权限写入(Write

    -x 测试是否这只有可执行权限(Excute

     

    文件特殊权限测试

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

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

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

     

    文件大小测试

    -s FILE: 是否存在且非空;

     

    文件是否打开

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

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

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

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

     

    双目测试

    FILE1 -ef FILE2: FILE1FILE2是否指向同一个设备上的相同inode

    FILE1 -nt FILE2: FILE1是否新于FILE2

    FILE1 -ot FILE2: FILE1是否旧于FILE2

 

2、数值比较

-eq   1个数等于(Equal)第2个数

-ne   1个数不等于(Not Equal)第2个数

-gt    1个数大于(Greater Than)第2个数

-lt    1个数小于(Lesser Than)第2个数

-le     1个数小于或等于(Lesser or Equal)第2个数

-ge  1个数大于或等于(Lesser or Equal)第2个数

 

3、字符串比较

=     1个字符串与第2个字符串相同

!=    1个字符串与第2个字符串相同,其中!符号表示取反的意思

-z    检查字符串是否为空(Zero),对于未定义或赋予空值的变量将视为空串。

==    是否等于;

>:      ascii码是否大于ascii

<:      是否小于

!=:     是否不等于

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

注意: 此表达式一般用于[[ ]]中;

 

-z "STRING":字符串是否为空,空为真,不空为假

-n "STRING":字符串是否不空,不空为真,空为假

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

 

算术运算

bash中的算术运算

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

实现算术运算:

let var=算术表达式

var=$[算术表达式]

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

var=$(expr arg1 arg2 arg3 …)

declare –i var = 数值

echo ‘算术表达式’ | bc

乘法符号有些场景中需要转义, *

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

echo $[$RANDOM%50] 0-49之间随机数

Shell脚本编程入门

 

赋值

增强型赋值:

+=, -=, *=, /=, %=

let varOPERvalue

例如:let count+=3            自加3后自赋值

自增,自减:

let var+=1

let var++

let var-=1

let var–

 

示例:算术运算

Shell脚本编程入门

 

示例:j自增自减运算

Shell脚本编程入门

 

    逻辑测试

&&:逻辑与,表示而且的意思,只有当前后两个条件都成立时,真个测试命令的返回值才为0。使用test命令测试时,&&可改为-a

||:逻辑与,表示或者的意思,只有前后两个条件有一个成立时,整个测试命令的返回值为0。使用test名测试时,||可改为-o

!:逻辑否,表示的意思,只有当指定的条件不成立时,正测试命令的返回值才为0

 

逻辑运算

true, false

1, 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,第二个必须要参与运算;

短路或:

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

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

异或: ^

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

 

聚集命令

有两种聚集命令的方法

复合式: date; who | wc –l          命令会一个接一个地运行

shell (date; who | wc -l )  >> /tmp/trace

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

 

组合测试条件

第一种方式:

COMMAND1 && COMMAND2 并且

COMMAND1 || COMMAND2 或者

! COMMAND

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

第二种方式:

EXPRESSION1 -a EXPRESSION2 并且

EXPRESSION1 -o EXPRESSION2 或者

! EXPRESSION

必须使用测试命令进行;

# [ -z “$HOSTNAME” -o $HOSTNAME "==\"localhost.localdomain" ] && hostname www.magedu.com

# [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab

 

示例:判断两个变量的大小

Shell脚本编程入门

 

退出状态

进程使用退出状态来报告成功或失败,$? 变量保存最近的命令退出状态

0  代表成功

1255  代表失败

 

示例:ping一个ip地址,并查看其返回

Shell脚本编程入门

 

退出状态码

bash自定义退出状态码

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

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

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

 

示例:根据测试条件返回状态码

Shell脚本编程入门

 

read命令:接受用户输入

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

read  [选项]  [参数]

-p    指定要显示的提示信息

-t    指定读取值时等待的时间(秒)

-n    读取用户输入的前几个字符

-s    隐藏用户的输入字符

-r    允许输入包含反斜杠

-d    -d选项指定的字符作为结束符,如空格、特殊符号

read 从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量。

read -p “Enter a filename: “ FILE

 

示例:编写修改当前用户的密码脚本

Shell脚本编程入门

使用-s选项可隐藏用户要输入的字符信息,如密码等信息

 

 

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

(0)
cyh5217cyh5217
上一篇 2016-08-12
下一篇 2016-08-12

相关推荐

  • Linux的启动流程

    启动流程  POST: Power-On-Self-Test,加电自检,是BIOS功能的一个主要部分。负责完成对CPU、主板、内存、硬盘子系统、显示子系统、 串并行接口、键盘、 CD-ROM光驱等硬件情况的检测。 ROM: BIOS, Basic Input and Output System,保存着有关计算机系统最重要的基本输入输出程序,系统信息设置、 …

    Linux干货 2016-09-13
  • Linux虚拟网络接口-Bonding 配置

    一、bonding 的定义     bonding是通过将同一设备的多个物理网卡绑定到一个虚拟网卡上,再对外提供连接。对于外端来说,多个物理网卡共享虚拟网卡的IP和mac地址,也就表现为一个网卡设备。通过bonding技术可以实现高可用或者负载均衡。     bonding有7种工作模式:&nbsp…

    Linux干货 2017-07-02
  • Linux命令格式、获取帮助、文件系统

    一、Linux的命令     (一)、概念和意义:             发起一个命令:请求内核将某个二进制程序运行为一个进程;      &nbs…

    Linux干货 2016-08-15
  • N26 第八周作业

    1、请描述网桥、集线器、二层交换机、三层交换机、路由器的功能、使用场景与区别。 网桥(network bridge) 网桥工作于物理层与数据链路层,在终端设备较多的局域网中可以用网桥设备将局域网分离为不同的冲突域(collision domain),减少网络冲突,提升网络传输效率 集线器(network hub) 集线器具有多个I/O端口,一个端口的输入信号…

    2017-02-25
  • httpd服务归纳:浅谈I/O模型

    1. 四种理论的I/O模型      1) 调用者(服务进程):         阻塞:  进程发起I/O调用,如果调用为完成,进程被挂起休眠,不能再执行其他功能    …

    Linux干货 2015-05-27

评论列表(1条)

  • 马哥教育
    马哥教育 2016-08-12 14:39

    学习态度端正,博客不仅写的完善而且有自己的想法,通过自己的思路汇总,足以见其对知识的理解深刻,望后期能持续学习,提升自我。