一、什么是shell?
shell是Linux上的一个命令解释器。他的作用是解释执行用户的命令,然后调用相应的应用程序,命令行中每次输入的一条命令,shell就会执行一条命令,并将结果展示到命令行窗口。
二、什么是shell脚本?
shell脚本就像是早期dos年代的.bat,最简单的功能就是将许多指令汇整在一起,让使用者很容易的就能够一个操作执行多个命令,他比windows下的批处理更强大,他提供了数组,循环,条件以及逻辑判断等重要功能,让使用者直接以shell来写程序,比其他的程序效率更高
1、shell脚本可包括的结构
- shell关键字——例如:if...else,for do...done
- shell命令——例如:export,exit,return
- Linux命令——例如:data,rm,mkdir
- 文本处理功能——例如:awk,cut,sed,grep
- 函数——通过函数把一些常用的功能放在一起。例如:/etc/init.d目录中的大部分或者全部系统的shell脚本所使用的函数都包含在文件夹/etc/init.d/functions中
- 控制流程语句——例如if...then...else或执行重复操作的shell
2、经常用到的shell脚本的实例
- 监控Linux系统
- 备份数据和创建快照
- 创建邮件告警系统
- 查找耗尽资源的进程
- 查找是否所有网络服务都运行正常
三、shell语言的种类
查看当前系统所使用的shell命令 # cat /etc/shells
Linux中的shell有多种类型,其中最常用的种类有Bourne Shell(sh)、C shell 和Korn shell。
-
Bourne Shell是unix最初使用的shell,并且在每种unix上都可以使用。Bourne shell在shell在编程方面相当优秀,但是人机交互没有其他的shell理想
-
Bourne-Again Shell(bash)是Linuxxixi'to系统中最常用的shell。是Bourne Shell完全向后兼容,并且在Bourne Shell的基础上增加、增强了很多特性,具有很多特色,可以提供命令补全,命令编辑和命令历史等功能,还包含了很多CShell和Korn Shell中的优点,有很灵活和强大的编程接口,同时又有很友好的用户界面
-
C shell(csh)是一种比Bourne shell更使用于编程的shell,他的语法和c语言很相似,Linux为喜欢c shell的编程人员提供了tsh。tcsh是与c shell兼容的增强版本。他包括命令行编程,可编程单词补全,拼写校正,历史命令替换、作业控制和类似C语言的语法
-
Korn shell(ksh)集合了c shell 和Bourne shell的优点,并和Bourne shell完全兼容。Linux系统提供了ksh的扩展,他支持任务控制,可以在命令行上挂起、台执程序、唤醒和终止。
四、脚本的编写
在Linux系统中,shell脚本(bash shell程序)通常在编辑器vi/vim中编写,由UNIX/Linux命令、bash shell命令、程序控制结构语句和注释等内容组成。
1、脚本的开头(第一行)
指出由那个程序(解释器)来执行脚本中的内容,这一行内容在Linux bash的编程一般为:
#vi myfirst.sh
#!/bin/bash 这个又称为幻数,根据“#!”后的解释器来确定该用那个解释器来解释这个脚本中的内容
2、脚本的注释
- 单行注释 “# xxxxxxxxxxxxx” 以#开头
- 多行注释 <<! !
3、脚本的执行
当shell脚本开始运行的时候会先查找env,该变量指定了环境文件,加载了环境变量文件后,shell就开始执行脚本中的内容。shell是从上至下、自左向右依次执行每一行的命令和语法,即执行完一个命令后会再执行下一个命令,如果遇到了子脚本,会先执行子脚本的文件,完成后再返回父脚本执行后续命令。通常情况下,在执行shell脚本时,会向系统内核请求启动一个新的进程,以便在该进程中执行脚本的命令及shell脚本
- bash script_name或者sh script_name,(当脚本没有执行权限时使用)
- ./script_name 或者/path/to/script_name,在当前路径或者指定路径下执行脚本
- source script_name或者.script_name
4、shell脚本的编写规范
- 指定解释器,通常为: #! /bin/bash
- 增加版本,作者及脚本信息的描述
#Date:~~~~~~~
#Author:~~~~~~~~~
#Desc:
#version
- 脚本注释尽量减少中文
- shell脚本的扩展名以.sh结尾
- 成对的符号应该一次性写完,然后退格在括号内容
- 流程控制语句应该应先写格式完,再添加内容,避免嵌套多增多时遗漏。代码缩进内容更清晰
五、shell中的变量
-
什么是变量?
是假定为一组特定值中之任一值的量。变量为程序或脚本访问内存中可被修改的一块数据提供了简单的方式。Linux Shell中的变量可被指定为任意数据类型,比如文本字符串或是数值。例:# a=“i am littleFatty”
#echo $a
i am littleFatty
-
变量类型
A:环境变量(全局变量):可以在创建他们的shell及其派生出来的任意子进程shell中使用
B、系统变量
系统已经定义好的的环境变量,在/bin/login程序设置好的
系统变量 | 含义 |
BASH_VERSION | 保存Bash实力版本 |
HISTFILE | 命令历史文件 |
HISTFILESIZE | 命令历史文件中能包含的最大行数 |
HOME | 家目录 |
HOSTNAME | 主机名 |
PATH | 搜索命令路径 |
PS1 | 命令提示符 |
PWD | 当前工作目录 |
SHELL | 设置登录shell路径 |
TERM | 设置登录的终端的类型 |
TMOUT | read命令默认超出时间 |
IFS | 内部分割符,当shell处理“命令替换”和“参数替换”时,shell根据IFS的值,默认是space,tab,newwhile来拆解读入的变量,然后根据对特殊字符进行处理,最后重新组合默认赋值给该变量 |
3、自定义全局变量
方法一:export 变量命=value
方法二:变量名=value;export 变量名
方法三:declar -x 变量名=value
注:在赋值操作符“=”的周围,不要有任何的空格。本地变量也要遵循。
在当前shell环境定义的变量只在当前环境有效,如何让环境变量永久生效,如下操作:
(1)用户的环境变量配置
在用户目录下的.bashrc文件中优先设置生效,除了这个文件还有.bash_profile文件
(2)全局的环境变量配置文件如下
/etc/profile(主要是默认的主环境变量,系统所有用户都会加载这个文件)
/etc/bashrc(全局环境变量文件,优先推荐)
/etc/profile.d(若需要在登录后初始化或者显示加载内容)
三个文件的加载顺序: /etc/profile——>/etc/profile.d——>./bshrc(用户环境变量文件)——>/etc/bashrc
(3)取消环境变量 unset 变量名
例:#echo $USER
#unset USER
#echo $USER
(4)变量名赋值要求:变量名一般由字母、数字、下划线组成,要能做到见名知意,可加单引号,双引号,不加引号
不加引号:直接定义内容,内容为连续数字,字符串就可以,若有变量时则可以被解析出来变量值再一同输出。
加单引号:引号内的值是什么就输出什么,不会解析,当值中有变量时,不会被解析
加双引号:会将值中变量和命令解析后再输出
B:普通变量(局部变量):只能只能在他们创建的shell函数或shell脚本中使用
查看变量值的命令:set、env、declare
set:输出所有的变量,包括全局变量和局部变量
-o:只显示bash Shell的所有参数配置信息
env:只显示全局变量
declare:输出所有的变量、函数、整数和已经导出的变量
4、设置登录提示的两种方式
(1)#vim /etc/motd
# cat /etc/motd
welcome to Linux
(2)#cd /etc/profile.d
#echo ”echo hello word“ > login.sh
5、变量数组
环境变量的一个重要特性就是可以使用数组,数组是能够保存多个值的变量,数组中的值既可以分别引用,也可以整体引用。
要为某个环境变量设置多个值,只需要将他们列到圆括号内,各个值用空格分割
(1)定义数组变量
# myvar=(one two 3 4 5 6)
#echo $myvar
one
#echo $myvar[1] 索引值是从0开始的,单个索引数组中的某个值
two
#echo $myvar[*] 显示整个数值的变量,可以用*号通配
one two 3 4 5 6
(2)更改索引位置的值
# myvar[2]=10
echo $myvar[*]
one two 10 4 5 6
(3)移除数组中某个值
# unset myvar[3]
echo $myvar[*]
one two 10 5 6
6、特殊的shell变量
(1)位置变量
在shell中存在一些特殊的环境变量,例如 0,#,*等,我们称为位置参数变量,要给命令,脚本等传递参数时,就需要在shell脚本中使用位置参数变量。
位置变量 | 作用说明 |
$0 | 获取当前执行shell脚本的文件名,如包含了路径 |
$n | 获取当前执行的shell脚本的第n个参数值,当n=0时表示脚本的文件名,当n>9时需要用括号括起来 ${10} |
$# | 获取当前执行的脚本的参数总个数 |
$* | 获取当前shell脚本所有传递的参数,不加引号和$@相同,如果给$*加上双引号,则将所有的参数视为单个字符,相当于“$1 $2 $3” |
$@ | 获取当前shell脚本所有传递的参数,不加引号和$*相同,如果加引号则便是所有的参数视为不同的独立的字符串,相当于“$1","$2","$3" |
(2)状态变量
状态变量 | 作用说明 |
$? | 获取执行上一个指令的状态返回值,返回0表示上一个命令或执行程序执行成功,返回非0则表示上一个命令执行失败;可以接收脚本中执行exit数字后,将这个数字返回给$?变量;可以接收在函数中使用return数字返回的值。 |
$$ | 获取当前执行的shell脚本的进程号PID
|
$! | 获取上一个后台工作的进程的进程号PID |
$_ | 获取在此之前执行的命令或脚本的最后一个参数 |
7、shell中的扩展变量
表达式 | 说明 |
${parameter:-word} | 如果parameter的变量值为空或者未赋值,则会返回word字符串替代变量值 |
${parameter:=word} | 如果parameter的变量值为空或者未赋值,则设置设置这个变量值为word,并返回其值 |
¥{parameter:?word} | 如果parameter的变量值为空或者未赋值,那么word字符串会被当做标准错误输出,否则输出变量的值 |
${parameter:+word} | 如果parameter的变量值为空或者未赋值,则什么都不做,否则word字符将被代替变量的值 |
8、shell脚本中变量的数值运算
(1)算术运算符
算数运算符 | 含义 |
+,- | 加法,减法或者正负号 |
* ,/,% | 乘法,触发,取余 |
** | 幂运算 |
++,-- | 增加或者减少 |
! ,&&,|| | 逻辑运算:非,与,或 |
<,<+=,>,>= | 小于,小于等于,大于,大于等于 |
==,!=,= | 相等,不等于,相等于 |
<<,>> | 向左移位,向右移位 |
=,+=,-=,*=,/=,%= | 赋值运算符 |
运算操作符与运算命令 | 含义 |
(()) | 用于整数运算的常用运算符 |
let | 用于整数运算类似(()) |
expr | 用于整数运算,也还有其他功能 |
bc | 计算器程序 |
$[] | 用于整数运算 |
declare | 定义变量和属性,-i参数可以用于定义整型变量,做运算 |
A:双小括号基础语法
运算操作符和命令 | 含义 |
((i=i+1)) | 赋值运算,将1+1结果运算后赋值给i,不能直接用echo$((i=i+1)) |
i=$((i+1)) | 表示将表达式运算后赋值给i |
((8>1&&1=1)) | 可以进行比较操作,也可以加入逻辑与,或运算 |
echo $((1+2)) | 可以在双小括号前加$符号用来直接输出运算 |
B:expr命令用法
expr命令是一个强大的计算命令,既可以做整数运算,也可以做字符串匹配等运算,expr在计算时可以直接使用数字和运算符进行计算
例:# expr 3 + 3 运算符及数字之间需要有空格隔开,不然系统会默认当作一个字符串处理
6
# expr 3 \* 3 使用乘号时,需要转义
9
C:let运算命令法
let运算符可以用来计算整数,和小括号功能类似 ; let运算符表达式等同于((运算表达式))
D:$[]运算
# i=1
# echo $[i+1]
2
# echo $[3*3]
9
9、shell中的内置命令
echo printf export read shift exec
(1)echo作用是为了将数据输出至屏幕上,常用选项有:
选项 | 说明 |
-n | 不换行输出内容 |
-e | 解析转义字符 |
转义字符 | |
\n | 换行 |
\r | 回车 |
\t | 制表符 |
\b | 退格 |
\v | 纵向制表符 |
(2)read命令 让用户输入信息传给shell内部变量
-t:等待时间
-p:设置提示信息
#read -t 10 -p ”please input one number:“ one
please input one number: 1
#echo $one
1
(3)shift 重新命名所有参数的位置,会使位置参数$#减一
(4)exec 可以在不创建子进程的情况下去执行命令,并在命令执行结束后终止进程
六、shell脚本中的条件测试
条件测试语法 | 说明 |
test<测试表达式> | 利用test进行条件测试的表达式,test和测试表达式直接至少需要有一个空格 |
[<测试表达式>] | 通过[]小括号来进行测试,[]的两半括号和测试表达式直接至少需要一个空格,不能用&&,||,>,<,一般只用-a,-o,-gt,le |
[[<测试表达式>]] | 通过双小括号来进行条件测试,[[]]的两个半括号边界和测试表达式之间至少需要一个空格,可以进行通配选择 |
((<测试表达式>)) | 通过双小括号进行条件测试,双小括号两个括号边界不需要和测试表达式空格 |
(1)文件测试
(2)字符串测试表达式
(3)整数二元比较
(4)逻辑操作符
七、shell脚本中条件判断
1、if条件语句
(1)单分支结构
(2)双分支结构
(3)多分支结构
2、case 条件语句
3、for循环
语法结构:
for 变量名 in [取值列表]
do
循环体
done
4、while 循环
while 条件语句
do
循环体
done
shell循环控制中条件与循环控制及程序返回命令知识
命令 | 说明 |
break n | 如果省略n表示跳出整个循环,n表示跳出循环的层数 |
continue | 如果省略你n,则表示跳过本次循环,忽略本次循环的剩余代码,进入循环的下一次循环。n表示退到第n层继续循环 |
exit n | 退出当前shell程序,n为上一次程序执行的返回状态值。 |
return n | 用于在函数里作为函数的返回值,以判断执行是否正确。 |
八、shell中的函数
一、函数的定义
1、 function 函数名()
{
指令
}
2、函数名 ()
{
指令
}
3、function 函数名
{
指令
}
二、函数的传递
1、 函数名
2、函数名 参数1 参数2 ...