shell脚本-工作练习篇

瞎扯时间

    人的惰性真的很难去戒掉,每天工作下班回家后,只想瘫倒在床上,玩玩手游,刷刷抖音,甚至看看无聊至极的“爽文”,对于学习、看书啥的,完全提不起兴趣,也许正是因为如此,我才显得这么平庸而无趣吧。
    现在,Now,正在清明假期,两个室友都出去浪去了,我一个人在租房里,把客厅打扫了一遍,然后就是坚持了运动,算是一点小改变吧,运动也近两周了,每天都还坚持着,只是熬夜这个糟糕的习惯依然没有戒掉,这是下一阶段的目标吧,早睡早起!

    还一个目标,多多学习多多写东西,去年底计划要每个月看一本书的,今年基本上没开始,惭愧,四月了,还不开始补就晚了!平时有时间也准备多写写博客,嗯,目标在前方。

正题

    最近两天在办公室工作量不大,想到平时在工作中,服务器一般都是Linux操作系统,跟踪 DM 数据库报错、慢等问题,都是把日志文件打包下载到 Win 环境,借助 UE 或者 Notepad++ 来分析,但是日志文件一般都比较大,这么一个过程其实还蛮耗时间的,就想着能不能写写shell脚本来工作,当然,这才刚刚开始,只是一个练习。

    第一个脚本,统计操作系统的基础信息,比如操作系统版本、cpu信息等,因为项目很多,每个项目用到的服务器也不少,经常需要统计操作系统的一些信息,这是一个小繁琐的事情,就写了个脚本,其实这个还蛮简单的,就是把平时经常用到的命令打印到一个指定的文件而已,很简单。

#!/bin/bash
# system stats script
# Write this shell script by Light Ink in April 2019.

# 清空日志文件
echo "" > L-Ink_sys_stats.log

# 标题符
title_char="============================="
echo -e "${title_char} SYSTEM STATS ${title_char}\n" >> L-Ink_sys_stats.log

# 打印系统时间
sys_date=`date '+%Y-%m-%d %H:%M:%S'`
echo -e "System Date:${sys_date}\n" >> L-Ink_sys_stats.log

# 分割符
cutter_char="------------------------------------------------------------------------"
echo -e "${cutter_char}\n" >> L-Ink_sys_stats.log

# 统计操作系统版本
echo "[OS version]" >> L-Ink_sys_stats.log
command="`cat /etc/redhat-release`"
echo -e "${command}\n" >> L-Ink_sys_stats.log
echo -e "${cutter_char}\n" >> L-Ink_sys_stats.log

# 统计CPU信息
echo "[CPU model]" >> L-Ink_sys_stats.log
command="`cat /proc/cpuinfo | grep name | cut -f2 -d:`"
echo -e "${command}" >> L-Ink_sys_stats.log
echo "[Physical Cpu nums]" >> L-Ink_sys_stats.log
command="`cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l`"
echo -e "${command}" >> L-Ink_sys_stats.log
echo "[Cpu Cores]" >> L-Ink_sys_stats.log
command="`cat /proc/cpuinfo| grep "cpu cores"| uniq`"
if [ ! -n "$command" ]; 
then
  command="NULL"
fi
echo -e "${command}" >> L-Ink_sys_stats.log
echo "[Processor]" >> L-Ink_sys_stats.log
command="`cat /proc/cpuinfo| grep "processor"| wc -l`"
echo -e "${command}\n" >> L-Ink_sys_stats.log
echo "[CPUINFO]" >> L-Ink_sys_stats.log
command="`cat /proc/cpuinfo`"
echo -e "${command}\n" >> L-Ink_sys_stats.log
echo -e "${cutter_char}\n" >> L-Ink_sys_stats.log

# 统计内存信息
echo "[Mem Info]" >> L-Ink_sys_stats.log
command="`cat /proc/meminfo`"
echo -e "${command}\n" >> L-Ink_sys_stats.log
echo -e "${cutter_char}\n" >> L-Ink_sys_stats.log

# 磁盘使用情况
echo "[Disk Using Info]" >> L-Ink_sys_stats.log
command="`df -h`"
echo -e "${command}\n" >> L-Ink_sys_stats.log
echo -e "${cutter_char}\n" >> L-Ink_sys_stats.log

# 磁盘挂载情况
:<<eof
echo "[Disk Mount Info]" >> L-Ink_sys_stats.logi
command="`fdisk -l`"
echo -e "${command}\n" >> L-Ink_sys_stats.log
echo -e "${cutter_char}\n" >> L-Ink_sys_stats.log
eof

echo "[Disk Mount Info]" >> L-Ink_sys_stats.log
sysuser="`echo $USER`"
if [ $sysuser = "root" ]; then
  command="`fdisk -l`"
  echo -e "${command}\n" >> L-Ink_sys_stats.log
  echo -e "${cutter_char}\n" >> L-Ink_sys_stats.log
else
  echo -e "(State Disk Info Error)Permission denied!" |tee -a L-Ink_sys_stats.log
  echo -e "\n${cutter_char}\n" >> L-Ink_sys_stats.log
fi

# IO 统计 
echo "[IO]" >> L-Ink_sys_stats.log
command="`iostat -x 3 5`"
echo -e "${command}\n" >> L-Ink_sys_stats.log

