导读 | 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脚本例子都比较实用,在面试题中也经常出现,希望大家参考着多动手写写,不要复制粘贴就拿来跑,这样是学不会的!