day31-shell编程-5

1. 数组

  • 数组也是一种变量,一组数据
  • 数组可以存放多个 相关联内容,通过访问数组调用

1.1. 数组赋值

1.批量赋值
ip_array=(10.0.0.1 10.0.0.2 10.0.0.200)

array=(命令结果)
array=(`cat ip.txt`)

2.逐个元素赋值
array[0]=第一个值
array[1]=第二个值
array[2]=第三个值

3.red命令赋值
交互式输入,-a参数可以赋值给数组
read -p "输入" -a array

案例26:书写脚本批量检查ip/域名,ip或域名存放在数组变量中

#!/bin/bash
##############################################################
# File Name: 26-ip_check.sh
# Version: V1.0
# Author: zbl
# Organization: www.zbl.com
# Description:
##############################################################
source /server/scripts/func.d/color_func.sh
#array
ip_array=(`cat /server/scripts/ip.txt`)

#ping
for ip in ${ip_array[*]}
do
	ping -c1 -W 1 ${ip} >/dev/null 2>&1
	if [ $? -eq 0 ];then
		greenecho "${ip}可以ping通"
	else
		redecho "${ip}不可以ping通"
	fi
done

1.2. 技巧

  • 命令参数curl命令,包含选项,选项中还有引号,可以使用数组解决
curl=(选项)

2. Debug

  • -x
bash -x
sh -x
显示脚本运行过程
一般使用这个进行调试
  • 精确控制,脚本中某个范围的内容,显示详细过程,其他的不显示详细过程
#开始
set -x

中间的内容会显示详细的执行过程

#结束
set +x
  • 配合函数
  • 注释排除法
  • 使用echo输出变量内容
id $user
echo $?

id $user
rc=$?

3. 案例

3.1. 案例27:书写系统僵尸进程检查与处理的脚本

  • 检查: top命令的 0 zombie 即可.
  • 处理:
    • 定位到具体的僵尸进程
    • 僵尸进程的pid
    • 找出僵尸进程的父进程的id,ppid
    • 判断ppid是否为1
      • 是则提示重启系统.
      • 否,提示是否要结束掉这个进程,输入yes则结束
#!/bin/bash
##############################################################
# File Name: 27-zombie_check.sh
# Version: V1.0
# Author: zbl
# Organization: www.zbl.com
# Description:
##############################################################

#color func
func_file=/server/scripts/func.d/color_func.sh
if [ -f ${func_file} ];then
        source ${func_file}
else
        exit 1
fi

#1.vars
zombie_num=`top -bn 1 | awk 'NR==2{print $(NF-1)}'`
zombie_pid=`ps aux | awk '$8~/Z/{print $2}'`

function check_zombie_num() {
	if [ ${zombie_num} -eq 0 ];then
		greenecho "当前系统没有僵尸进程了,继续摸鱼"
	else
		redecho "当前系统有${zombie_num}个僵尸进程,请及时处理。"
		check_zombie
	fi
}

#check_zombie func
function check_zombie() {
	for id in ${zombie_pid}
	do
		zombie_ppid=`ps -ef | grep "${id}" | grep -v "grep" | awk '{print $3}'`
		if [ ${zombie_ppid} -eq 1 ];then
			redecho "需要重启系统解决"
		else
			read -p "是否结束这个${zombie_ppid}进程,请输入yes,结束这个僵尸进程: " yes_kill
			case ${yes_kill} in
				yes)
					kill ${zombie_ppid}
					;;
				*)
					redecho "${zombie_ppid}僵尸进程未结束,已退出"
					exit
			esac
		fi
	done
}
check_zombie_num

3.2. 案例28: 磁盘空间不足案例

检查:
    1.是否有block导致的磁盘空间不足
    df -h  |awk -F '[ %]+' '$5>=90  && NR>1'
    2.是否有inode导致的磁盘空间不足
    df -i  |awk -F '[ %]+' '$5>=90  && NR>1'
处理:
    情况1:df -h + du -sh 处理
    情况2:lsof |grep delete 
    情况3:df -i +find 大于1MB目录
#!/bin/bash
##############################################################
# File Name: 28-disk_check.sh
# Version: V1.0
# Author: zbl
# Organization: www.zbl.com
# Description:
##############################################################

#color func
func_file=/server/scripts/func.d/color_func.sh
if [ -f ${func_file} ];then
        source ${func_file}
else
        exit 1
fi

#1.block
function block_check() {
	disk_use=`df -h / | awk 'NR==2{print $(NF-1)}'`
	disk_status=`echo ${disk_use} 60% | awk '$1 >= $2{print "ge"}' | grep ge | wc -l`
	if [ ${disk_status} -ne 0 ];then
		redecho "当前磁盘空间使用率${disk_use},磁盘空间不足,请及时处理"
		block_reason
	else
		greenecho "当前磁盘空间使用率${disk_use},正常,继续摸鱼"
	fi
}

#2.inode
function inode_check() {
	inode_use=`df -i / | awk 'NR==2{print $(NF-1)}'`
	inode_status=`echo ${inode_use} 60% | awk '$1 >= $2{print "ge"}' | grep ge | wc -l`
	if [ ${inode_status} -ge 1 ];then
		redecho "当前inode空间使用率${inode_use},inode空间不足"
		inode_reason
	else
		greenecho "当前inode空间使用率${inode_use},正常,继续摸鱼吧"
	fi
}

