shell脚本:
Linux从底层到上层的系统架构:硬件-->内核-->库(lib)-->shell-->用户。
shell既是一种命令语言,也是程序设计语言(shell脚本),作为一种命令语言,它提供了用户与内核的交互界面,互动式的解释和执行用户所输入的命令;作为程序设计语言,它又定义了各种变量和参数,并且提供了许多在高级语言中才具有的控制结构,比如循环和分支。
写shell脚本的一般规范:
# Name:init_app_jboss.sh //脚本的名称
# Version Number:1.00 //脚本修改后的版本
# Type:config middleware for initing server //脚本的功能
# Language:bash shell //脚本shell语言
# Date:2013-06-19 //编写时间
# Author:magedu //脚本作者
# Email:[email protected] //作者邮件
注意:#开头的行会被解释器忽略,空白行也会被解释器忽略
shell脚本当中的变量:
本地变量:作用域为当前的shell进程,包含环境变量
变量的赋值:name=value 比如:a=1; a=$(cat /etc/passwd |wc -l)
变量的引用:$name $a
变量的查看:set
变量的撤销:uset name 注意:此次不是引用变量,所有不需要加$
环境变量:作用域为当前的shell进程及派生出来的子进程
变量的赋值: declare -x name=[value] 或 export name=[value]
变量的查看:env,export,declare -x,printenv
局部变量:普通的变量,只在创建它的shell脚本中有效。
位置参数变量: 表示向脚本传递参数
[root@localhost tmp]# bash sum.sh $1 $2 $3
$1 $2 $3就是脚本要用到的参数变量
特殊变量:向脚本传递参数
$0: 脚本文件路径自身
$@: 取出给定脚本参数的路径 全部一起取并显示
$#: 表示脚本参数的个数
$*: 取出给定脚本参数的路径 单个单个取并显示
$?: 查看上次执行后所返回的状态码
比如: [ $# -eq 2 ] && echo "yes,you are right" || echo "pleses give me two digital" 表示传递两个参数给脚本,如果是2个就输出yes,you are right,如果不是就输出please give me two digital。
shell脚本当中的算术运算:
+、-、*、/、%
注意:shell变量是一种很“弱”的变量,默认情况下,一个变量保存一个串,shell不关心这个串是什么,所以要进行一些算术运算时,需要要用到一些命令如 let、declare、expr、双括号等。
语法:
let var=$sum1+$sum2
var=$[$sum1+$sum2]
var=$(($sum1+$sum2))
var=$(expr $sum1 + $sum2)
注意:*、/、%在有些情况下需要转义\,比如在var=$(expr $sum1 \* $sum2)
变量的自曾自减:
变量做某种运算后回存到此变量中;
比如:let i=$i +# #表示数字
let i+=#
[root@localhost ~]# i=1 [root@localhost ~]# let i=$i+2 [root@localhost ~]# echo $i 3
变量的自增:
var=$[$var+1]
let var+=1
let var++
[root@localhost ~]# i=2 [root@localhost ~]# let i+=1 [root@localhost ~]# echo $i 3
变量的自减:
var=$[$var-1]
let var-=1
let var--
[root@localhost ~]# i=2 [root@localhost ~]# let i-- [root@localhost ~]# echo $i 1
shell脚本之条件测试:
判断某需求是否满足,需要用到测试机制来实现:
1、通过命令执行后返回的状态码来判断
echo $? 0:表示正常 1-255:表示失败
[root@localhost ~]# sum=$[$sum1+$sum2] [root@localhost ~]# echo $? 0
2、通过测试表达式:
test expression 或[expression] 或[[expression]]
注意:EXPRESSION两端必须有空白字符,否则为语法错误;
2.1 数值测试
-eq:是否等于
-ne:是否不等于
-gt:是否大于
-lt:是否小于
-le:是否小于等于
示例:比较用户centos和ubuntu哪个的uid更大.
[root@localhost ~]# bash sum1.sh MAX is 1004 #!/bin/bash # a=$(id -u centos) b=$(id -u ubuntu) [ $a -gt $b ] && echo "MAX is $a" ||echo "MAX is $b"
2.2 字符串的比较
==:是否等于
建议变量比较的时候加上 “” [ ubuntu == "$u" ]
>:是否大于
<:是否小于
!=:是否小于
=~:左侧的字符串是否能被右侧的所匹配(包含)
-z:判断字符串是否为空
2.3 存在性测试
-a file
-e file 文件的存在性测试,如果存在,则为真
-s file 文件是否有内容
文件的类型测试
-b file :块设备文件
-c file:字符文件
-f file:文本
-d file:目录
-h 或者 -L : 是否为符号链接
-p file:管道文件
-S file:套接字文件,比如mysql的mysql.sock
[ -f /var/log/message ]
[ -f message]
2.4 文件权限测试
-r 对当前用户可读
-w 对当前用户可写
-x 对当前用户可执行
-O file 当前用户是否为文件属主
-G file 当前用户是否为文件属组
2.5 时间戳
-N file 文件自从上一次读操作之后,是否被改过
2.6 双目测试
FILE1 -ef FILE 是否指向同一文件系统的相同inode的硬链接
FILE1 -nt FILE file1文件是否新于file2
FILE1 -ot file file1文件是否旧于file2
shell脚本中可以用exit [n] n表示自己可以指定一个状态码
注意:shell脚本中,一旦遇到exit时,即将会退出
示例: 写一个脚本,通过命令传递两个文本路径给脚本,计算空行之和,参数大于两个报错
脚本: #!/bin/bash # [ $# -eq 2 ] && echo "" >/dev/null || echo "Unknow" sum=$(cat $1 |grep '^$' |wc -l) sum1=$(cat $2 |grep '^$' |wc -l) echo $sum echo $sum1 结果: [root@magedu md0]# bash sum.sh /etc/issue /etc/fstab 1 1
示例:通过参数传递一个用户名给脚本,此用户名如果不存在则添加,参数 不为1,则报错.
脚本: #!/bin/bash # [ $# -eq 1 ] && echo "" >/dev/null || echo "Unknow" if [ $ ] 结果: [root@magedu md0]# bash sum.sh centos centos is exist [root@magedu md0]# bash sum.sh centos1 [root@magedu md0]# vim sum.sh
3、条件判断(选择分支)
shell脚本的执行是顺序执行的,所以脚本无非就是语法加命令的堆积。
选择分支
单分支的if语句:
if 测试条件;
then
代码分支
fi
双分支的if语句
if 测试条件;then
条件为真的时候执行的分支
else
条件为假的时候执行的分支
fi
多分支的if语句
if 测试条件;then
条件为真的时候执行的分支
elif 测试条件;then
elif 测试条件;then
else
条件为假的时候执行的分支
fi
示例:通过命令参数,给定两个数字,输出其中交大的数值 ,如果参数不为2,则报错
脚本: #!/bin/bash # [ $# -eq 2 ] && echo "" >/dev/null || echo "Unknow" && exit 1 if [ $1 -eq $2 ];then echo "$1 is same $2" elif [ $1 -gt $2 ];then echo "max is $1" else echo "max is $2" fi 结果: [root@magedu md0]# bash sum.sh 2 3 max is 3 [root@magedu md0]# bash sum.sh 2 2 2 is same 2 [root@magedu md0]# bash sum.sh 3 2 max is 3 [root@magedu md0]# bash sum.sh 3 Unknow
shell脚本之用户交互:
read [option] 。。。。
-p:提示符
-t:timetout
写一个脚本,提示用户输入一个字符串,如果输入的是quit,则退出,否则输出其输入的内容
脚本:#!/bin/bash # read -p "please give me two charcet: " char if [ $char == "quit" ];then exit 1 else echo "$char" fi 结果:[root@magedu md0]# bash sum.sh please give me two charcet: quit [root@magedu md0]# bash sum.sh please give me two charcet: hello hello
磁盘高级管理:
RAID:磁盘冗余阵列
表示多个独立的硬盘按照不同的方式组合起来,形成一个虚拟的硬盘来提升性能和冗余。
可以解决的问题:
提供IO能力、提供磁盘的耐用性,RAID在管理和扩展、在性能上及在可靠性和可用性上都有优势
镜像冗余:比如raid1
1、镜像冗余使用了磁盘镜像的技术
2、磁盘镜像是一个简单的虚拟化技术,每个I/O操作都会在两个磁盘上执行,两个磁盘看起来像一个磁盘一样
3、镜像冗余可以提高磁盘的读性能
校验冗余:raid3 raid5
1、根据冗余算法计算阵列中成员磁盘上数据的校验信息,将校验信息保存在
2、其他的磁盘资源上
3、保证了数据的可靠性
4、和镜像冗余相比,校验冗余的开销更小
RAID实现的方式:
1、外接式磁盘阵列:通过扩展卡提供适配能力
2、内接式磁盘阵列:主板集成RAID控制器
3、software RAID:软磁盘阵列
RAID0:已条带的形式将数据均匀分布在阵列的各个磁盘上
组成:至少2个
优点:极高的磁盘读写速率、不存在校验,不占用太多CPU资源
缺点:无冗余,不能应用于对数据安全性较高的环境
RAID1:已镜像为冗余方式,对虚拟磁盘上的数据进行多分拷贝,放在磁盘成员上
组成:至少2个
优点:具有100%数据冗余性,提高最高的数据安全保障,理论上可以实现2倍的读取速率
缺点:开销大,磁盘利用率只有50%,在写性能上提示不大
RAID3:数据块被分为更小的块并行传输到各个成员磁盘上,同时计算XOR校验数据并存放到专用的校验磁盘上
组成:至少3块
优点:读写性能都比较好,当磁盘损坏时,对整体吞吐量影响较少,减少了开销
缺点:控制器设计复杂,校验磁盘的写性能有瓶颈
RAID5: 采用独立存取的阵列方式,校验信息被均匀的分散到阵列的各个磁盘上
组成:至少3个
优点:读性能比较高,中等的写性能,校验信息的分布式存取,避免出现写操作的瓶颈
缺点:控制器设计复杂,磁盘重建的过程比较复杂
RAID10:结合RAID1和RAID0,先镜像,在条带化
组成:最低4个
优点:读性能很高,写性能比较好,数据安全性好,允许同时有N个磁盘失效
缺点:磁盘空间开销大,利用率只有50%、
RAID50: 结合RAID5和RAID0,先实现RAID5,在条带化
组成:至少6个
优点:比RAID5有更好的读性能,比相同容量的RAID5重建时间更短,可以容许N个磁盘同时失效
缺点:设计复杂,比较难实现,同一个RAID5组内的两个磁盘失效会导致整个阵列的失效
在做多RAID组合当中,RAID0的性能最好,RAID1的数据冗余度最高,相同容量下RAID和RAID1的磁盘开销最大。
软RAID阵列,比如用mdadm工具
mdadm命令:
选项:
-C:创建
-A:装配
-F:监控
-f:人为的损坏 -r(移除) -a(添加)
-n # 使用#个设备来创建次RAID
-l # 指定要创建的RAID级别
-a (yes|no)自动创建目标RAID设备文件
-c 指定块大小
-x # 指定空闲盘个数
-D 显示raid的详细信息
-S 停止RAID
示例:创建一个RAID1阵列,要求文件系统为ext4,有一个空闲盘,开机自动挂载到/md0目录下。
先创建三个Linux raid autodetect磁盘
/dev/sdb5 12587008 12791807 102400 fd Linux raid autodetect
/dev/sdb6 12793856 12998655 102400 fd Linux raid autodetect
/dev/sdb7 13000704 13205503 102400 fd Linux raid autodetect
[root@magedu md0]# mdadm -C /dev/md127 -n 2 -l 1 -a yes -c 1M -x 1 /dev/sdb[5,6,7] [root@magedu md0]# mdadm -D /dev/md127
可以人为的损坏:mdadm /dev/md127 -f /dev/sdb5
可以移除:mdadm /dev/md127 -r /dev/sdb5
可以添加:mdadm /dev/dm127 -a /dev/sdb5