:<<eof
# 是否继续统计 DM 数据库 想了想,这一块功能不太好做,关闭此功能开发。
flag=0
for ((i=0;i<3;i++)) 
do 
  read -p "Check DMDB info?[y/n]" input
  if [ $input = "y" -o $input = "Y" ]; then
    flag=1
    echo "To be continue..." >> L-Ink_sys_stats.log
    break
  elif [ $input = "n" -o $input = "N" ]; then
    flag=1
    break
  else
    echo "Input Error!"
  fi
done

if [ $flag -eq 0 ]; then
  echo "【Error】Input error more than 3 times!!" |tee -a L-Ink_sys_stats.log
  exit 1
fi
eof

echo -e "${title_char}    - End -    ${title_char}\n" >> L-Ink_sys_stats.log
echo "SYSTEM STATS DONE!"


    好久没有写 shell ,基本上是个新手,在上手过程中,在 if 判断语法中还吃了小亏, [] 一般不能邻着变量名,要不然就报错,还有经常获取变量的值,忘记加 $ 符,很蠢,需要多写写。
    另外,在这个脚本中,有块注释方法 :<<eof 与 eof ,期间还想着弄一些骚操作,包括自定义异常抛出,但是最后还是觉得没必要,反而太繁琐,命令错误本身就有系统异常,所以就用块注释了。

    第二个脚本,是一个需要一些时间不断去完善的脚本,分析 DM 库(达梦数据库) 日志的脚本,目前实现了两个小功能,筛选报错语句和超过1s的慢SQL的功能。

#!/bin/bash
# analysis dmsql logs
# Write this shell script by Light Ink in April 2019.
# v1.0
read -p "Please input the log name:" in_logname
arr=($in_logname)

echo "--------------------------------"
echo "The Options:"
echo "1.Find Errors"
echo "2.Filter SQLs More Than 100ms"
echo "3.Filter SQLs More Than 1000ms"
echo "4.exit"
echo "--------------------------------"
read -p "Choose one option please:" in_op

# 将日志中的错误信息,筛选输出至文本
Find_Errs(){
  for element in ${arr[@]}
  do
    command_01="`cat $element |grep "ERR("`"
    echo "====================== log name: "$element" =======================" >> $1
    echo "${command_01}" >> $1
  done
}

# 将日志中超过100ms的sql语句,筛选输出至文本
Filter_SQL_100ms(){
  for element in ${arr[@]}
  do 
    command_02="`cat $element |egrep "[1-9][0-9][0-9]\(ms\)"`"
    echo "====================== log name: "$element" =======================" >> $1
    echo "${command_02}" >> $1
  done
}

# 将日志中超过1000ms的sql语句,筛选输出至文本
Filter_SQL_1000ms(){
  for element in ${arr[@]}
  do
    command_03="`cat $element |egrep "[1-9][0-9][0-9][0-9]\(ms\)"`"
    echo "====================== log name: "$element" =======================" >> $1
    echo "${command_03}" >> $1
  done
}

# 创建文件夹目录
Create_dir(){
# ls -l 以 d 开头的即文件夹,通过 sed 将多个空格替换为单个空格,再以 cut 分割,取文件名,文件名会以空格为间隔符存到变量中
command_ls="`ls -l|egrep "^d"|sed -e 's/[[:space:]][[:space:]]*/ /g' | cut -d ' ' -f 9`"
dirname=($command_ls)
# 判断目录是否已经存在的标志,0表示不存在
dir_exst_flag=0
# 遍历数组,如果存在目录名,即将标志置为1,反之不变
for i in ${dirname[@]}
do
  if [ $1 == $i ]; then
    dir_exst_flag=1
  fi
done

if [ $dir_exst_flag = 0 ]; then
  mkdir $1
else
  return
fi
}

currentMon=`date "+%Y%m"`
currentTime=`date "+%Y%m%d%H%M%S"`
if [ $in_op = "1" ]; then
  dir_name="ERR_SQLS_"$currentMon
  Create_dir $dir_name
  log_name=errlog_"$currentTime".log
  Find_Errs $dir_name/$log_name
elif [ $in_op = "2" ]; then
  dir_name="More_Than_100ms_SQLs_"$currentMon
  Create_dir $dir_name
  log_name=more_than_100ms_SQLs_"$currentTime".log
  Filter_SQL_100ms $dir_name/$log_name
elif [ $in_op = "3" ]; then
  dir_name="More_Than_1000ms_SQLs_"$currentMon
  Create_dir $dir_name
  log_name=more_than_1000ms_SQLs_"$currentTime".log
  Filter_SQL_1000ms $dir_name/$log_name
elif [ $in_op = "4" ]; then
  exit 1
else
  echo "Input Error!"
  exit 1
fi

    在这个里面,用到了 shell 中的函数,函数调用不用在 fun 的()中声明变量,直接用 $1 $2 之类的指代传入的第一个、第二个参数,还是蛮方便的。
    另外,作为一个新手,发现确实自己在处理文本信息或者是字符串信息的过程中,还是缺乏很多系统的命令学习,想 sed 等命令就需要再好好学学,其实以前就看过 sed 命令,但是因为长期没实践,自己也没像样的博客或者笔记记载,就跟没学习一样,这一点还需要好好加油。
    重点提示一个遍历元素的方法,dirname=($command_ls) 这样将变量转成数组,当然是有分割符的,因为代码里是空格,属于默认分割符,就没有再设置,后面再详细记载。最后再用 for 来遍历数组内容。


补充

    后面代码更新,会另起新的一篇博客,链接记录会在这里,先预存好位置,也提醒自己要更新。

猜你喜欢

转载自www.cnblogs.com/DimInk/p/10662558.html