Shell典型应用
#主控制脚本实现
Shell场景脚本
- 提取Linux操作系统信息
- 获取操作系统运行状态
- 分析应用状态
- 应用日志分析
VIM编辑器设置
为什么要设置VIM编辑器
- 友好的设置VIM编辑器,能更加方便、快捷的提高Shell语言编程效率
设置方式分类
临时性的设置
永久性的设置(修改vimrc文件,本章主要介绍该方式)
1
2
3
4
5
6
7
8
9
10
11
12
13
14[root@lvjing ~]# cat /etc/vimrc
if v:lang =~ "utf8$" || v:lang =~ "UTF-8$"
set fileencodings=ucs-bom,utf-8,latin1
endif
set nocompatible " Use Vim defaults (much better!)
set bs=indent,eol,start " allow backspacing over everything in insert mode
"set ai " always set autoindenting on
"set backup " keep a backup file
set viminfo='20,\"50 " read/write a .viminfo file, don't store more
" than 50 lines of registers
set history=50 " keep 50 lines of command line history
set ruler " show the cursor position all the time
……针对于某个用户下的.vimrc编辑功能的设置
1
[root@lvjing ~]# vim /home/{用户名}/.vimrc
VIM编辑器设置的内容
语法高亮
1
2syntax on 开启
syntax off 关闭显示行号
1
set number
自动缩进
1
2set autoindent
set cindent自动加入文件头
1
2
3
4
5
6
7
8
9
10
11
12
13
14autocmd BufNewFile *.py,*.sh, exec ":call SetTitle()"
let $author_name="jinglv"
let $author_email="lvjing0705@126.com"
func SetTitle()
if &filetype == 'sh'
call setline(1,"\######################################################")
call append(line("."),"\# File Name:".expand("%"))
call append(line(".")+1,"\# Author:".$author_name)
call append(line(".")+2,"\# Email:".$author_email)
call append(line(".")+3,"\# Created Time:".strftime("%c"))
call append(line(".")+4,"\#==============================================")
call append(line(".")+5,"\#!/bin/bash")
endif
endfunction
Shell高亮显示
基本格式
1
echo -e 终端颜色 + 显示内容 + 结束后的颜色
例如:
1
2echo -e "\e[1;30m Jing sey hi~ \e[1;0m"
echo -e "\e[1;30m" "Jing sey hi~" $(tput sgr0)
场景脚本结构
Shell中关联数组
关联数组:
- 普通数组:只能使用整数作为数组索引
- 关联数组:可以使用字符串作为数组索引
声明关联数组变量:
1 | declare -A ass_array1 |
数组名[索引]=变量值
1 | ass_array[index1]=pear |
脚本实现
1 | ##################################################### |
测试执行
1 | [root@lvjing use]# ls |
系统信息及运行状态获取
脚本:system_monitor.sh
功能一:提取操作系统信息(内核、系统版本、网络地址等)
Shell脚本实现
1 | ##################################################### |
执行结果
1 | [root@lvjing use]# sh system_monitor.sh |
功能二:分析系统的运行状态(CPU负载、内存及磁盘使用率等)
分析系统的运行状态
系统是使用的内存和应用使用内存区别
- 系统使用内存=Total-Free
- 应用使用内存=Total-(Free+Cached+Buffers)
内存中cache和buffer区别
内存类型 功能 读取策略 Cache 缓存主要用于打开的文件 最少使用原则(LRU) Buffer 分缓存主要用于目录项、inode等文件系 先进先出策略 Shell脚本实现
1
2
3
4system_men_usages=$(awk '/MemTotal/{total=$2}/MemFree/{free=$2}END{print (total-free)/1024}' /proc/meminfo)
apps_men_usages=$(awk '/MemTotal/{total=$2}/MemFree/{free=$2}/^Cached/{cached=$2}/Buffers/{buffers=$2}END{print (total-free-cached-buffers)/1024}' /proc/meminfo)
echo -e '\E[32m' "System memuserages:" $reset_terminal $system_men_usages
echo -e '\E[32m' "Apps memuserages:" $reset_terminal $apps_men_usages
CPU负载概念
系统负荷为0,意味着大桥上一辆车也没有。
系统负荷为0.5,意味着大桥一半的路段有车。
系统负荷为1.0,意味着大桥的所有路段都有车,也就是说大桥已经”满”了。但是必须注意的是,直到此时大桥还是能顺畅通行的。
系统负荷为1.7,意味着车辆太多了,大桥已经被占满了(100%),后面等着上桥的车辆为桥面车辆的70%。以此类推,系统负荷2.0,意味着等待上桥的车辆与桥面的车辆一样多;系统负荷3.0,意味着等待上桥的车辆是桥面车辆的2倍。总之,当系统负荷大于1,后面的车辆就必须等待了;系统负荷越大,过桥就必须等得越久。
CPU的系统负荷,基本上等同于上面的类比。大桥的通行能力,就是CPU的最大工作量;桥梁上的车辆,就是一个个等待CPU处理的进程(process)。
Linux获取CPU负载值的命令
1
top -n 1 -b |grep "load average:" |awk '{print $12 $13 $14}'
系统磁盘容量
1
2
3
4
5
6
7
8[root@lvjing use]# df -h
文件系统 容量 已用 可用 已用% 挂载点
devtmpfs 1.8G 0 1.8G 0% /dev
tmpfs 1.8G 0 1.8G 0% /dev/shm
tmpfs 1.8G 572K 1.8G 1% /run
tmpfs 1.8G 0 1.8G 0% /sys/fs/cgroup
/dev/vda1 40G 9.6G 31G 24% /
……- Filesystem(文件系统):磁盘设备名称
- Size(容量):设备总容量
- Used(已用):已用容量
- Avail(可用):可用容量
- Use%(已用%):使用容量百分比
- Mounted on(挂载点):设备挂载的系统目录文件
系统磁盘已使用(%),Linux命令如下:
1
df -h | grep -vE '文件系统|tmpfs' | awk '{print $1 " " $5}'
注意:
df -h
输出的中英文,和系统有关
完整Shell脚本
1 | ###################################################### |
脚本执行结果如下:
1 | [root@lvjing use]# sh system_monitor.sh |
nginx和mysql应用状态分析
脚本:check_server.sh
应用运行状态监控脚本
利用操作系统命令:
- 网络命令:ping、nslookup、nm-tool、tracertroute、dig、telent、nc、curl
- 监控进程:ps、netstat、pgrep
利用客户端命令、工具:
- 应用客户端:mysql、ab、mongo、php、jstack
- 第三方工具包:nginxstatus、nagios-libexec
服务端接口支持:
- nginx-http_stub_status_module
- nutcracker监控集群(redis、memcache)状态
- Mongodb
……
nginx监控脚本
监控nginx需要在nginx在配置文件中开启监控,Linux监控命令如下:
1 | curl -m 5 -s -w %{http_code} http://8.140.112.109/nginx_status -o /dev/null |
Shell脚本如下:
1 | ###################################################### |
未启动nginx情况下,执行脚本结果如下
1 | [root@lvjing use]# sh check_server.sh |
监控MySQL主从复制状态
搭建MySQL主从复制环境
基于mysql客户端连接,获取主从复制状态
1
mysql> show slave status\G;
- Slave_IO_Running – IO线程是否有连接到主服务器上
- Seconds_Behind_Master – 主从同步的延时时间
在MySQL从库里设置监控普通用户
1
mysql> grant replication slave, replication client on *.* to 用户名@'%' identified by '密码';
Shell脚本如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19mysql_slave_server='8.140.112.109'
mysql_slave_port='3306'
mysql_slave_user='rep'
mysql_slave_pass='123123'
check_mysql_server()
{
nc -z -w2 ${mysql_slave_server} ${mysql_slave_port} &>/dev/null
if [ $? -eq 0 ];then
mysql -u${mysql_slave_user} -p${mysql_slave_pass} -h${mysql_slave_server} -e "show slave status\G" | grep "Slave_IO_Running" | awk '{if($2!="Yes"){print "Slave thread not running!";exit 1}}'
if [ $? -eq 0 ];then
# 获取主从的延时
mysql -u${mysql_slave_user} -p${mysql_slave_pass} -h${mysql_slave_server} -e "show slave status\G" | grep "Seconds_Behind_Master"
fi
else
echo "Connect MySQL Server not Succeeded!"
fi
}
# 函数调用
check_mysql_server完整的Shell脚本
1 | ###################################################### |
应用日志分析
常见系统日志文件
- 系统日志
- /var/log/messages 系统主日志文件
- /var/log/secure 认证、安全
- /var/log/dmesg 和系统启动相关
- 应用服务
- access.log nginx访问日志
- mysqld.log mysqld运行日志
- xferlog 和访问FTP服务器相关
- 程序脚本
- 开发语言:C、C++、Java、PHP
- 框架:Django、MVC、Servlet
- 脚本语言:Shell、Python
nginx的log_format介绍
日志输出的格式,在nginx.conf配置文件中,进行设置
nginx大致有三类变量能够记录在log_format 中
- HTTP请求变量- arg_PARAMETER http_HEADER send_http_HEADER(服务端返回)
- 内置变量- Nginx内置的
- 自定义变量- 自己定义的
变量含义:
- remote_addr:对应客户端的地址
- remote_user:是请求客户端请求认证的用户名,如果没有开启认证模块的话是值为空。
- time_local:表示nginx服务器时间
- request:表示request请求头的行
- status:表示response的返回状态
- body_bytes_sent:表示从服务端返回给客户端的body数据大小
- http_referer:表示请求的上一级页面
- http_user_agent:表示agent信息 http_x_forwarded_for:会记录每一级请求中信息
HTTP状态码
1**
信息,服务器收到请求,需要请求者继续执行操作2**
成功,操作被成功接收并处理3**
重定向,需要进一步的操作以完成请求4**
客户端错误,请求包含语法错误或无法完成请求5**
服务器错误,服务器在处理请求的过程中发生了错误
日志分析脚本
nginx.log日志的示例:
1 | 113.87.161.17 - - [05/Dec/2018:00:11:39 +0000] "GET /cable HTTP/1.1" 101 3038 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36" 112.418 112.418 . |
脚本实现功能介绍
功能一:分析HTTP状态码在100-200、200-300、300-400、400-500、500以上,五个区间的请求条数
获取HTTP协议及状态码,Linux命令如下
1
2
3
4
5
6
7[root@lvjing ~]# cat nginx.log | grep -ioE "HTTP\/1\.[1|0]\"[[:blank:]][0-9]{3}"
HTTP/1.1" 101
HTTP/1.1" 101
HTTP/1.1" 301
HTTP/1.1" 301
HTTP/1.1" 200
……Shell脚本实现如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27resettem=$(tput sgr0)
logfile_path='/root/nginx.log'
check_http_status()
{
http_status_codes=(`cat $logfile_path | grep -ioE "HTTP\/1\.[1|0]\"[[:blank:]][0-9]{3}" | awk -F"[ ]+" '{
if($2>=100 && $2<200)
{i++}
else if($2>=200 && $2<300)
{j++}
else if($2>=300 && $2<400)
{k++}
else if($2>=400 && $2<500)
{n++}
else if($2>=500)
{p++}
}END{
print i?i:0,j?j:0,k?k:0,n?n:0,p?p:0,i+j+k+n+p
}'`)
echo -e '\E[33m' "The number of http status[100+]:" ${resettem} ${http_status_codes[0]}
echo -e '\E[33m' "The number of http status[200+]:" ${resettem} ${http_status_codes[1]}
echo -e '\E[33m' "The number of http status[300+]:" ${resettem} ${http_status_codes[2]}
echo -e '\E[33m' "The number of http status[400+]:" ${resettem} ${http_status_codes[3]}
echo -e '\E[33m' "The number of http status[500+]:" ${resettem} ${http_status_codes[4]}
echo -e '\E[33m' "All request numbers:" ${resettem} ${http_status_codes[5]}
}
# 函数调用
check_http_status
功能二:分析日志中HTTP状态码为404、500的请求条数
Shell脚本如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16check_http_code()
{
http_code=(`cat $logfile_path | grep -ioE "HTTP\/1\.[1|0]\"[[:blank:]][0-9]{3}" | awk -v total=0 -F '[ ]+' '{
if($2!="")
{code[$2]++;total++}
else
{exit}
}END{
print code[404]?code[404]:0,code[500]?code[500]:0,total
}'`)
echo -e '\E[33m' "The number of http status[404+]:" ${resettem} ${http_code[0]}
echo -e '\E[33m' "The number of http status[500+]:" ${resettem} ${http_code[1]}
echo -e '\E[33m' "All request numbers:" ${resettem} ${http_code[2]}
}
# 函数调用
check_http_code
完整的Shell脚本
1 | ###################################################### |
执行结果如下
1 | [root@lvjing use]# sh check_http_log.sh |