导读 | Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动、挂起、停止甚至是编写一些程序。简单来讲,Shell是连接用户与内核的桥梁,是用户与内核交流的工具。 |
注意事项
1)开头加解释器:#!/bin/bash
2)语法缩进,使用四个空格;多加注释说明。
3)命名建议规则:变量名大写、局部变量小写,函数名小写,名字体现出实际作用。
4)默认变量是全局的,在函数中变量local指定为局部变量,避免污染其他作用域。
5)有两个命令能帮助我调试脚本:set -e 遇到执行非0时退出脚本,set-x 打印执行过程。
6)写脚本一定先测试再到生产上。
1 获取随机字符串或数字
获取随机8位字符串:
class="">方法1: #?echo?$RANDOM?|md5sum?|cut?-c?1-8 471b94f2 方法2: #?openssl?rand?-base64?4 vg3BEg== 方法3: #?cat?/proc/sys/kernel/random/uuid?|cut?-c?1-8 ed9e032c
获取随机8位数字:
class="">方法1: #?echo?$RANDOM?|cksum?|cut?-c?1-8 23648321 方法2: #?openssl?rand?-base64?4?|cksum?|cut?-c?1-8 38571131 方法3: #?date?+%N?|cut?-c?1-8 69024815
cksum:打印CRC效验和统计字节
2 定义一个颜色输出字符串函数
class="">方法1: function?echo_color()?{ ????if?[?$1?==?"green"?];?then ????????echo?-e?"\033[32;40m$2\033[0m" ????elif?[?$1?==?"red"?];?then ????????echo?-e?"\033[31;40m$2\033[0m" ????fi } 方法2: function?echo_color()?{ ????case?$1?in ????????green) ????????????echo?-e?"\033[32;40m$2\033[0m" ????????????;; ????????red) ????????????echo?-e?"\033[31;40m$2\033[0m"? ????????????;; ????????*)? ????????????echo?"Example:?echo_color?red?string" ????esac } 使用方法:echo_color?green?"test"
function关键字定义一个函数,可加或不加。
3 批量创建用户
class="">#!/bin/bash DATE=$(date?+%F_%T) USER_FILE=user.txt echo_color(){ ????if?[?$1?==?"green"?];?then ????????echo?-e?"\033[32;40m$2\033[0m" ????elif?[?$1?==?"red"?];?then ????????echo?-e?"\033[31;40m$2\033[0m" ????fi } #?如果用户文件存在并且大小大于0就备份 if?[?-s?$USER_FILE?];?then ????mv?$USER_FILE?${USER_FILE}-${DATE}.bak ????echo_color?green?"$USER_FILE?exist,?rename?${USER_FILE}-${DATE}.bak" fi echo?-e?"User\tPassword"?>>?$USER_FILE echo?"----------------"?>>?$USER_FILE for?USER?in?user{1..10};?do ????if?!?id?$USER?&>/dev/null;?then ????????PASS=$(echo?$RANDOM?|md5sum?|cut?-c?1-8) ????????useradd?$USER ????????echo?$PASS?|passwd?--stdin?$USER?&>/dev/null ????????echo?-e?"$USER\t$PASS"?>>?$USER_FILE ????????echo?"$USER?User?create?successful." ????else ????????echo_color?red?"$USER?User?already?exists!" ????fi done
4 检查软件包是否安装
class="">#!/bin/bash if?rpm?-q?sysstat?&>/dev/null;?then ????echo?"sysstat?is?already?installed." else ????echo?"sysstat?is?not?installed!" fi
5 检查服务状态
class="">#!/bin/bash PORT_C=$(ss?-anu?|grep?-c?123) PS_C=$(ps?-ef?|grep?ntpd?|grep?-vc?grep) if?[?$PORT_C?-eq?0?-o?$PS_C?-eq?0?];?then ????echo?"内容"?|?mail?-s?"主题"?dst@example.com fi
6 检查主机存活状态
方法1:将错误IP放到数组里面判断是否ping失败三次
class="">#!/bin/bash?? IP_LIST="192.168.18.1?192.168.1.1?192.168.18.2" for?IP?in?$IP_LIST;?do ????NUM=1 ????while?[?$NUM?-le?3?];?do ????????if?ping?-c?1?$IP?>?/dev/null;?then ????????????echo?"$IP?Ping?is?successful." ????????????break ????????else ????????????#?echo?"$IP?Ping?is?failure?$NUM" ????????????FAIL_COUNT[$NUM]=$IP ????????????let?NUM++ ????????fi ????done ????if?[?${#FAIL_COUNT[*]}?-eq?3?];then ????????echo?"${FAIL_COUNT[1]}?Ping?is?failure!" ????????unset?FAIL_COUNT[*] ????fi done
方法2:将错误次数放到FAIL_COUNT变量里面判断是否ping失败三次
class="">#!/bin/bash?? IP_LIST="192.168.18.1?192.168.1.1?192.168.18.2" for?IP?in?$IP_LIST;?do ????FAIL_COUNT=0 ????for?((i=1;i<=3;i++));?do ????????if?ping?-c?1?$IP?>/dev/null;?then ????????????echo?"$IP?Ping?is?successful." ????????????break ????????else ????????????#?echo?"$IP?Ping?is?failure?$i" ????????????let?FAIL_COUNT++ ????????fi ????done ????if?[?$FAIL_COUNT?-eq?3?];?then ????????echo?"$IP?Ping?is?failure!" ????fi done
方法3:利用for循环将ping通就跳出循环继续,如果不跳出就会走到打印ping失败
class="">#!/bin/bash ping_success_status()?{ ????if?ping?-c?1?$IP?>/dev/null;?then ????????echo?"$IP?Ping?is?successful." ????????continue ????fi } IP_LIST="192.168.18.1?192.168.1.1?192.168.18.2" for?IP?in?$IP_LIST;?do ????ping_success_status ????ping_success_status ????ping_success_status ????echo?"$IP?Ping?is?failure!" done
7 监控CPU、内存和硬盘利用率
1)CPU
借助vmstat工具来分析CPU统计信息。
class="">#!/bin/bash DATE=$(date?+%F"?"%H:%M) IP=$(ifconfig?eth0?|awk?-F?'[?:]+'?'/inet?addr/{print?$4}')??#?只支持CentOS6 MAIL="example@mail.com" if?!?which?vmstat?&>/dev/null;?then ????echo?"vmstat?command?no?found,?Please?install?procps?package."? ????exit?1 fi US=$(vmstat?|awk?'NR==3{print?$13}') SY=$(vmstat?|awk?'NR==3{print?$14}') IDLE=$(vmstat?|awk?'NR==3{print?$15}') WAIT=$(vmstat?|awk?'NR==3{print?$16}') USE=$(($US+$SY)) if?[?$USE?-ge?50?];?then ????echo?" ????Date:?$DATE ????Host:?$IP ????Problem:?CPU?utilization?$USE ????"?|?mail?-s?"CPU?Monitor"?$MAIL fi
2)内存
class="">#!/bin/bash DATE=$(date?+%F"?"%H:%M) IP=$(ifconfig?eth0?|awk?-F?'[?:]+'?'/inet?addr/{print?$4}')?? MAIL="example@mail.com" TOTAL=$(free?-m?|awk?'/Mem/{print?$2}') USE=$(free?-m?|awk?'/Mem/{print?$3-$6-$7}') FREE=$(($TOTAL-$USE)) #?内存小于1G发送报警邮件 if?[?$FREE?-lt?1024?];?then ????echo?" ????Date:?$DATE ????Host:?$IP ????Problem:?Total=$TOTAL,Use=$USE,Free=$FREE ????"?|?mail?-s?"Memory?Monitor"?$MAIL fi
3)硬盘
class="">#!/bin/bash DATE=$(date?+%F"?"%H:%M) IP=$(ifconfig?eth0?|awk?-F?'[?:]+'?'/inet?addr/{print?$4}')?? MAIL="example@mail.com" TOTAL=$(fdisk?-l?|awk?-F'[:?]+'?'BEGIN{OFS="="}/^Disk?/dev/{printf?"%s=%sG,",$2,$3}') PART_USE=$(df?-h?|awk?'BEGIN{OFS="="}/^/dev/{print?$1,int($5),$6}') for?i?in?$PART_USE;?do ????PART=$(echo?$i?|cut?-d"="?-f1) ????USE=$(echo?$i?|cut?-d"="?-f2) ????MOUNT=$(echo?$i?|cut?-d"="?-f3) ????if?[?$USE?-gt?80?];?then ????????echo?" ????????Date:?$DATE ????????Host:?$IP ????????Total:?$TOTAL ????????Problem:?$PART=$USE($MOUNT) ????????"?|?mail?-s?"Disk?Monitor"?$MAIL ????fi done >
8 批量主机磁盘利用率监控
前提监控端和被监控端SSH免交互登录或者密钥登录。
写一个配置文件保存被监控主机SSH连接信息,文件内容格式:IP User Port
class="">#!/bin/bash HOST_INFO=host.info for?IP?in?$(awk?'/^[^#]/{print?$1}'?$HOST_INFO);?do ????USER=$(awk?-v?ip=$IP?'ip==$1{print?$2}'?$HOST_INFO) ????PORT=$(awk?-v?ip=$IP?'ip==$1{print?$3}'?$HOST_INFO) ????TMP_FILE=/tmp/disk.tmp ????ssh?-p?$PORT?$USER@$IP?'df?-h'?>?$TMP_FILE ????USE_RATE_LIST=$(awk?'BEGIN{OFS="="}/^/dev/{print?$1,int($5)}'?$TMP_FILE) ????for?USE_RATE?in?$USE_RATE_LIST;?do ????????PART_NAME=${USE_RATE%=*} ????????USE_RATE=${USE_RATE#*=} ????????if?[?$USE_RATE?-ge?80?];?then ????????????echo?"Warning:?$PART_NAME?Partition?usage?$USE_RATE%!" ????????fi ????done done
9 检查网站可用性
1)检查URL可用性
class="">方法1: check_url()?{ ????HTTP_CODE=$(curl?-o?/dev/null?--connect-timeout?3?-s?-w?"%{http_code}"?$1) ????if?[?$HTTP_CODE?-ne?200?];?then ????????echo?"Warning:?$1?Access?failure!" ????fi } 方法2: check_url()?{ if?!?wget?-T?10?--tries=1?--spider?$1?>/dev/null?2>&1;?then?? #-T超时时间,--tries尝试1次,--spider爬虫模式 ????????echo?"Warning:?$1?Access?failure!" ????fi }
使用方法:check_url www.baidu.com
2)判断三次URL可用性
思路与上面检查主机存活状态一样。
class="">方法1:利用循环技巧,如果成功就跳出当前循环,否则执行到最后一行 #!/bin/bash?? check_url()?{ ????HTTP_CODE=$(curl?-o?/dev/null?--connect-timeout?3?-s?-w?"%{http_code}"?$1) ????if?[?$HTTP_CODE?-eq?200?];?then ????????continue ????fi } URL_LIST="www.baidu.com?www.agasgf.com" for?URL?in?$URL_LIST;?do ????check_url?$URL ????check_url?$URL ????check_url?$URL ????echo?"Warning:?$URL?Access?failure!" done
class="">方法2:错误次数保存到变量 #!/bin/bash?? URL_LIST="www.baidu.com?www.agasgf.com" for?URL?in?$URL_LIST;?do ????FAIL_COUNT=0 ????for?((i=1;i<=3;i++));?do ????????HTTP_CODE=$(curl?-o?/dev/null?--connect-timeout?3?-s?-w?"%{http_code}"?$URL) ????????if?[?$HTTP_CODE?-ne?200?];?then ????????????let?FAIL_COUNT++ ????????else ????????????break ????????fi ????done ????if?[?$FAIL_COUNT?-eq?3?];?then ????????echo?"Warning:?$URL?Access?failure!" ????fi done
class="">方法3:错误次数保存到数组 #!/bin/bash?? URL_LIST="www.baidu.com?www.agasgf.com" for?URL?in?$URL_LIST;?do ????NUM=1 ????while?[?$NUM?-le?3?];?do ????????HTTP_CODE=$(curl?-o?/dev/null?--connect-timeout?3?-s?-w?"%{http_code}"?$URL) ????????if?[?$HTTP_CODE?-ne?200?];?then ????????????FAIL_COUNT[$NUM]=$IP??#创建数组,以$NUM下标,$IP元素 ????????????let?NUM++ ????????else ????????????break ????????fi ????done ????if?[?${#FAIL_COUNT[*]}?-eq?3?];?then ????????echo?"Warning:?$URL?Access?failure!" ????????unset?FAIL_COUNT[*]????#清空数组 ????fi done
10 检查MySQL主从同步状态
class="">#!/bin/bash?? USER=bak PASSWD=123456 IO_SQL_STATUS=$(mysql?-u$USER?-p$PASSWD?-e?'show?slave?status\G'?|awk?-F:?'/Slave_.*_Running/{gsub(":?",":");print?$0}')??#gsub去除冒号后面的空格 for?i?in?$IO_SQL_STATUS;?do ????THREAD_STATUS_NAME=${i%:*} ????THREAD_STATUS=${i#*:} ????if?[?"$THREAD_STATUS"?!=?"Yes"?];?then ????????echo?"Error:?MySQL?Master-Slave?$THREAD_STATUS_NAME?status?is?$THREAD_STATUS!" ????fi done
本章写的Shell脚本例子都比较实用,在面试题中也经常出现,希望大家参考着多动手写写,不要复制粘贴就拿来跑,这样是学不会的!