#3.deleted
function block_reason() {
	big_files=`find /study -type f -size +1G 2>/dev/null`
	yellowecho "已找到大于1G的文件:${big_files},请及时处理"
}

#4.lsof_deleted
function inode_reason() {
	big_dir=`find / -type d -size +100k 2>/dev/null`
	yellowecho "已找到大于10M的目录:${big_dir},请及时处理"
}

#func
function main() {
	block_check
	inode_check
}
main

4. 三剑客

4.1. sed

  • sed与变量
src=172.16.1.210
dest=192.168.16.253

sed使用单引号不会解析变量
sed 's#$src#$dest#g' ip.txt

sed使用双引号会解析变量
sed "s#$src#$dest#g" ip.txt
  • 案例29:书写1个修改配置文件的函数
chcfg port 2222 sshd_config
chcfg IPADDR 10.0.0.211 ifcfg-ens33


1.在文件中过滤是否有port的行(精确过滤),没有退出
grep -w ""

sed "/\b  \b/s###g"

2.找出这行,取出当前的值(22),进行替换(2222)
3.提示配置修改完成请重启服务
  • 脚本
#!/bin/bash
##############################################################
# File Name: 29-change_cfg.sh
# Version: V1.0
# Author: zbl
# Organization: www.zbl.com
# Description:
##############################################################

#color func
func_file=/server/scripts/func.d/color_func.sh
if [ -f ${func_file} ];then
        source ${func_file}
else
        exit 1
fi

#1.vars
src=$1
dest=$2
file=$3

#2.check_file
function check_file() {
	if [ ! -f ${file} ];then
		redecho "文件不存在,请检查文件是否输入正确"
		exit 1
	fi
}

#3.check_args
function check_args() {
	if [ $# -ne 3 ];then
		redecho "error: usage: $0 过滤的内容 修改的内容 修改的文件"
		exit 2
	fi
}

#4.check_src_cont
function check_src_cont() {
	src_cont=`egrep -v "^$|^#" ${file} | grep -wc "${src}" ${file}`
	if [ ${src_cont} -eq 0  ];then
		redecho "error: ${src_cont},过滤的内容不存在,请重新输入"
		exit 3
	fi
}

#5.sed
function change_cfg() {
	old_cont=`egrep -v "^$|^#" ${file} | grep -w "${src}" ${file} | awk -F '[ =]+' '{print $2}'`
	sed -i.bak "/\b${src}\b/s#${old_cont}#${dest}#g" ${file}
	if [ $? -eq 0 ];then
		grep -w ${src} ${file}
		greenecho "配置文件修改成功,重启服务后生效"
	else
		redecho "修改失败,请重新输入"
	fi
}

#6.func_main
function main() {
	check_file
	check_args $*
	check_src_cont
	change_cfg
}
main $*

4.2. awk

  • awk数组
统计access.log文件第一列是ip地址,第10是访问的资源大小
需求01:统计每个ip出现的次数awk+sort+uniq就可以实现
需求02:统计每个ip使用的流量

awk 'BEGIN{}'

shell中
for ip in ${ips[*]}
do
  echo $ip
done

变量获取到的是数组具体值

awk中
for(ip in ips)
print ip,ips[ip]

变量获取到的是下标[下标]

  • 案例30:统计去重
cat  >/server/files/url.txt<

  • 案例31:统计去重并求和(数组)

awk '{ip[$1]=ip[$1]+$10} END{for(i in ip) print i,ip[i]}' access.log | column -t | sort -rnk2 | head

5. shell编程总结

  • 变量
    • 普通变量 命令规则
    • 环境变量 PATH , UID , LANG , PS1
    • 特殊变量: $n , $0 , $# , $* , $@ , $?
  • 判断
    • 条件表达式
      • 比较大小 -eq -ne -gt -ge -lt -le
      • 字符比较 = != -z -n
      • 文件判断 -f -d -L/-h -s -x
      • 逻辑判断 -a -o !
      • 正则匹配 [[ =~ ]]
    • if
      • 单分支
      • 双分支
      • 多分支
    • case
      • 菜单选择
  • 循环
    • for
    • while
      • 死循环
      • 读取文件
    • 循环控制
      • continue 退出当前循环,进入下一次循环
      • break 退出循环
      • exit 退出脚本
      • return 退出当前函数
  • 函数
    • 格式
    • 函数传参:$n , $0 , $# , $* , $@ , $?
    • 颜色
  • 数组

目标:

  • 自动化
  • 与定时任务配合
    • 定时检查
    • 定时备份
    • xxx
  • 部署服务脚本
    • 一般先手动部署
    • 根据流程书写脚本
  • 服务检查脚本
  • 服务管理脚本
  • 大脚本
    • 巡检脚本
    • 服务安装脚本
    • 优化脚本
    • 安全检查脚本(安全加固,等保加固)

day31-shell编程-5_第1张图片

你可能感兴趣的:(linux运维学习笔记,云计算,运维,服务器,linux,bash)