一.shell 简介
• 两种执行命令的方式:交互式:解释执行用户的命令,用户输入一条命令,Shell就解释执行一条。
批处理:用户事先写一个Shell脚本(Script),其中有很多条命令,让Shell一次把这些命令执行完,而不必一
条一条地敲命令。
• 常用的Shell
Bourne Shell(/usr/bin/sh或/bin/sh)
Bourne Again Shell(/bin/bash 在日常工作中被广泛使用)
C Shell(/usr/bin/csh)
K Shell(/usr/bin/ksh)
• 如何创建一个shell脚本?
vi test.sh 创建一个名为test.sh的shell进行编辑
#!/bin/bash
#this is a test by kahn
echo "hell world”
chmod +x ./test.sh #使脚本具有执行权限 运行脚本即可 sh test.sh
二.Shell相关基础掌握
要写一个shell脚本,首先要熟悉常用的命令及基本知识,主要有以下几点: 变量、文本字符处理、判断及比较。
1.变量:定义变量时,变量名不加美元符号($),如:varName=“value”。变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:首个字符必须为字母(a-z,A-Z),中间不能有空格,可以使用下划线(_),不能使用标点符号。变量中我们用到最多的还有一些符号表示的特殊变量,在以后写shell脚本的过程中尤为重要,你不了解一下相关变量的本意,根本无从下手。下面是常用的特殊变量:
变量 | 含义 |
$0 | 当前脚本的文件名 |
$n | 传递给脚本或函数的参数,n 是一个数字,表示第几个参数 |
$# | 传递给脚本或函数的参数个数 |
$* | 传递给脚本或函数的所有参数 |
$? | 上个命令的退出状态,或函数的返回值 |
$$ | 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID |
$_ | 记录上一个操作指令的最后一个参数 |
处理领域,比较重要常用的工具及命令就是的grep、 sed 、awk ,sort。grep负责找出特定的行,sed则可以实现更新插入删除等写操作,awk能将行拆分成多个字段,sort帮我们依据不同的数据类型进行排序,这些命令通常搭配正则表达式来使用。
grep命令行匹配模式
grep [options] files
其中options(选项)主要为下表:
选项 | 功能描述 |
-i | 忽略大小写 |
-w | 匹配整词 |
-v | 不匹配匹配的 |
-c | 输出匹配的数目(行数) |
-l | 输出匹配的文件名 |
-L | 输出不匹配的文件名 |
1.忽略大小写(可以看到无论是a还是A的行都可以显示)
[root@localhost shell]# less a.sh
a:bc:d
A:B
1:5:8
[root@localhost shell]# less a.sh | grep -i "a"
a:bc:d
A:B
2.匹配整词(可以看到只有hehe的行显示出来)
[root@localhost shell]# less hello.sh
hello world!
hehe
[root@localhost shell]# less hello.sh | grep -w he
[root@localhost shell]# less hello.sh | grep -w hehe
Hehe
3.不匹配匹配的(可以看到只显示无world的行)
[root@localhost shell]# less hello.sh
hello world!
hehe
[root@localhost shell]# less hello.sh | grep -v world
hehe
4.输出匹配的行数(可以看到含有a的行数为1)
[root@localhost shell]# less a.sh
a:bc:d
A:B
1:5:8
[root@localhost shell]# grep -c a a.sh
15
. 输出匹配的文件名(可以看到含有world则文件名被输出)
[root@localhost shell]# less hello.sh
hello world!
hehe
[root@localhost shell]# grep -l world hello.sh
hello.sh
6.输出不匹配的文件名(可以看到含有world则文件名被输出)
[root@localhost shell]# less hello.sh
hello world!
hehe
[root@localhost shell]# grep -L world hello.sh
[root@localhost shell]# grep -l world hello.sh
hello.sh
sed命令行匹配模式sed [options]‘command’files
其中options(选项)及command命令主要为下表:
选项(options) | 含义 |
-i | 直接修改读取的档案内容,而不是由屏幕输出。 |
-n | sed处理默认全部输出,加上-n则经过sed 特殊处理的那一行(或者动作)才会被 列出来 |
命令(command) | 含义 |
a | 新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行) |
c | 取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行 |
d | 删除,因为是删除啊,所以 d 后面通常不接任何 |
i | 插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行) |
p | 列印,亦即将某个选择的资料印出。通常 p 会与参数 sed -n 一起运作 |
s | 取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法 |
1.a新增一行(可以看到加上i参数,文件新增了一行)
[root@localhost shell]# less a.sh
a:bc:d
A:B
1:5:8
[root@localhost shell]# sed -i "1a this is a test" a.sh
[root@localhost shell]# less a.sh
a:bc:d
this is a test
A:B
1:5:8
2. c取代(可以看到在包含A:的行替换了)
[root@localhost shell]# less a.sh
a:bc:d
A:B
1:5:8
[root@localhost shell]# sed '/A:/c\this is ok' a.sh
a:bc:d
this is ok
1:5:8
3. d 删除(可以看到1和2行被删除)
[root@localhost shell]# less a.sh
a:bc:d
A:B
1:5:8
[root@localhost shell]# sed -i '1,2d' a.sh
[root@localhost shell]# less a.sh
1:5:8
4.i插入(可以看到在第一行前面hello插进去了)
[root@localhost shell]# less a.sh
1:5:8
[root@localhost shell]# sed -i '1i hello' a.sh
[root@localhost shell]# less a.sh
hello
1:5:8
5.s替换(可以看到5:被替换)
[root@localhost shell]# less a.sh
hello
1:5:8
[root@localhost shell]# sed 's/5:/this is ok/g' a.sh
hello
1:this is ok8
awk是一个强大的文本分析工具,在对文本文件的处理以及生成报表,awk是无可替代的。awk认为文本文件都是结
构化的,它将每一个输入行定义为一个记录,行中的每个字符串定义为一个域(段),域和域之间使用分割符分割,域之间
用空格,tab键或其他符号进行分割,分割域的符号叫作分割符。用$符号加数字来记录域,$0代表全部域,$1代表第一
个域,$n代表第n个域。
awk工作原理:awk 会把每行进行一个拆分,用相应的命令对拆分出来的“段”进行处理
(1)行工作模式,读入文件的每一行,会把一行的内容,存到$0里
(2)使用内置的变量FS(段的分隔符,默认用的是空白字符),分割这一行,把分割出来的每个段存到相应的变量$(1-n)
(3)输出的时候按照内置变量OFS(out FS),输出
(4)读入下一行继续操作
awk pattern(模式) { action }(动作)
例:常见的分割模式awk -F 域分隔符‘{print 域}' files 默认的分割符为空格
[root@tx3 ~]# echo "this is a book" > awk.txt
[root@tx3 ~]# awk '{print $2,$1,$3,$4}' awk.txt
is this a book
下面是取出分号前的第一个域值
[root@localhost shell]# less a.sh
a:bc:d
1:5:8
[root@localhost shell]# less a.sh | awk -F ":" '{print $2}'
bc
5
sort命令行匹配模式sort [options] files 其中options(选项)为下表:
命令(command) | 含义 |
-b | 忽略每行前面开始出的空格字符 |
-u | 去除重复的行 |
-n | 依照数值的大小排序。 |
-t | <分隔字符>指定排序时所用的栏位分隔字符 |
-k | 选择以哪个区间进行排序 |
-r | 以相反的顺序来排序。 |
1.b忽略每行前面开始出的空格字符
[root@localhost shell]# less a.sh
banana
apple
pear
orange
[root@localhost shell]# sort -b a.sh
apple
banana
orange
Pear
2.u去除重复的行
[root@localhost shell]# less a.sh
banana
apple
banana
pear
[root@localhost shell]# sort -u a.sh
apple
banana
pear
3.n按数值大小排序
[root@localhost shell]# less a.sh
4b1anana
2ap3ple
banana
10pear
[root@localhost shell]# sort -n a.sh
banana
2ap3ple
4b1anana
10pear
4.指定区间进行排序
[rocrocket@]$ less a.sh
banana:30:5.5
apple:10:2.5
orange:20:3.4
[rocrocket@]$ sort -n -k 2 -t : a.sh
apple:10:2.5
orange:20:3.4
banana:30:5.5
5.-r反向排列
[root@localhost shell]# less a.sh
banana
ap3ple
oanana
pear
[root@localhost shell]# sort -r a.sh
pear
oanana
banana
ap3ple
正则表达式
很多linux shell编程的工具和命令普遍使用到了正则表达式,如grep,sed和awk等,两者相结
合能够灵活的进行文本搜索及处理。在这之前我们会和shell中搜索匹配文件经常使用到的通配
符搞混淆,虽然有共同的符号但是两者不同,下面主要介绍通配符和正则表达式的用法和区别。
通配符只适用于匹配目录及文件,常用的通配符有以下几种:
符号 | 含义 |
* | 代表匹配0到多个任意字符 |
? | 代表一定有一个任意字符 |
[ ] | 代表一定有一个字符在括号内;如[abc],[a-z],[0-9] |
例如:在当前路径下搜索名字开头为shel的目录
[root@lhost home]# find . -type d -name"shel*"
./shell
./shel3
./shelabc
搜当前路径所有后缀为.sh文件中包含log字符的文件
[root@localhost shell]# grep 'log' *.sh
backuplog.sh:log_path=/var/log
b.sh:/sbin/nologin
搜索当前路径下名为”一个字符+.sh”文件中包含log的文
件
[root@localhost shell]# grep 'log' ?.sh
b.sh:/sbin/nologin
搜索当前路径下名为”[a-z]est.sh”文件
[root@localhost shell]# find . -name [a-z]est.sh
./test.sh
正则表达式的基本元素包括普通字符和元字符,例如,a,b,1,2等字符属于普通字符,而*,^,[ ]
等就属于元字符。
常见正则的元字符有已下几种:
符号 | 含义 | 说明 |
* | 匹配前一个字符的零次或多次出现 | a*可以表示a, aa ,aaaa等 |
^ | 匹配行首的位置 | ^ab表示行开头为ab的行 |
$ | 匹配行首的位置 | ;$表示行尾为;的行 |
. | 代表单个字符 | a.b可以表示acb,adb,a0b |
[ ] | 匹配括号内任意一个字符 | [acd]b可以表示ab,cb,db |
+ | 匹配前一个字符的一次或多次出现 | a*可以表示aa ,aaaa等 |
条件判断是shell脚本经常用到的
1、通过if条件语句来判断,基本语法:
if [ command ]; then
符合该条件执行的语句
fi
判断方式如下几类:
数值判断:
[ a -eq b ] a和b两数相等返回为真 ,=
[ a -ne b ] a和b两数不等返回为真 ,<>
[ a -gt b ] a大于b返回为真 ,>
[ a -ge b ] a大于等于b返回为真,>=
[ a -lt b ] a小于b返回为真 ,<
[ a -le b ] a小于等于b返回为真,<=
逻辑判断:
[ ! a ] 逻辑非,如果 a 是false则返回为真。
[ a1 -a a2 ] 逻辑与,如果 a1 and a2 全真则返回
为真。
[ a1 -o a2 ] 逻辑或,如果 a1 或者 a2 为真则返回
为真。
文件/目录判断:
[ -d FILE ] 如果 FILE 存在且是一个目录则返回为真。
[ -e FILE ] 如果 指定的文件或目录存在时返回为真。
[ -f FILE ] 如果 FILE 存在且是一个普通文件则返回为真。
三.shell使用
特别擅长系统管理任务,尤其适合那些易用性、可维护性和便携性比效率更重要的任务。在开发与运维过程中经常运用到,它能处理一些简单重复性的操作,在服务器中经常用其来处理一些任务。如自动化部署、监控服务及磁盘、备份、清除处理文件。
脚本进行定时执行我们一般使用crontab, crontab用于设置周期性被执行的指令,它是一个可以根据时间、日期、月份、星期的组合来调度对重复任务的执行的守护进程命令。
crontab文件的格式:minute hour day month weekday command
minute:分,值为0-59
hour:小时,值为1-23
day:天,值为1-31
month:月,值为1-12
weekday:星期,值为0-6(0代表星期天,1代表星期一,以此类推)
command:要执行的程序路径(设置为脚本的绝对路径)
例如: #每天早上6点10分
10 6 * * * sh /home/test.sh
#每两个小时
0 */2 * * * sh /home/test.sh
1.下面主要是持续部署工具中常见的触发部署脚本
#启动tomcat服务
start_tomcat()
{
ps -ef | grep -w "tomcat" | grep -v "grep" > /dev/null
ret=$?
if [ $ret -ne 0 ];then
cd /appserver/apache-tomcat-7.0.68/bin/
sh startup.sh > /dev/null
fi
}
#关闭tomcat服务stop_tomcat()
{
ps -ef | grep -w "tomcat" | grep -v "grep" > /dev/null
ret=$?
if [ $ret -eq 0 ];then
cd /appserver/apache-tomcat-7.0.68/bin/
sh shutdown.sh > /dev/null
sleep 3
ps -ef | grep -w "tomcat" | grep -v "grep" > /dev/null
ret=$?
if [ $ret -eq 0 ];then
echo "无法通过脚本停止服务!"
else
echo "脚本停止服务成功!!!"
fi
fi
}
#部署服务tomcat()
{
echo "准备停止服务!"
stop_tomcat
mkdir -p /home/backup/ ` date +%Y-%m-%d-%s`
cp –r /appserver/apache-tomcat-7.0.68/webapps/jenkins.war “$_”
cp -r /home/jenkins/jenkins.war /appserver/apache-tomcat-7.0.68/webapps
echo "重启服务!"
start_tomcat
echo "完成部署任务!"
}
tomcat
2.监控服务及磁盘下面主要实现的是一台主机监控多台服务器上的服务和磁盘脚本
#主函数模块
#!/bin/bash
conf_file=/root/monitor/configurations.properties
main()
{
IFS=$'\n'
for list in `cat $conf_file | grep -v ^# `
do
ip_name=`echo $list |awk '{print $1}'`
echo "================================================="
echo "服务器IP地址为:$ip_name"
check_tomcat
check_disk
done
}
main
其中configurations.properties配置如下:
#第1列IP地址 第2列中间件类型 #第3列检查磁盘的路径 #第4列中间件安装的路径
192.168.137.2 tomcat /var /appserver/apache-tomcat-7.0.68
192.168.137.4 tomcat /home /appserver/apache-tomcat-7.0.68
#检查磁盘
check_disk(){
vlv=`echo $list|awk '{print $3}'`
nu=`ssh $ip_name df -h $vlv|awk 'NR==2{print int($5)}'`
if [[ $nu -le 30 ]];then
echo "$vlv磁盘空间:$nu%"
else
echo "$vlv磁盘空间:$nu%"
fi
}
#检查服务
check_tomcat()
{
app_name=`echo $list|awk '{print $4}'`
ssh $ip_name "ps -ef |grep -w $app_name | grep -v grep" > /dev/null
ret=$?
if [ $ret -eq 0 ];then
echo "$app_name 服务正常"
else
echo "$app_name 服务停止"
fi
}