首页 > 技术文章 > shell编程

yang-dan 2019-12-25 17:54 原文

1.什么是Shell

shell是一个命令解释器,   将人类输入高级语言, 通过 Shell程序 转换为 二进制 .

shell分为两种使用方式:
	交互:		登录 执行命令 退出
	非交互:		执行某个文件, 文件中都是一推命令, 整个文件从上往下依次执行.

2.什么是Shell脚本

1) 将系统命令堆积在一起,顺序执行(简称: 系统命令堆积)
2) 特定的格式 + 特定的语法 + 系统的命令 = 文件。  Shell脚本
				if for ...

3.Shell脚本能做什么

标准:
	1.安装方式一致
	2.安装路径一致
	3.目录结构一致
	4.日志格式一致
	5.脚本路径一致
能将平时操作脚本化,流程化,自动化     ITIL 
	ppt   人  流程   技术/工具
备份
监控
自动化上线
约束标准

4.shell脚本需要的预备知识

5.shell脚本如何才能学好

思路
练习
分享    

6.Shell脚本编写规范、执行方式。

执行方式分为两种:
	1.加执行权限  				./script_filename.sh
	2.通过bash直接翻译   bash  script_filename.sh

#!/usr/bin/bash  加与不加区别在哪?
	1.如果你明确清楚这是一个什么类型的脚本,直接调用对应的解释器执行,没有影响?
	2.如果你不清楚是什么类型的脚本, 直接使用./执行,那么会读取该脚本的第一行
		如果第一行是#!/usr/bin/bash 或者 没有写该行,那么都将使用默认的bash翻译
		问题: 如果我是一个python脚本,没有写开头,那么执行一定会报错
			因为默认查找的是bash解释器,而我的文件需要用python解释器来翻译.

添加命令解释器的几种方式:
	#!/usr/bin/bash
	#!/usr/bin/sh
	#!/usr/bin/env bash
	#!/usr/bin/env python

7.什么是变量

变量是shell中传递数的一种方法。
简单理解:就是用一个固定的字符串去表示不固定的值,便于后续引用。

8.定义变量规范

1、大写开头,后面小写或数字都OK
2、变量具体一定的含义
3、注意 变量的写法 仅支持 a=1 不支持 a = 1

9、自定义变量

var="holle world"
echo $var
echo ${var}_log

#$* 和 $@ 的区别?
可以看到不加引号时,二者都是返回传入的参数,但加了引号后,此时$*把参数作为一个字符串整体(单字符串)返回,$@把每个参数作为一个字符串返回

需求1:通过位置传参方式, 创建 Linux 系统账户及密码,执行 var1.sh username password

[root@manager variables]# cat var01.sh 
#!/bin/bash

useradd $1
echo "$2" | passwd --stdin $1

[root@manager variables]# sh var04 username password

需求2:通过位置传参方式, Linux 系统账户及密码,执行 var1.sh username password,控制最多传递两个参数。

[root@manager variables]# cat var02.sh 
#!/bin/bash

if [ $# -ne 2 ];then
	echo "USAGE: $0 请传递两个参数  [ username | password ]"
	exit 
fi
useradd $1
echo "$2" | passwd --stdin $1

read交互传递变量

需求1:使用read模拟Linux登陆页面。

1.先实现, 无论多low
2.在进行改进
[root@manager variables]# cat var03.sh 
#!/bin/bash

echo "$(hostnamectl |awk -F ":" '/Operating System:/ {print $2}')"
echo "Kernel $(uname -r) on an $(uname -m)"

read -p "$(hostname) Login: " acc
read -s -t50 -p "Password: " pw
echo ""
echo "你输入的用户名: $acc	你输入的密码是: $pw"

需求2:使用 read编写一个备份脚本,需要用户传递2个参数,源和目标。

[root@manager variables]# cat var04.sh 
#!/bin/bash


echo "----------请按照如下提示输入---------------"

read -p "请输入你要备份的源文件或者源目录: " Source
read -p "请输入你要备份的目录位置是哪里: " Dest

echo -e "\t你要备份的源是 $Source
       你要备份的目标是: $Dest"
read -p "你确定要备份吗? [ y | n ] " Action

if [ $Action == "y" ];then
	cp -rpv $Source $Dest
fi

需求3:使用read编写一个探测主机存活脚本,需要用户传递测试的IP地址。

#思路:
    1.提示用户输入IP地址
    2.对用户输入的IP地址进行探测是否存活
    3.判断探测结果是否成功
	成功则输出成功的结果
	失败则输出失败的结果

[root@manager variables]# cat var5.sh 
#!/bin/bash

read -p "请输入需要探测的IP地址: " ip

ping -W1 -c1 "$ip" &>/dev/null
if [ $? -eq 0 ];then
	echo "$ip" is ok...
else
	echo "$ip" is err...
fi

需求4:使用read编写一个修改系统主机名称脚本。

#思路:
    1.打印当前的主机名称
    2.提示用户输入新的主机名称
    3.询问用户是否修改?
    4.确定修改,执行修改命令
    5.不确定修改,退出脚本

[root@manager variables]# cat var6.sh 
#!/bin/bash

Hostname=$(hostname)
echo "当前的主机名称是: ${Hostname}"
read -p "请输入新的主机名称: " new_host
read -p "你确定要将 ${Hostname} 变更为 ${new_host} 吗? [ y | n ] " Action

if [ $Action == "y" ];then
	hostname ${new_host}
	hostnamectl set-hostname ${new_host}
	echo "你的主机名称已修改为  ${new_host} "
fi

变量取值

[root@manager ~]# url=www.sina.com.cn
[root@manager ~]# echo $url
www.sina.com.cn
[root@manager ~]# echo $url | awk -F '.' '{print $2,$3,$4}'
sina com cn
[root@manager ~]# echo ${url}
www.sina.com.cn

------------#
[root@manager ~]# echo ${url#*.}		#从头开始匹配,最短匹配
sina.com.cn 
[root@manager ~]# echo ${url##*.}		#从头开始匹配,最长匹配
cn

------------%
[root@manager ~]# echo ${url%.*}
www.sina.com
[root@manager ~]# echo ${url%%.*}
www

-------------/
[root@manager ~]# echo ${url/c/C}
www.sina.Com.cn
[root@manager ~]# echo ${url//c/C}
www.sina.Com.Cn

需求1:如何替换 $PATH 中的/bin/替换为/BIN/

[root@manager ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

[root@manager ~]# echo ${PATH//bin/BIN}

需求2:变量string="Bigdata process is Hadoop, Hadoop is open source project",执行脚本后,打印输出string变量,并给出用户以下选项:

#要求:
1)、打印string长度
2)、删除字符串中所有的Hadoop
3)、替换第一个Hadoop为Linux
4)、替换全部Hadoop为Linux
用户输入数字1|2|3|4,可以执行对应项的功能

[root@manger variables]# cat var7.sh
#!/bin/bash
 
string="Bigdata process is Hadoop, Hadoop is open source project"

echo $string
echo "1)、打印string长度"
echo "2)、删除字符串中所有的Hadoop"
echo "3)、替换第一个Hadoop为Linux"
echo "4)、替换全部Hadoop为Linux"
read -p "请输入对应的选项 [ 1 | 2 | 3 | 4 | q ] " Action

if [ $Action -eq 1 ];then
	echo "他的长度是: ${#string}"
fi

if [ $Action -eq 2 ];then
        echo "${string//Hadoop/}"
fi

if [ $Action -eq 3 ];then
	echo ${string/Hadoop/Linux}
fi

if [ $Action -eq 4 ];then
	echo ${string//Hadoop/Linux}
fi

需求3:查看内存/当前使用状态,如果使用率超过80%则报警发邮件

#思路:
1.当前内存使用百分比是多少
2.进行判断比对  
	如果大于80%  则触发邮件
	否则,over
	已使用的内存  /  总内存  * 100 = 使用的百分比

mem_use=$(free -m | awk '/^Mem/ {print $3/$2*100}')
if [ ${mem_use%.*}  -ge 10 ];then
	echo "你的内存已经超过了80%  目前的内存使用状态是 ${mem_use}%"
fi

需求4:根据系统时间,打印今年和明年时间。

[root@manager variables]# cat var8.sh 
#!/bin/bash

echo "今年的时间是: $(date +%Y)"
echo "明年的时间是: $(( $(date +%Y) +1 ))"

需求5:根据系统时间获取今年还剩下多少星期,已经过了多少星期。

思路如下:
date +%j  已经过了多少天
一年有365天   已经过了 301 = 还剩下   365-301 = 64  / 7 = 还剩下多少周
	      已经过了 301 天 / 7 = 已经过了多少周

[root@manager variables]# cat var9.sh 
#!/bin/bash

Date=$(date +%j)

echo "今年已经过了 ${Date}   天"
echo "今年已经过了 $[ ${Date} /7 ] 周"
echo "今年还剩下 $[ ( 365 - ${Date} ) / 7 ]  周"
echo "从现在距离下一个新年还有  $[ 365 - ${Date} ]  天"

需求6:完成一个计算器功能: 传入2个值,然后对传入的值进行 加 减 乘 除

思路如下:
1.使用read让用户传值:     $1 $2
2.对传入的值进行运算:
3.输出对应的结果.

[root@manager variables]# cat var10.sh 
#!/bin/bash

echo "$1 + $2 = $[ $1 + $2 ]"
echo "$1 - $2 = $[ $1 - $2 ]"
echo "$1 * $2 = $[ $1 * $2 ]"
echo "$1 / $2 = $[ $1 / $2 ]"
echo "$1 % $2 = $[ $1 % $2 ]"

if 判断语句

1.什么是if

if 仅仅只是用来判断的, 基于条件来进行判断,整数、字符、正则...

2、为什么要使用if

需要使用if,判断是否是整数、是否是数字等,一些无法判断的语句,需要if判读,存在会怎样,不存在会怎样 #纯属个人简介,如有好的建议,我洗耳恭听,☺☺

3、if基础语法

- 单条件
- 双条件
- 多条件

- 基于文件进行判断
- 基于整数进行判断
- 基于字符进行判断
- 基于正则进行判断
- 基于逻辑或 && || -a -o 

1、编写if判断的shell脚本

需求1:根据输入一个用户名称, read $1 <--test

#思路:
1.判断输入的用户是否存在当前系统,
2.如不在再次判断用户是否在/home下拥有家目录
3.如果都没有则提示不存在。

[root@manager if]# cat if-01.sh 
#!/bin/bash

if grep $1 /etc/passwd &>/dev/null;then
	echo "$1 用户存在系统中...."
elif ls -ld /home/$1 &>/dev/null;then
	echo "$1 用户不存在系统中,但拥有家目录"
else
	echo "$1 用户不存在系统,也没有家目录"
fi
---------------------方法二------------------------------------
[root@manager if]# cat if-02.sh 
#!/bin/bash

grep_user=$(grep $1 /etc/passwd &>/dev/null)
grep_rc=$?
cat_home=$(ls -ld /home/$1 &>/dev/null)
cat_rc=$?

if [ $grep_rc -eq 0 ];then
	echo "$1 用户存在系统中...."
elif [ $cat_rc -eq 0 ];then
	echo "$1 用户不存在系统中,但拥有家目录"
else
	echo "$1 用户不存在系统,也没有家目录"
fi

需求2:通过脚本传入两个参数,进行整数关系比较。比如: if.sh [ 1 2 | 2 2 | 2 3 ],请使用双分支和多分支两种方式实现。

[root@manager if]# cat if-03.sh 
#!/bin/bash

if [ $1 -eq $2 ];then
	echo "$1 = $2"
elif [ $1 -lt $2 ];then
	echo "$1 < $2"
else
	echo "$1 > $2"
fi
-----------------方法二-----------------------------
[root@manager if]# cat if-04.sh 
#!/bin/bash

if [ $1 -eq $2 ];then
	echo " $1 = $2"
else
	if [ $1 -gt $2 ];then
		echo "$1 > $2"
	else
		echo "$1 < $2"
	fi
fi

2、基于文件的条件比对:

需求1:备份mysql,手动输入你需要备份的库名称, 备份到/backup/mysql/时间/xx.sql

#思路:
1.数据库怎么备份?
2.将手动执行的命令转为脚本
mysqldump -uroot -poldxu.com -B mysql > /backup/mysql/2019-10-29/mysql.sql

[root@manager if]# cat if-05.sh 
#!/bin/bash

#1.保存的路径
Date=$(date +%F)
Path="/backup/mysql/$Date"

#2.判断保存的目录是否存在
[ -d $Path ]  || mkdir -p $Path

#3.给用户展示当前有哪些数据库
mysql -uroot -poldxu.com -e "show databases;"

read -p "请输入你需要备份的数据库名: " dbname

#4.执行备份命令
mysqldump -uroot -poldxu.com -B ${dbname} > $Path/${dbname}.sql

3、基于整数比对:

需求1:用户执行脚本,sh status.sh nginx,则检查nginx服务的运行状态。(仅支持传递一个参数)

#思路:
1.检查nginx状态  systemctl status nginx
2.状态结果非0 则提示未启动
3.状态结果为0 则提示已启动

[root@manager if]# cat if-06.sh 
#!/bin/bash

#1.控制传递的参数为一个
if [ $# -ne 1 ];then
	echo "USAGE: $0 { nginx | rsyncd | sshd | all service name  }"
	exit 
fi

systemctl status $1 &>/dev/null
if [ $? -eq 0 ];then
	echo "$1 已启动"
else
	echo "$1 未启动"
fi

需求2:查看磁盘/当前使用状态,如果使用率超过80%则报警发邮件

[root@manager if]# cat if-07.sh 
#!/bin/bash

disk_use=$(df -h | awk '/\/$/ {print $(NF-1)}')

if [ ${disk_use%\%} -ge 5 ];then
	echo "邮件报警中...."
	sleep 3
	echo "邮件已发送, 你的磁盘使用率是 $disk_use"
fi

单分支、双分支

需求1:单分支,判断当前用户是不是root,如果不是那么返回“ERROR”

#1.通过整数比对的方式
[root@manager if]# cat if-08.sh 
#!/bin/bash

if [ $UID -ne 0 ];then
	echo "ERROR"
	exit
fi

#2.通过字符串比对的方式
[root@manager if]# cat if-09.sh 
#!/bin/bash

if [ $USER != "root" ];then
	echo "ERROR"
	exit 
fi

需求2:双分支,判断当前登录用户是管理员还是普通用户,如果是管理员输出”hey admin“ 如果是普通用户输出”hey guest“

[root@manager if]# cat if-10.sh 
#!/bin/bash

if [ $UID -eq 0 ];then
	echo "hey admin"
else
	echo "hey guest"
fi

需求3:备份filename文件至/backup/system/filename-2019-10-29,如果该目录不存在则自动创建。

[root@manager if]# cat if-11.sh 
#!/bin/bash
 
Dest=/backup/system
Date=$(date +%F)

read -p "请输入备份源: " Src
if [ ! -d $Dest ];then
	mkdir $Dest
fi
cp -rpv $Src $Dest/filename-$Date

需求4:继需求3,判断备份的文件是否存在,如果不存在则提示”No such file or directory“,然后退出。

[root@manager if]# cat if-12.sh 
#!/bin/bash

Dest=/backup/system
Date=$(date +%F)
read -p "请输入备份源: " Src
#1.判断用户输入的路径是否存在,是否是一个文件
if [ ! -f $Src ];then
	echo "$Src No such file or directory"
	exit
fi
if [ ! -d $Dest ];then
	mkdir $Dest
fi
cp -rpv $Src $Dest/filename-$Date

需求5:继需求3、4,判断备份的文件是否为空,如果为空则提示"This is file empty",然后退出。

[root@manager if]# cat if-13.sh 
#!/bin/bash

Dest=/backup/system
Date=$(date +%F)
read -p "请输入备份源: " Src

#1.判断用户输入的路径是否存在,是否是一个文件
if [ ! -f $Src ];then
	echo "$Src No such file or directory"
	exit
fi

#2.判断文件为空,则报错
if [ ! -s $Src ];then
	echo "$Src This is file empty"
	exit
fi

#3.备份源没有问题,则创建备份的目录
if [ ! -d $Dest ];then
	mkdir $Dest
fi
cp -rpv $Src $Dest/filename-$Date

-------------------------------方法二------------------------------------------
[root@manager if]# cat if-14.sh 
#!/bin/bash

read -p "请输入一个数字: " num

#判断用户输入的是否为空
if [ -z $num ];then
	echo "请不要输入空值"
	exit
fi
echo "你输入的数字是: $num"

基于正则比对

#1.两个条件必须都满足
[root@manager if]# [ 1 -lt 2 -a 5 -gt 10 ];echo $?

#2.只要满足一个条件即可
[root@manager if]# [ 1 -lt 2 -o 5 -gt 10 ];echo $?

#3.两个条件必须都满足
[root@manager if]# [ 1 -lt 2 ] && [ 5 -gt 10 ] ; echo $?

#4.只要满足一个条件即可
[root@manager if]# [ 1 -lt 2 ] || [ 5 -gt 10 ] ; echo $?

需求1:提示学生输入自己的成绩。

#要求:
1.如果分数大于0小于59提示补考。
2.如果分数大于60小于70提示良好。
3.如果分数大于71小于85提示好。
4.如果分数大于86小于100提示优秀。
5.不允许输入空值.
6.必须输入的是全数字.

[root@manager if]# cat if-15.sh 
#!/bin/bash

read -p "请输入你的成绩分数: " cj
if [ -z $cj ];then
	echo "....."
	exit 1
fi

#除了数字0-9以外的,其他都匹配
if [[ ! "$cj" =~ ^[0-9]+$ ]];then
	echo "请输入纯数字"
	exit 2
fi
if [ $cj -ge 0  -a  $cj -le 59 ];then
	echo "补考..."

elif [ $cj -ge 60  -a  $cj -le 70 ];then
	echo "不错..."

elif [ $cj -ge 71  -a  $cj -le 85 ];then
	echo "good"

elif [ $cj -ge 86  -a  $cj -le 100 ];then
	echo "very good!"
else
	echo "gdx"
fi

需求2:使用for循环打印一推单词,然后仅输出以r开头的单词。

[root@manager if]# cat if-16.sh 
#!/bin/bash 

for var in ab ac rx bx rvv vt
do
	if [[ "$var" =~ ^r ]];then
		echo $var
	fi
done

需求3:编写一个创建用户的脚本。

#要求:
1.提示用户输入要创建用户的前缀,必须是英文。  oldboy
2.提示用户输入后缀,必须是数字。			  123
3.如果前缀和后缀都没有问题,则进行用户创建。

oldboy123     ok!!!

[root@manager if]# cat if-17.sh 
#!/bin/bash

read -p "请输入用户的前缀: " qz
#判断用户输入的前缀
if [[ ! $qz =~ ^[a-Z]+$ ]];then
	echo "你输入的不是纯英文....."
	exit 1
fi


read -p "请输入用户的后缀: " hz
#判断用户输入的后缀
if [[ ! $hz =~ ^[0-9]+$ ]];then
	echo "你输入的不是纯数字...."
	exit 2
fi

#开始拼接用户输入的前缀+后缀=user_name变量
	user_name=$qz$hz
	id $user_name &>/dev/null
	if [ $? -eq 0 ];then
		echo " $user_name 用户已存在"
		exit 3
	else
		useradd $user_name
		echo "$user_name 用户创建成功"
	fi

if判断综合练习

需求1:使用root用户清空/var/log/messages日志,并每次执行保留最近100行

#思路:
1.必须是root用户
2.需要保留最后100行

[root@manager if]# cat if-18.sh 
#!/bin/bash

Log_Path=/var/log/messages

#如果是普通用户则拒绝
if [ $UID -ne 0 ];then
	echo "Permission denied...."
	exit 1
fi

if [ -f $Log_Path ];then
	#先提取100行的内容写入新的文件
	tail -100 $Log_Path >/var/log/messages_bak

	#将新的文件重新写入到/var/log/messages中
	cat /var/log/messages_bak > $Log_Path

	#最后删除文件
	rm -f /var/log/messages_bak

	#输出结果
	echo "clean log done...."
else
	echo "$Log_Path No such file or directory"
	exit 2

fi

需求2:判断httpd服务是否正常启动, 脚本名必须为httpd_deamon.sh $$

#思路:
1.手动如何看这个服务是正常的
	1.ps
	2.losf netstat
	3.curl  200 301 302 
	4.systemctl

[root@manager if]# cat if-19.sh 
#!/bin/bash

systemctl status httpd &>/dev/null
if [ $? -eq 0 ];then
	echo "httpd is ok...."
else
	systemctl start httpd &>/dev/null
	if [ $? -eq 0 ];then
		echo "Httpd 重新启动ok"
	else
		echo "httpd 重新启动失败"
	fi
fi

--------------------------方法二--------------------------------------
[root@manager if]# cat if-20.sh 
#!/bin/bash

Httpd_status=$(ps aux|grep httpd | grep -v grep |wc -l)


if [ $Httpd_status -ge 1 ];then
	echo "httpd service is ok"
else
	systemctl start httpd &>/dev/null
	if [ $? -eq 0 ];then
		echo "重新拉起成功"
	else
		echo "重新拉起失败"
	fi
fi

-------------------------方法三-------------------------------
[root@manager if]# cat if-21.sh 
#!/bin/bash

Httpd_Status=$(curl -sI  localhost | awk '/HTTP/ {print $2}')

if [[ "$Httpd_Status" -eq 200  ||  "$Httpd_Status" -eq 301  ||  "$Httpd_Status" -eq 302 ]];then
	echo "Httpd is ok ...."
else
	echo "Httpd is down...."
	echo "尝试复活中......."
	sleep 3
	systemctl start httpd &>/dev/null
	if [ $? -eq 0 ];then
		echo "复活成功"
	else
		echo "复活失败"
	fi
fi

需求3:根据不同的系统版本,配置不同的yum源

#思路:
1.获取相同系统,不同的版本
2.根据不同系统的不同版本实现
	1.判断是centos还是ubuntu
	2.根据判断的条件进入嵌套if
2.根据不同的系统配置不同yum源

[root@manager if]# cat if-22.sh 
#!/bin/bash

system_status=$(cat /etc/redhat-release  | awk '{print $(NF-1)}')

if [ ${system_status%%.*} -eq 7 ];then
	echo "systemctl 7"
elif [ ${system_status%%.*} -eq 6 ];then
	echo "systemctl 6"
fi

需求4:安装不同版本的PHP方式,使用echo输出即可,不用真的安装。

#思路:
1.给一个选择的菜单
2.给一个数字编号  1 2 3 4 
3.根据用户的选择进行判断

[root@manager if]# cat if-23.sh 
#!/bin/bash 

clear
cat <<EOF
=====================================
1) Installed PHP 5.5 
2) Installed PHP 7.0
3) Installed PHP 7.3 
4) quit
=====================================
EOF
read -p "请输入你要安装的版本 [ 1 | 2 | 3 | 4 ] " Action

#判断空值
if [ -z $Action ];then
	echo "请不要输出空值"
	exit 1
fi


#必须是数字
if [[ ! $Action =~ ^[0-9]+$ ]];then
	echo "仅支持数字"
	exit 1
fi

if [ ${#Action} -ne 1 ];then
	echo "仅支持一位数字"
	exit 1
fi

#判断
if [ $Action -eq 1 ];then
	echo "1) Installed PHP 5.5"
elif [ $Action -eq 2 ];then
	echo "2) Installed PHP 7.0"

elif [ $Action -eq 3 ];then
	echo "3) Installed PHP 7.3"

else
	exit 1
fi

需求5:

1.如果姑娘小于18岁,打印“未成年”
2.如果姑娘大于18岁小于25岁,打印“表白”
3.如果姑娘大于25岁小于45岁,打印“阿姨好”。
4.如果姑娘大于45岁,打印“奶奶好”

[root@manager if]# cat if-24.sh
#!/bin/bash

read -p "请输入她的年龄:" nl

if [ $nl -gt 45 ];then
	echo "奶奶好"

elif [ $nl -gt 25 -a $nl -lt 45 ];then
	echo "阿姨好"

elif [ $nl -gt 18 -a $nl -lt 25 ];then
	echo "表白"

else
	echo "未成年"

fi

需求6:写一个脚本,提示用户输入身高,如果身高达到180以上全票,120以下免票,其余不能进。

#思路:
1.需要交互
2.判断  超过180
3.判断  低于120
4.其他  over

[root@manager if]# cat if-25.sh
#!/bin/bash

read -p "请输入你的身高: " Action

if [ $Action -ge 180 ];then
	echo "全票"
else
	if [ $Action -lt 120 ];then
		echo "免票"
	else
		echo "over"
		exit
	fi
fi

需求7:写一个Nginx安装脚本,加入判断,当上一步执行成功在执行下一步,否则退出脚本

[root@manager1 if]# cat if-26.sh
#!/bin/bash

#1.网络
ping -W1 -c1 www.baidu.com &>/dev/null
if [ $? -ne 0 ];then
	echo "网络存在故障...."
	exit 1
fi

#2.源  记得要判断系统
if [ -f /etc/yum.repos.d/epel.repo ];then
	if [ -s /etc/yum.repos.d/epel.repo ];then
		echo "yum repos skip ...."
	else
		echo "epel 为空  wget ..."
		#wget .... 
	fi
else
	echo "epel文件不存在"
	#wget .......
fi

#3.安装
rpm -q nginx &>/dev/null
rc=$?

if [ $rc -eq 0 ];then
	echo "nginx已安装"
else
	yum install nginx -y 
fi

需求8:在每月第一天备份并压缩/etc目录的所有内容,存放到/opt/bak目录,存放的形式2019_04_10_etc.tar.gz,脚本名称为fileback,存放在/root的家目录下。

#思路:
1.备份什么	/etc
2.备份到哪	/root/bak
3.备份周期	每月1号 crond

[root@manager if]# cat if-27.sh
#!/bin/bash

Dest_Dir=/opt/bak
Date=$(date +%F)
#准备存放的目录
if [ ! -d $Dest_Dir ];then
	mkdir -p $Dest_Dir
fi

#打包并将内容存放置备份的目录
cd / && tar czf $Dest_Dir/etc_${Date}.tar.gz etc 

#判断是否ok
if [ ! -f $Dest_Dir/etc_${Date}.tar.gz ];then
	echo "备份失败>......"
fi

1.监控内存小于500M和磁盘容量小于10G,则发邮件报警

#思路:
1.剩余内存低于500M    free -m |awk '/^Mem/ {print $NF}'
2.剩余磁盘低于10G	  df -h|awk '/\/$/ {print $(NF-2)}'

[root@manager if]# cat if-28.sh
#!/bin/bash

Free=$(free -m |awk '/^Mem/ {print $NF}')
Disk=$(df -h|awk '/\/$/ {print $(NF-2)}')


if [ $Free -lt 500 -a ${Disk%G} -lt 10 ];then
	echo "报警......"
else
	echo "目前一切良好"
	echo "内存是: ${Free}M   磁盘是: $Disk"
fi

2.检测本机当前用户是否为超级管理员,如果是管理员,则使用 yum 安装 vsftpd,如果不是,则提示您非管理员

[root@manager if]# cat if-29.sh
#!/bin/bash

if [ $UID -eq 0 ];then
	yum install vsftpd -y
else
	echo "你不是管理员>.."
	exit
fi

3.输入三个数并进行升序排序

[root@manager if]# cat if-30.sh
#!/bin/bash

if [ $# -ne 3 ];then
	echo "请传递三个参数"
	exit 
fi
echo "$1 $2 $3" | xargs -n1 | sort -n

4.提示用户输入年份后判断该年是否为闰年 能整除4, 并且不能被100整除则为 闰年

#思路:
2012 / 4  = 整数  -a    2012 / 100 = 有余数   

1.传递年份   2012 2013 
2.用年份除以4
	2.1 在用年份除以100
		如果有余数  则是润年
		如果没有    则是平年

[root@manager if]# cat if-31.sh
#!/bin/bash

read -p "请输入你想检测的年份: " Action
#1.先除以4
rn=$(( ${Action} % 4 ))
rn_2=$(( ${Action} % 100 ))
rn_3=$(( ${Action} % 400 ))


#1.判断是否能被400整除
if [ $rn_3 -eq 0 ];then
	echo "$Action 为闰年"
	exit 
else
	#2.没有被400整除的, 先除以4
	if [ $rn -eq 0 ];then
		#3.成立,在除以100,有余数则润
		if [ $rn_2 -ne 0 ];then
			echo "$Action 为闰年"
			exit
		fi
	fi
fi
	echo "$Action 为平年"
----------------------------------方法二----------------------------------------------------
[root@manager if]# cat if-32.sh
#!/bin/bash

read -p "请输入年份: " Y
if [ $[$Y%4] -eq 0 -a $[$Y%100] -ne 0 ] || [ $[$Y%400] -eq 0 ];then
   echo "$Y 是闰年"
else
   echo "$Y 是平年

5.根据用户输入密码位数,生成随机密码(包含数字、大小写字母、特殊符号)

#思路:
1.怎么生成随机数  mkpasswd -l 8
2.控制输入的长度,最少8位

[root@manager if]# cat if-33.sh
#!/bin/bash

read -p "请输入你想生成的随机数密码位数: " Action
#控制回车

#控制必须是数字

if [ $Action -ge 7  -a $Action -lt 20 ];then
	mkpasswd -l $Action
else
	echo "复杂度密码必须7位以上"
fi

使用case编写脚本案例

需求1:使用case实现nginx服务启停脚本。

1.如何启动 /usr/sbin/nginx

2.如何停止 /usr/sbin/nginx -s stop

3.如何重载 /usr/sbin/nginx -s reload

[root@manager case]# cat case-1.sh
#!/bin/bash

source /etc/init.d/functions 
#加锁
Lock=/tmp/nginx.lock 
if [ -f $Lock ];then
     echo "此脚本正在运行,请稍后....."
     exit 
fi 
touch $Lock 
rc=$1
case $rc in
     start) 
        if [ -f /var/run/nginx.pid ];then
         sleep 10 
            action "nginx服务已经启动...." /bin/false 
else
            /usr/sbin/nginx
             action "nginx服务启动成功..." /bin/true
         fi 
        ;; 
    stop)
         if [ -f /var/run/nginx.pid ];then
             /usr/sbin/nginx -s stop
             if [ $? -eq 0 ];then
                 action "nginx关闭成功..." /bin/true
             else
                 action "nginx关闭失败..." /bin/false
             fi
         else
             action "nginx已经关闭...[error] open() /run/nginx.pid" /bin/false
         fi
                  ;; 
    reload)
         if [ -f /var/run/nginx.pid ];then
             /usr/sbin/nginx -t &>/dev/null
             if [ $? -eq 0 ];then
                 /usr/sbin/nginx -s reload
                 if [ $? -eq 0 ];then
                     action "nginx重载成功..." /bin/true
                 else
                     action "nginx重载失败..." /bin/false
                     fi
             else
                 /usr/sbin/nginx -t &>err.txt
                 nginx_conf=$(awk -F "[: ]" 'NR==1{print $(NF-1)}' err.txt) 
                 nginx_line=$(awk -F "[: ]" 'NR==1{print $(NF)}' err.txt)
                 /usr/sbin/nginx -t
                 read -p "$nginx_conf 配置文件有错,在第 $nginx_line 行, 是否要需要进行配置修改[y|n]: " re
                 case $re in
                     y|yes|YES)
                         vim +${nginx_line} ${nginx_conf}
                         ;;
                     n|no|NO) 
                        echo "你可以选择手动修改,再见!"
                         ;;
                     *)
                         echo "USAGE: $0 {y|n} " 
                esac 
            fi
        else
             action "nginx没有启动,无法完成重载" /bin/false
         fi
         ;;
     status)
         if [ -f /var/run/nginx.pid ];then
             nginx_pid=$(cat /var/run/nginx.pid)
             echo "nginx ( $nginx_pid ) is running...."
         else
             echo "nginx is Not running...."
         fi
         ;;
     *)
         echo "USAGE: $0 [ start | stop | reload | status ] "
esac 

#解锁
rm -f $Lock 
-------------------------------方法二-------------------------------------------------------------
[root@manager case]# cat case-2.sh 
#!/bin/bash


#定义环境变量
. /etc/init.d/functions
nginx_pid="/var/run/nginx.pid"

case $1 in
    start)
    if [ -f $nginx_pid ];then
        if [ -s $nginx_pid ];then
            action "nginx服务已启动" /bin/false
        else
            rm -f $nginx_pid
            systemctl start nginx &> /dev/null
            if [ $? -eq 0 ];then
                action "nginx启动成功" /bin/true
            else
                action "nginx启动失败" /bin/false
            fi
         fi
    else
        systemctl start nginx &> /dev/null
        if [ $? -eq 0 ];then
            action "nginx启动成功" /bin/true
        else
            action "nginx启动失败" /bin/false
        fi
    fi
    ;;
    

stop)
if [ -f $nginx_pid ];then
    systemctl stop nginx && \
    rm -f ${nginx_pid}
        action "nginx服务已停止" /bin/true
    else
        echo "${nginx_pid} : No such file or directory"
fi
;;

status)
if [ -f $nginx_pid ];then
    echo "PID $(cat $nginx_pid) is active..."
else
    echo "${nginx_pid}不存在,服务未启动"
fi
;;

    reload)
    if [ -f $nginx_pid ];then
        nginx -t -c /etc/nginx/nginx.conf &> nginx.error
        rc=$?
        if [ $rc -eq 0 ];then
            action "nginx is reload" /bin/true
        else
            nginx_conf=$(cat nginx.error |awk -F "[ :]" 'NR==1 {print $(NF-1)}')
            nginx_line=$(cat nginx.error |awk -F "[ :]" 'NR==1 {print $NF}')
            read -p "是否进入${nginx_conf} 配置文件中的 ${nginx_line} 行修改: [ yes | no ]" select
                case $select in
                    yes)
                        vim ${nginx_conf} +${nginx_line}
                        ;;
                    no)
                        exit 2
                esac
        fi
    else
        action "nginx 没有启动" /bin/false

​   fi
​   ;;

*)
    echo "USAGE:  $0 {start | stop | status | reload }"
        exit 3

esac

需求2:使用case实现nginx状态监控脚本。 stub_status

#思路:
sh nginx_status.sh
USAGE nginx_status.sh { Active | accepts | handled | requests | Reading  | Writing  |Waiting }
	1.nginx开启状态监控
	[root@manager case]# cat /etc/nginx/conf.d/test.conf 
	server {

		listen 80;
		server_name test.yangdan.com;

		location / {
			index index.html;
		}

		location /nginx_status {
			stub_status;
		}
	}
	2.awk取值		curl -H Host:test.yangdan.com http://127.0.0.1:80/nginx_status
			
	3.case
[root@manager case]# cat case-3.sh
#!/bin/bash

HostName=test.yangdan.com
Nginx_status_file=nginx.status
Nginx_Status_Path=nginx_status

curl -sH Host:${HostName} http://127.0.0.1/${Nginx_Status_Path} >${Nginx_status_file}
case $1 in
	active)
		echo $(( $(awk '/Active connections/ {print $NF}' ${Nginx_status_file}) -1 ))
		;;
	accepts)
		echo $(( $(awk 'NR==3 {print $1}' ${Nginx_status_file}) -1 ))
		;;
	handled)
		echo $(( $(awk 'NR==3 {print $2}' ${Nginx_status_file}) -1 ))
		;;

	requests)
		echo $(( $(awk 'NR==3 {print $3}' ${Nginx_status_file}) -1 ))
		;;
	*)
		echo "USAGE: $0 { active | accepts | handled | requests | Reading  | Writing  | Waiting }"
		exit 1
esac

需求3:使用case实现php-fpm状态监控脚本。

[root@web01 conf.d]# cat test.yangdan.com.conf 
server {
    listen 80;
    server_name test.yangdan.com;
    

location ~ ^/(phpfpm_status)$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}   

}

[root@manager case]# cat case-4.sh 
#!/bin/bash 

HostName=test.cheng.bao.com
php_status_file=phpfpm.status
php_status_path=phpfpm_status

curl -sH Host:${HostName} http://10.0.0.7/${php_status_path} > ${php_status_file}

case $1 in
    pool)
        echo "$(awk '/pool/ {print $NF}' ${php_status_file})"
        ;;
    process_manager)
        echo "$(awk '/process manager/ {print $NF}' ${php_status_file})"
        ;;
    start_time)
        echo "$(awk  '/start time/{print $3,$4}' ${php_status_file})"
        ;;
    start_since)
        echo "$(awk  '/start since/ {print $NF}' ${php_status_file})"
        ;;
    accepted_conn)
        echo "$(awk  '/accepted conn/ {print $NF}' ${php_status_file})"
        ;;
    listen_queue)
        echo "$(sed -n '6p' ${php_status_file} |awk '{print $NF}')"
        ;;
    max_listen_queue)
        echo "$(awk '/max listen/ {print $NF}' ${php_status_file})"
        ;;
    listen_queue_len)
        echo "$(awk '/queue len/ {print $NF}' ${php_status_file})"
        ;;
    idle_processes)
        echo "$(awk '/idle processes/ {print $NF}' ${php_status_file})"
        ;;
    active_processes)
        echo "$(sed -n '10p' ${php_status_file} |awk '{print $NF}')"
        ;;
    total_processes)
        echo "$(awk '/total processes/ {print $NF}' ${php_status_file})"
        ;;
    max_active_processes)
        echo "$(awk '/max active processes/ {print $NF}' ${php_status_file})"
        ;;
    max_children_reached)
        echo "$(awk '/max children reached/ {print $NF}' ${php_status_file})"
        ;;
    slow_requests)
        echo "$(awk '/slow requests/ {print $NF}' ${php_status_file})"
        ;;
    *)
        echo "USAGE: $0 { pool | process_manager | start_time | start_since }"
        exit 1

esac

1:编写脚本,根据用户输入的服务名称查询该服务的状态,并让用户选择启动、关闭、重启、保持不变并输出该服务器以启动、关闭、重启、保持不变

[root@manager case]# cat case-6.sh 
#!/bin/bash

#判断当前执行脚本的是否为超级管理员
if [ $UID -ne 0 ];then
    echo "\"$USER\" $0 Permission denied"
    exit 
fi


#判断用户传入的参数
if [ $# -ne 1 ];then
    echo "USAGE: $0 Service Name [ nginx | httpd | vsftpd | rsyncd ]"
    exit
fi

systemctl status $1 &>/dev/null
if [ $? -eq 4 ];then
    echo "Unit $1 could not be found."
else
    #字符串比对
    system_status=$(systemctl status $1|grep Active|awk '{print $2}')
    if [ $system_status == "active" ];then
        read -p "$1 已启动,你可以选择 [ restart | stop ] " Action
        case $Action in
            restart)
                systemctl restart $1
                echo "$1 重启成功......"
                ;;
            stop)
                systemctl stop $1
                echo "$1 停止成功......"
                ;;
            *)
                exit 1
        esac

#针对没有启动的服务,提示是否启动
elif [ $system_status == "inactive" ];then
    read -p "$1 未启动,可以选择 [ start | quit ] " Action2
    case $Action2 in
        start)
            systemctl start $1
            echo "$1 启动成功"
            ;;
        quit)
            echo "Bye"
            exit
            ;;
        *)
            exit
    esac
fi

 fi


方式二:
[root@manager case]# cat case-5.sh 
#!/bin/bash


read -p "请输入你要查询服务的名称:" Action
systemctl status ${Action} &> /dev/null
if [ $? -eq 0 ];then
    echo "Active: active (running)"
else
    echo "Active: failed"
fi

cat <<EOF
1)启动
2)停止
3)重启
4)退出
EOF

read -p "请输入你需要执行的操作:[ 1 | 2 | 3 | 4 ] " Nu
case ${Nu} in
    1)
        systemctl start ${Action}
        if [ $? -eq 0 ];then
            echo "$Action服务已启动"
        else
            echo "$Action服务未启动"
        fi
        ;;
    2)
        systemctl stop ${Action}
        if [ $? -eq 0 ];then
            echo "$Action服务已停止"
            exit 1
        fi
        ;;
    3)
        systemctl restart ${Action}
        if [ $? -eq 0 ];then
            echo "$Action服务已重启"
            exit 1

​   fi
​   ;;
4)
​   echo "抱歉,没有这个服务,你可以去其他地方找找"

esac

2:输入两个数字,输出着两个数字加减乘除的四个的数(判断输入的是否为两个数字,输入的是否为数字)

[root@manager case]# cat case-7.sh 
#!/bin/bash

if [[ -z $1 || -z $2 ]];then
	echo "请输入数字"
	exit 1
fi

if [[ ! $1 =~ ^[0-9]+$ ]] || [[ ! $2 =~ ^[0-9]+$ ]];then
	echo "请输入两位数字"
	exit 2
fi

echo "$1 + $2 = $[ $1 + $2 ]"
echo "$1 - $2 = $[ $1 - $2 ]"
echo "$1 * $2 = $[ $1 * $2 ]"
echo "$1 / $2 = $[ $1 / $2 ]"
echo "$1 % $2 = $[ $1 % $2 ]"

[root@m01 case]# sh case-7.sh  1 1
1 + 1 = 2
1 - 1 = 0
1 * 1 = 1
1 / 1 = 1

4:取出当前系统日期、时间、当前有几个登陆用户、过去15分钟的平均负载、当前可用内存大小、当前系统空闲时间,输入到/tmp/txt.csv

[root@manager case]# cat case-8.sh 
#!/bin/bash

Date=$(date |awk '{print $3,$4}')	
User=$(who |awk '{print $1}' |wc -l)	
Fzai=$(uptime |awk '{print $NF}')
Neicun=$(free -m |awk '/Mem/ {print $4}')
Time=$(cat /proc/uptime |awk '{print $2}')

echo "当前系统日期时间为: ${Date}" >> /tmp/txt.csv
echo "当前有 ${User} 个普通用户正在登陆" >> /tmp/txt.csv
echo "过去15分钟的平均负载是:  ${Fzai}" >> /tmp/txt/csv
echo "当前可用内存大小: ${Neicun}" >> /tmp/txt.csv
echo "当前系统空闲时间: ${Time}" >> /tmp/txt.csv


[root@manager tmp]# cat txt.csv 
当前系统日期时间为: 30 20:38:35
当前有 2 个普通用户正在登陆
当前可用内存大小: 760
当前系统空闲时间: 4941.93
当前系统日期时间为: 30 20:39:28
当前有 2 个普通用户正在登陆
当前可用内存大小: 760
当前系统空闲时间: 4995.64

5:检测本机当前用户是否为超级管理员,如果是管理员,则使用 yum 安装 vsftpd,如果不是,则提示您非管理员

[root@manager case]# cat case-9.sh 
#!/bin/bash


if [ $UID -eq 0 ];then
	echo "正在安装vsftpd,请稍后... "
	sleep 3
	echo "安装成功!"

else
	echo "你不是管理员,权限不足"
fi

for循环

需求1:批量探测某个网段的主机存活状态,将存活的主机存入ok.txt文件中。

[root@manager for]# cat for-1.sh 
#!/bin/bash

for i in {1..254}
do
	{
		ip=10.0.0.$i
		ping -W1 -c1 $ip &>/dev/null
		if [ $? -eq 0 ];then
			echo "$ip 存活"
		fi
	}&
done
	wait

需求2:判断主机存活状态,要求判断三次,如果三次失败则失败。

[root@manager for]# cat for-2.sh 
#!/bin/bash


for i in {1..254}
do
    {
			ip=10.0.0.$i
			ping -W1 -c1 $ip &>/dev/null
			if [ $? -eq 0 ];then
				echo "$ip 存活" >> ok.txt

	else
			#如果判断第一次不存活,则在进行一次for循环,循环3次
			for j in {1..3}
			do
				ping -W1 -c1 $ip &>/dev/null
				if [ $? -eq 0 ];then
					echo "$ip 存活" >> ok.txt
				else
					echo "$ip 不存活" >> err.txt
				fi
			done
	fi
 }&
done
	wait

需求3:现在有一个ip.txt的文件,里面有很多IP地址。

还有一个port.txt的文件,里面有很多端口号。
现在希望对ip.txt的每个IP地址进行端口的探测,探测的端口号来源于port.txt文件中
最后将开放的端口和IP保存到一个ok.txt文件。
ip.txt port.txt
10.0.0.1 80
10.0.0.2 22
10.0.0.3 3306
10.0.0.4 23
10.0.0.5 443
10.0.0.6 9000
10.0.0.7 123
10.0.0.8 6379
10.0.0.9 10050
172.16.1.5 10051
192.168.10.1
172.16.1.6

[root@manager for]# cat for-3.sh 
#!/bin/bash

#遍历文件中的IP地址
for ip in $(cat ip.txt)
do
	#第二次循环,遍历文件中的端口号
	for port in $(cat port.txt)
	do
		#探测IP与端口的存活状态
		nc -z -w 1 $ip $port &>/dev/null
		if [ $? -eq 0 ];then
			echo "$ip $port is ok"
		fi
	done
done

需求4:获取系统的所有用户并输出。效果如下:

This is 1 user: root
This is 2 user: bin
This is 3 user: daemon
This is 4 user: adm
...............
1.怎么获取所有的用户 awk -F ":" '{print $1}'
2.遍历/etc/passwd 这个文件
3.如何让数字的编号进行自增

[root@manager for]# cat for-4.sh 
#!/bin/bash

i=1
for user in $(awk -F ":" '{print $1}' /etc/passwd)
do
	echo This is ${i} $user
	#let i++ 
	i=$[ $i + 1 ]
done

需求5:批量创建100个用户,比如输入oldxu则会创建oldxu001-100。

1.怎么输出001-100		seq -w 1 100

[root@manager for]# cat  for-5.sh 
#!/bin/bash
 
for user in $(seq -w 1 100)
do
	useradd $1$user
	echo "$1$user is ok"
done

----------------------------------------------------------------------
----------------------------------------------------------------------
[root@manager for]# cat for-6.sh 
#!/bin/bash

for user in $(seq -w 1 10)
do
	id $1$user &>/dev/null
	if [ $? -ne 0 ];then
		useradd $1$user
		echo "$1$user is ok"
	else
		#表示结束当前本次的循环,直接开始下一次循环
		continue
	fi
done

需求6:批量创建用户脚本,需要用户输入创建的用户数量,以及需要用户输入创建的前缀。例如:前缀oldxu,个数10,代表创建oldxu1~oldxu10,总共10个用户。

[root@manager for]# cat for-7.sh 
#!/bin/bash

read -p "请输入你需要创建的前缀: " qz
read -p "请输入你需要创建的数量: " hz
read -p "你要创建的用户是 $qz , 个数是 $hz 你确定要创建吗? [ y | n ] " : Action
case $Action in
	y|yes|Y)
			for number in $(seq $hz)
			do
				username=$qz$number
				id $username &>/dev/null
				if [ $? -ne 0 ];then
					useradd $username
					echo "$username is ok"			
				else
					#表示结束当前本次的循环,直接开始下一次循环
					continue
				fi
			done
		;;
	n|no|N)
			echo "Bey!"
			exit 
		;;
	*)
		echo "Gdx"
		exit
esac

需求7:批量创建用户脚本,需要用户输入创建的用户数量(必须是整数),同时还需要用户输入前缀(前缀不能为空)。

例如:前缀oldxu,个数10,代表创建oldxu1~oldxu10,总共10个用户。

[root@manager for]# cat for-8.sh 
#!/usr/bin/bash

read -p "请输入你需要创建的前缀: " qz
if [ -z $qz ];then
	echo "回车做什么  gdx...."
	exit
fi

read -p "请输入你需要创建的数量: " hz
if [[ ! $hz =~ ^[0-9]+$ ]];then
	echo "让你输数字,,,,emm"
	exit
fi
read -p "你要创建的用户是 $qz , 个数是 $hz 你确定要创建吗? [ y | n ] "  Action
case $Action in
	y|yes|Y)
		for number in $(seq $hz)
		do
			username=$qz$number
			id $username &>/dev/null
			if [ $? -ne 0 ];then
				useradd $username
				echo "$username is ok"			
			else
				#表示结束当前本次的循环,直接开始下一次循环
				continue
			fi
		done
		;;
	n|no|N)
			echo "Bey!"
			exit 
		;;
	*)
		echo "Gdx"
		exit
esac

需求8:循环批量创建用户,需要填入用户的数量、用户的前缀、用户的统一密码(使用read、case、for语句)

[root@manager for]# cat for-9.sh 
#!/usr/bin/bash

read -p "请输入你需要创建的前缀: " qz
if [ -z $qz ];then
	echo "回车做什么  gdx...."
	exit
fi

read -p "请输入你需要创建的数量: " hz
if [[ ! $hz =~ ^[0-9]+$ ]];then
	echo "让你输数字,,,,emm"
	exit
fi

read -p "请输入所有用户统一的密码: " pw


read -p "你要创建的用户是 $qz , 个数是 $hz  密码是 $pw 你确定要创建吗? [ y | n ] "  Action
case $Action in
	y|yes|Y)
		for number in $(seq $hz)
		do
			username=$qz$number
			id $username &>/dev/null
			if [ $? -ne 0 ];then
				useradd $username
				echo "$pw" | passwd --stdin $username
				echo "$username $pw is create ok"			
			else
				#表示结束当前本次的循环,直接开始下一次循环
				continue
			fi
		done
		;;
	n|no|N)
			echo "Bey!"
			exit 
		;;
	*)
		echo "Gdx"
		exit
esac

需求9:通过读入文件中的用户,进行批量添加用户。

[root@manager for]# cat for-10.sh 
#!/bin/bash 

for user in $(cat user.txt)
do
	useradd $user

done

需求10:通过读入文件中的用户与密码文件,进行批量添加用户。文件中的格式: user:passwd

[root@manager for]# cat for-11.sh 
#!/bin/bash

for user in $(cat user.txt)
do
	us=$(echo $user|awk -F ":" '{print $1}')
	pw=$(echo $user|awk -F ":" '{print $2}')

	id $us &>/dev/null
	if [ $? -eq 0 ];then
		continue
	else
		useradd $us
		echo "$pw" | passwd --stdin $us &>/dev/null 
		echo "$us is create ok......"
	fi

done

需求11: 批量创建用户,用户名oldxu01-100 密码随机(8~12), 然后将创建成功的用户名及密码写入到一个文件中.

oldxu01:dasd1#!@#!@dsa
oldxu02:dascxasdas1!@#

[root@manager for]# cat for-12.sh 
#!/bin/bash 

#1.创建100个用户
for user in aa{1..10}
do

	  #2.设定随机密码 (for循环一次,就生成一次)
	  pass=$(mkpasswd -l 8)

	  #3.创建用户
	  useradd $user &>/dev/null
	  echo "$pass" | passwd --stdin $user &>/dev/null
	
	  #4.保存每次循环的用户名和密码
	  echo "$user:$pass" | tee -a  pass.txt
done

需求12:使用case实现批量删除用户。

1.提示用户输入需要删除的用户以及删除的个数。
2.如果用户存在则删除,如果不存在则提示no such user。
[root@manager for]# cat for-13.sh 
#!/bin/bash
 
read -p "请输入删除的用户: " qz
read -p "请输入删除的个数: " hz
read -p "是否要删除: [ y | n ]" Action

case $Action in
	y)
		for user in $(seq $hz)
		do
			username=$qz$user
			id $username &>/dev/null
			if [ $? -eq 0 ];then
				userdel -r $username 
				echo "$username is delete....."
			else
				echo "$username no such user ....."
				continue
			fi
		done
	;;
	n)
		exit
		;;
	*)
		exit
esac

需求14: 写一个倒计时脚本.

[root@manager for]# cat for-14.sh 
#!/bin/bash
 
for i in {10..1}
do
	echo -n -e "最后倒计时:   $i \r"
	sleep 1
done

需求15:编写一个上课随机点名脚本。

[root@manager for]# cat for-15.sh 
#!/bin/bash

if [ -s name.txt ];then
	 User=$(sort --random-sort name.txt |awk 'NR==1')
	 echo "$User" 
	 
	 grep $User name.txt >> name1.txt
	 sed -i '/'$User'/d' name.txt

 else
 	cat name1.txt>name.txt
	rm -rf name1.txt
fi


[root@manager for]# cat for-16.sh 
#!/bin/bash

#1.只循环20次
for i in {1..20}
do
	#统计一下名单中的行号
	line=$(cat name.txt|wc -l)

	#设定一个随机的变量值,但这个值不能超过文件名单的行号
	sj=$(( ${RANDOM}%$line+1 ))
	
	# 循环20次,打印20次名单
	echo  -e "  $(sed -n "${sj}p" name.txt) "
	sleep 0.1

done
	sj=$(( $sj + 1 ))
    username=$(sed -n "${sj}p"  name.txt)
    echo -e 这次回答问题的是: "\033[32m $username \033[0m" 同学。

需求16:抓取https://mirrors.aliyun.com/zabbix/zabbix/4.0/rhel/7/x86_64/页面中的所有rpm包至本地

[root@manager for]# cat for-17.sh 
#!/bin/bash
 
#1.获取网页的源代码
#2.对网页源代码进行过滤筛选,提取文件名称
#3.将下载的url和文件名称拼接,通过wget下载

Url_File=url.txt
Pkg_Name=$(grep "<a href=" $Url_File | awk -F '"' '{print $2}' | egrep -v "debuginfo|repodata|\.\./")
Get_Url=https://mirrors.aliyun.com/zabbix/zabbix/4.0/rhel/7/x86_64/

for package in $Pkg_Name
do
	#完整的下载url地址
	url_package=$Get_Url$package

	#指定下载至某个目录
	wget -O /mnt/$package    $url_package &>/dev/null

	#判断下载是否正常
	if [ $? -eq 0 ];then
		echo "软件包: $pkg is ok..."
	fi
done

需求17:使用for循环备份mysql库,每个库对应一个sql文件,需要排除没用的。

1.拿到需要的库名称  wordpress jpress zabbix zrlog 
2.循环拼接备份命令   mysqldump -uroot -poldxu.com  -B zabbix >/mysql/data/zabbix.sql
[root@db01 ~]# cat for-18.sh 
#!/usr/bin/bash

db_path=/backup/mysql
date_time=$(date +%F)
db_name=$(mysql -uroot  -e  "show databases;" |sed 1d|egrep -v "*_schema|mysql|test")

[ -d $db_path ] || mkdir $db_path -p


for i in $db_name
do
	mysqldump -uroot -B ${i} >$db_path/${i}_${date_time}.sql
	if [ -f $db_path/${i}_${date_time}.sql ];then
		echo "$i backup is done....."
	else
		echo "$i backup is error...."
	fi
done
	#保留最近180天的数据
	find $db_path -type f -mtime +180 -delete | xargs rm -rf 	

需求18:使用for嵌套循环实现分库分表备份。

分库:  值得是多个库分开备份.
分表:  一个库中有多个表,将多个分开备份

备份表
mysqldump -u<username> -p<password> dbname tablename1 tablename2... > /path/to/***.sql
mysqldump -uroot -poldxu.com  wordpress  t1 >/mysql/data/wordpress/2019-11-1/t1.sql

1.取出所有的库名称
2.取出库对应的所有表
3.将命令拼接在一起完成备份

[root@db01 ~]# cat for-19.sh 
#!/usr/bin/bash
db_path=/backup/mysql
date_time=$(date +%F)
db_name=$(mysql -uroot  -e  "show databases;" |sed 1d|egrep -v "*_schema|mysql|test")

#准备备份的目录
[ -d $db_path ] || mkdir $db_path -p

#1.获取所有的库名称
for i in $db_name
do
	#1.获取对应库的所有表
	db_table=$(mysql -uroot -e "use $i; show tables;"|sed 1d)
	for j in $db_table
	do
		[ -d $db_path/$i/$date_time ] || mkdir $db_path/$i/$date_time -p
		mysqldump -uroot $i $j >$db_path/$i/$date_time/${j}.sql
	done
done

while

while本质上就是循环
只不过while支持条件测试语句
	整数比对
	字符串比对
	正则比对
	文件比对

while读入文件的方式比较的特殊 
	while读入文件按行读取   IFS指定分隔符
	for读入文件按空格读取	IFS指定分隔符

while read  file
do
	echo $file
done < /etc/passwd

需求1: 使用while读入文件方式,批量创建用户

[root@manager while]# cat while-1.sh 
#!/bin/bash

while read line
do
	id $line &>/dev/null
	if [ $? -eq 0 ];then
		continue
	else
		useradd $line
	fi
done < user.txt

需求2: 使用while读入文件方式,批量创建用户以及密码 文件格式: username:password

[root@manager while]# cat while-2.sh 
#!/bin/bash


while read line
do
	user=$(echo $line | awk -F ":" '{print $1}')
	pass=$(echo $line | awk -F ":" '{print $2}')
	
	id $user &>/dev/null
	if [ $? -eq 0 ];then
		continue
	else
		useradd $user 
		echo "$pass" | passwd --stdin $user
	fi
done <user.txt

需求3: 猜数字游戏

1)随机输出一个1-100的数字 echo \(((\)RANDOM%100+1))
2)要求用户输入的必须是数字(数字处加判断)
3)如果比随机数小则提示比随机数小了 大则提示比随机数大了
4)正确则退出 错误则继续死循环
5)最后统计猜了多少次(猜对了多少次,失败多少次)

[root@manager while]# cat while-3.sh 
#!/bin/bash


SJ=$(($RANDOM%100+1))
i=1

while true
do
	read -p "请输入你要猜的数: " Action

	if [ $Action -eq $SJ ];then
		echo "恭喜你 gdx...."
		break

	elif [ $Action -lt $SJ ];then
		echo "太小了 gdx...."
	else
		echo "太大了 gdx...."
	fi
	let i++
done
	echo "你总共猜了 $i 次, 失败了 $(( $i-1 )) 次"

需求4: 在一个2000多行数据文件,然后有10个新的文件,1-5行数据放到第一个文件里,6-10行数据 放到第二个文件里...46-50数据放到第10个文件里。然后51-55数据在放到第一个文件里。如何实现?【可忽略】

[root@manager while]# cat while-4.sh 
#!/bin/bash


while true
do
	for i in $(seq 10)
	do
		head -5 file.txt >> file_$i.txt
		sed -i '1,5d' file.txt

		if [ ! -s file.txt ];then
			exit
		fi
	done
done
-------------------------方法二---------------------------------------------
[root@manager while]# cat while-5.sh 
#!/bin/bash
a=0
b=0
while [ $b -lt 2000 ]
do
        file=num.txt
        while [ $a -lt 10 ]
        do
                a=$[$a+1]
                b=$[$b+5]
                echo "$a $b"
                line=$(awk "NR==$[$b-4],NR==$b" $file)
                echo "$line">>${a}.txt
        done
        a=0
done

1.按照时间生成文件2018-05-22.log将每天的磁盘使用状态写入到对应日期的文件

df -h > $(date +%F).log

echo "`df -h`" > $(date +%F).log

2.统计Nginx日志中每个IP的访问量有多少,日志如下:

192.168.56.1 - - [21/May/2018:20:44:06 -0400] "GET /index.html HTTP/1.0" 404 169 "-" "ApacheBench/2.3" "-"/code/index.html

cat /var/log/nginx/access.log |awk '{print $1}'|sort -u|uniq -c

3.写一个脚本计算一下Linux系统所有进程占用内存大小的和。

[root@manager while]# cat while-1.sh         内存
#!/bin/bash

sum=0
for mem in `ps aux |awk '{print $6}'|grep -v "RSS"`
do
	sum=$[$sum+$mem]
done
	echo "The total memory is $sum"

4.在/backup下创建10个.txt的文件,找到/backup目录下所有后缀名为.txt的文件

1.批量修改txt为txt.bak
2.把所有的.bak文件打包压缩为123.tar.gz
3.批量还原文件的名字,及把增加的.bak再删除
-------------------方法一----------------------------------------------
[root@manager while]# cat while-2.sh 
#!/bin/bash

#1)批量修改txt为txt.bak
#2)把所有的.bak文件打包压缩为123.tar.gz
#3)批量还原文件的名字,及把增加的.bak再删除

dir=/backup
#1、判断目录是否存在,不存在则创建
if [ -f $dir ];then
	echo "$dir 已存在"
else
	echo "$dir 不存在,则创建" && mkdir -p $dir
fi

#2、创建10个.txt的文件
touch $dir/{1..10}.txt

#3、批量修改名称
find $dir -type f -name "*.txt" > $dir/txt.log
sed -r 's#(.*)#mv \1 \1.bak#g' $dir/txt.log |bash

#4、打包压缩
tar czf $dir/123.tar.gz $dir/*.bak

#5、还原
find $dir -type f -name "*.bak" > $dir/bak.log
sed -r 's#(.*).bak#mv \1.bak \1#g' $dir/bak.log |bash

--------------------方法二--------------------------------------------------
[root@manager while]# cat while-3.sh 
#!/bin/bash

#1)批量修改txt为txt.bak
#2)把所有的.bak文件打包压缩为123.tar.gz
#3)批量还原文件的名字,及把增加的.bak再删除

#定义变量
T=txt
B=bak
dir=/backup
#把nackup目录下.txt结尾的文件修改为txt.bak
cd $dir && rename $T $T\.$B *.txt

#把所有的.bak结尾的文件打包压缩为123.tar.gz
tar zcvf $dir/123.tar.gz $dir/*bak

5.把一个文本文档的前五行中包含字母的行删除掉,同时把6到10行中的全部字母删除掉

[root@manager while]# cat while-4.sh 
#! /bin/bash

## 把一个文本文档的前5行中包含字母的行删除掉,同时把6到10行中的全部字母删除掉。
## 假设文本名字叫做1.txt,并且文本行数大于10,脚本如下。
##先获取该文本的行数
nu=`wc -l 2.txt | awk '{print $1}'`
##对前5行进行处理
for i in `seq 1 5`
do
##使用sed把每一行的内容赋值给变量
l=`sed -n "$i"p 2.txt`
##用grep判定是否匹配字母,-v取反,-q不输出内容
if echo $l |grep -vq '[a-zA-Z]'
then
echo $l
fi
done
##对6-10行做删除处理
for i in `seq 6 10`
do
l=`sed -n "$i"p 2.txt`
echo $i | sed 's/[a-zA-Z]//g'
done
##剩余的直接输出
for i in `seq 11 $nu`
do
sed -n "$i"p 2.txt
done

7.写个shell,看看你的linux系统中是否有自定义用户(普通用户),若是有,一共有几个?

[root@m01 while]# cat while-5.sh
#!/bin/bash

v=`awk -F 'release ' '{print $2}' /etc/redhat-release |cut -d '.' -f1`
user()
{
	if [ $1 -eq 0 ];then
		echo "系统没有自定义的用户"
	else
		echo "系统存在自定义用户,有$1个"
	fi
}
case $v in
	7)
		n=`awk -F ':' '$3>=1000' /etc/passwd|wc -l`
		user $n
	;;

	*)
		echo "脚本出错."
		;;
esac 

9.中企动力面试题

用shell处理以下内容
1、按单词出现频率降序排序!
2、按字母出现频率降序排序!
the squid project provides a number of resources toassist users design,implement and support squid installations. Please browsethe documentation and support sections for more infomation

[root@manager while]# cat while-6.sh 
#!/bin/bash

str="the squid project provides a number of resources toassist users design,implement and support squid installations. Please browsethe documentation and support sections for more infomation"

#1、按单词出现的频率降序排序
word(){
	echo $str |sed 's#[^a-zA-Z]#\n#g'|grep -v "^$" |sort|uniq -c |sort -rn -k1
}

#1、按字母出现的频率降序排序
string(){
	echo $st|grep -o "."|egrep -v "[^a-zA-Z]" |sort|uniq -c|sort -rn -k1
}

menu(){
cat <<END
	1、按单词出现频率降序排序!
	2、按字母出现频率降序排序!
END
	read -p "Pls you choose num:" num
}
menu

usage(){
	echo "USAGE:you muset choose 1 or 2"
	exit 1
}

case "$num" in
	1)
		word
		;;
	2)
		string
		;;
	*)
		usage
esac

10.写一个脚本,实现判断10.0.0.0/24网络里,当前在线用户的IP有哪些

[root@manager while]# cat while-7.sh 
#!/bin/bash

for i in `seq 1 255`
do
        ping -c 1 10.0.0.$i &>/dev/null
	if [ $? -eq 0 ];then
		echo -e "10.0.0.$i is up."
	else
		echo -e "10.0.0.$i is down."
	fi
done

11.使用case实现系统管理工具箱。

Command action
h 显示命令帮助
f 显示磁盘分区
d 显示磁盘挂载
m 查看内存使用
u 查看系统负载
q 退出程序

[root@manager while]# cat while-8.sh
#!/bin/bash

cat <<EOF
==================
h 显示命令帮助    

f 显示磁盘分区

d 显示磁盘挂载

m 查看内存使用

u 查看系统负载

q 退出程序
===================
EOF
read -p "请输入你需要做的操作:" sys 
case $sys in
	h)
		man help
            	;;
	f)
		df -h
                ;;
        d)
		mount -a |less
		;;
	u)
		w
	        ;;
	q)
		exit
		;;
	*)
		echo "你输错了..."
esac

12.实现简单的JumpServer

1.执行脚本后,需要看到所有我能管理的主机

2.有一个选择菜单,提示输入连接某个主机

3.需要写一个死循环,保证程序连接后端服务,退出后还能接着选择主机。

4.不能让跳板机直接ctrl+c ctrl+z退出了,trap 控制ctrl+c ctrl+z的信号

5.退出服务器的会话,再次登录,又可以正常操作服务器。将脚本加入到/etc/bashrc中,当用户一连接,自动就运行该脚本。

[root@manager while]# cat jumpserver1.sh
#!/usr/bin/bash
meminfo(){
cat <<-EOF
-------------------------------
| 1) db01-172.16.1.52 |
| 2) db02-172.16.1.53 |
| 3) db02-172.16.1.54 |
| h) help |
---------------------------------
EOF
}
meminfo
    trap "" HUP INT TSTP #控制不让输出Ctrl+c,z
while true
do
    read -p "请输入你需要连接的主机序号[1|2|3|..]: " connection
    case $connection in
        1)
            ssh root@172.16.1.52
                ;;
        2)
            ssh root@172.16.1.53
                ;;
        3)
            ssh root@172.16.1.54
                ;;
        h) 
           clear
            meminfo
            ;;
        exec) 
           exit
            ;;
        *)
            echo "USAGE: $0 输入连接的主机编号即可 [ 1 | 2 | 3 | ]"
    esac
done

13.case场景示例,实现多级菜单功能

[root@manager while]# cat while-9.sh
#!/bin/bash

mem_option (){
cat << EOF
-------主菜单-------
1) 安装nginx 

2) 安装PHP

3) 退出
--------------------
EOF
}

mem_install_nginx (){
cat <<EOF
---------------------
1) 安装nginx1.1

2) 安装nginx1.2

3) 安装nginx1.3

4) 返回上一页
---------------------
EOF
}

mem_install_php (){
cat <<EOF
------------------------
1) 安装PHP5.5

2) 安装PHP5.6

3) 安装PHP7.0

4) 返回上一页
-----------------------
EOF
}

while true
do
	mem_option
	read -p "请输入主菜单需要选择的选项,使用方法[ 1 | 2 | 3 ]:" option
	case $option in
		1)
			clear
			while true
			do
				mem_install_nginx
				read -p "请输入你要安装nginx的Version:" nginx_install_option
				case $nginx_install_option in
					1)
						clear
						echo "Installed nginx Version 1.1 is Done...."
						sleep 1
						;;
					2)
						clear
						echo "Installed nginx Version 1.2 is Done....."
						sleep 1
						;;
					3)
						clear
						echo "Installed nginx Version 1.3 is Done....."
						sleep 1
						;;
					4)
						clear
						break
						;;
				esac
			done
				;;

		2)
			clear
			while true
			do
				mem_install_php
				read -p "请输入你要选择的PHP Version:" php_install_option
				case $php_install_option in
					1)
						clear
						echo "Installed php Version 5.5 is Done......"
						sleep 1
						;;
					2)
						clear
						echo "Installed php Version 5.6 is Done......"
						sleep 1
						;;
					3)
						clear
						echo "Installed php Version 7.0 is Done......"
						sleep 1
						;;
					4)
						clear
						break
						;;
					*)
				esac
			done
			;;
		3)
			exit
			;;
		*)
			echo "USAGE: [ 1 | 2 | 3 ]"
	esac
done

函数

1.如何定义函数和调用函数

fun01 () { echo "Hello World"; } 
fun01

2.如何给函数传递一个参数

fun01 () { echo "Hello $1"; } 
fun01 SHell			#执行时跟上一个固定的参数
fun01 $1			#执行时跟上一个不固定的参数    (脚本的位置参数,需要执行脚本时传递)

3.函数接收N多个参数传递

fun01 () { echo "Hello $*"; } 
fun01 liunx shell  Python  Test

4.函数传参

第一种方式
fun01 () {
	echo "Hello $1"
}

#脚本的位置参数
fun01 $1

需求,写一个脚本,该脚本可以实现计算器的功能,可以进行 +- * / 四种计算。

例如: sh cal.sh 30 + 40 | sh cal.sh 30 - 40 | sh cal.sh 30 * 40 | sh cal.sh 30 / 40

[root@manager functions]# cat fun01.sh 
fun () {
	case $2 in
		+)
			echo $1 + $3 = $[ $1 + $3 ]
			;;
		-)
			echo $1 - $3 = $[ $1 - $3 ]
			;;
		x)
			echo $1 x $3 = $[ $1 * $3 ]
			;;		
		/)
			echo $1 / $3 = $[ $1 / $3 ]
			;;
	esac
}
	fun $1 $2 $3

需求:写一个脚本,实现nginx服务的启动、停止、重启 (简单实现,在判断阶段使用函数来做。)

1.先实现启动和停止
2.在优化脚本

[root@manager functions]# cat fun02.sh 
#!/bin/bash

ngx_status=$1

nginx_is_status () {
	
	systemctl $ngx_status nginx
	if [ $? -eq 0 ];then
		echo "nginx is $ngx_status"
	else
		echo "nginx is $ngx_stauts err"
		exit 1
	fi
}

case $ngx_status in
	start)
		nginx_is_status
		;;

	stop)
		nginx_is_status
	;;
	*)
		echo "USAGE: $0 { start | stop | restart }"
		exit
esac

函数实例脚本: echo

echo "The 1 user is : root"
echo "The 2 user is : bin"

[root@manager functions]# cat fun03.sh 
#!/bin/bash

get_users () {
	user=$(awk -F ":" '{print $1}' /etc/passwd)
	echo $user
}

#将函数输出的结果,从新赋值给user_list变量存储起来
user_list=$(get_users)

index=1
for u in ${user_list}
do
	echo "The $index user is : $u"
	let index++
done

函数实例脚本: return

[root@manager functions]# cat fun04.sh 
#!/bin/bash
 
file=$1            #定义文件

t_file(){                   #函数判断
    if [ -f $file ];then
        return 0
    else
        return 1
    fi
}

$?
t_file
rc=$?

if [ $rc -eq 0 ];then
	echo "该文件存在 $file"
else
	echo "该文件不存在 $file"
fi
---------------------------------------------------------------------------

[root@manager functions]# cat fun05.sh 
#!/bin/bash
 
fun () {
	systemctl status nginx &>/dev/null

	if [ $? -eq 0 ];then
		return 0
	else
		return 100
	fi

}
fun
echo $?

retrun: 主要控制函数的返回值   可以理解是命令执行后的结果
echo:  主要控制函数的返回数据

[root@manager functions]# cat fun06.sh 
#!/bin/bash

#根据用户传递的服务名称,获取不同服务的状态
is_server_running(){
	systemctl status $1 &>/dev/null
    if [ $? -eq 0 ];then
        return 0
    else
        return 1
    fi
}
#调用函数,并根据函数返回状态码进行输出
is_server_running $1 && echo "$1 is Running" || echo "$1 is stoped

需求1:使用函数、循环、case实现系统管理工具箱。

Command action
h 显示命令帮助
f 显示磁盘分区
d 显示磁盘挂载
m 查看内存使用
u 查看系统负载
q 退出程序

[root@manager functions]# cat fun07.sh 
#!/bin/bash 

meminfo () {
cat <<-EOF
----------------------------
	Command action
	h 显示命令帮助
	f 显示磁盘分区
	d 显示磁盘挂载
	m 查看内存使用
	u 查看系统负载
	q 退出程序
---------------------------
EOF
}
	meminfo

while true
do
	read -p "请输出你要选择选项: " Action
	case $Action in 
		h)
			help
			;;
		f)
			lsblk
			;;
		d)
			df -h
			;;
		m)
			free -m
			;;
		u)
			uptime
			;;
		q)
			exit
			;;
		*)
			continue

	esac
done

需求3:使用case、循环、函数、实现JumpServer跳板机功能。

1.用户登陆该服务器则自动执行该脚本。 pass
2.脚本提示可连接主机列表。
3.该脚本无法直接退出。 pass

[root@manager functions]# cat fun08.sh 
#!/bin/bash

meminfo(){
        cat <<-EOF
        -------------------------------
        |       1) lb01-172.16.1.5      |
        |       2) lb02-172.16.1.6      |
        |       3) web01-172.16.1.7     |
        |       4) web02-172.16.1.8     |
        |       h) help                 |
        ---------------------------------
	EOF
}
	meminfo
	trap "" HUP INT TSTP

while true
do
	read -p "请输入你要登录的主机: " Action
	
	case $Action in
		1|lb01)
			ssh root@172.16.1.5
		;;
		2|lb02)
			ssh root@172.16.1.6
		;;
		3|web01)
			ssh root@172.16.1.7
		;;
		4|web02)
			ssh root@172.16.1.8
		;;
		h)
			clear
			meminfo
		;;
		exec)
			exit
			;;
		*)
			continue
	esac
done

5.case场景示例,实现多级菜单功能,需要使用到函数、case、循环、if判断、变量

info {
index1: linux
index2: nginx
index3: docker
index4: bash shell
}

[root@manager functions]# cat fun09.sh 
#!/bin/bash
# Author:      Oldux.com QQ: 552408925
# Date:       2019-11-04
# FileName:   array01.sh
# URL:         https://www.xuliangwei.com
# Description: 

while read line
do
	host[i++]=$line
done </etc/hosts

for item in ${!host[@]}
do
	echo "你的索引是: $item   你对应的值是: ${host[$item]}"
done

正则表达式

grep 实现正则表达式
sed 流编辑器 -->脚本

Usage: 
	grep [OPTION]... PATTERN [FILE]...
	command studot | grep [OPTION]... PATTERN

[^a-z]	
[0-9]{11}				#必须刚刚好11
[0-9]{11,}				#至少11,也可以是11以上
[0-9]{8,11}				#最少8次,最多11次
[A-Z]
^(133|152|166)[0-9]{8} 
^.*
^
$

ls file-*
ls *				#通配符一般用于筛选文件
grep * filename		#正则表达式一般用于匹配文件的内容,或者用户输入的内容


正则表达式	描述
\		转义符,将特殊字符进行转义,忽略其特殊意义
^		匹配行首,则是匹配字符串的开始
$		匹配行尾,$则是匹配字符串的结尾
^$		表示空行
.		匹配除换行符\n之外的任意单个字符
[ ]		匹配包含在[字符]之中的任意一个字符
[^ ]	匹配[]之外的任意一个字符
[ - ]	匹配[]中指定范围内的任意一个字符
?		匹配之前的项1次或者0次
+		匹配之前的项1次或者多次
*		匹配之前的项0次或者多次, .*
()		匹配表达式,创建一个用于匹配的子串
{ n }	匹配之前的项n次,n是可以为0的正整数
{n,}	之前的项至少需要匹配n次
{n,m}	指定之前的项至少匹配n次,最多匹配m次,n<=m
|		交替匹配|两边的任意一项ab(c|d)匹配abc或abd

特定字符	
[[:space:]]	空格
[[:digit:]]	[0-9]
[[:lower:]]	[a-z]
[[:upper:]]	[A-Z]
[[:alpha:]]	[a-Z]
#1.过滤以m开头的行
[root@manager grep]# grep "^m" test.txt

#2.排除空行,并打印行号
[root@manager grep]# grep -nv "^$" test.txt

#3.匹配任意一个字符,不包括空行
[root@manager grep]# grep  "." test.txt

#4.匹配所有内容
[root@manager grep]# grep  ".*" test.txt

#6.匹配以点结尾的
[root@manager grep]# grep  "\.$" test.txt

#7.匹配有a或b或c的行
[root@manager grep]# grep  "[a-c]" test.txt

#8.匹配数字所在的行
[root@manager grep]# egrep  "[0-9]" test.txt

#9.匹配所有小写字母
[root@manager grep]# egrep  "[a-z]" test.txt


#10.匹配572891887的qq号码
[root@manager grep]# egrep  "\<[0-9]{9}\>" test.txt


#11.匹配572891888887的qq号码
[root@manager grep]# egrep  "[0-9]{12}" test.txt

#12.匹配包含5个8的行
[root@manager grep]# egrep  "[8]{5}" test.txt

需求1:使用grep正则方式方式,提取eth0的IP地址。

10.0.0.61    
	第一列 10  192 172     至少2位数字,最多3位数字
	第二列     至少1位 最多三位
ifconfig eth0 | grep "^.*inet " | egrep -o "[0-9]{2,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
ifconfig eth0 | grep "^.*inet " | egrep -o "[[:digit:]]{2,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}"

需求2:使用grep正则表达式方式,排除nginx日志文件的空行和#号开头的行。

[root@manager grep]# egrep -v  "(^#|^$|^[[:space:]]+#)" nginx.conf

需求3:使用grep正则表达式方式,匹配nginx日志中的http1.0 和http1.1 http2.1 http2.0 http3.0

[root@manager grep]# egrep -o "HTTP/(1|2|3)\.(0|1)" access_log_grep

需求5:使用grep正则表达式方式,匹配133、152、166、135开头的手机号码。

手机号11位   3 固定   8位不固定
^(133|152|166|135)[0-9]{8}$
[root@manager grep]# cat grep_phone.sh 
#!/bin/bash 

read -p "请输入你要验证的手机号: " Action

#1.确保输入的是整数
if [[ $Action =~ [0-9]+$ ]];then
	#2.然后判断输入的是不是133 152 166 开头的 11 位数
	if [[ $Action =~ ^(133|152|166|135)[0-9]{8}$ ]];then
		echo "你输入的手机号 $Action 合法"
	else
		if [ ${#Action} -gt 11 ];then
			echo "你输入的手机号 长度超过 11位数...."
		elif [ ${#Action} -lt 11 ];then
			echo "你输入的手机号 长度小于 11位数...."
		else
			echo "你的手机号没有备案"
			exit
		fi
	fi
else
	echo "你输入的 $Action 手机号错误..."
	exit
fi

需求4:使用grep正则表达式方式,匹配zabbix_agentd.conf配置文件中所有已启用的配置。

[root@manager grep]# egrep -v  "^#|^$" zabbix_agentd.conf  
[root@manager grep]# grep '^[a-Z]' zabbix_agentd.conf 

需求7:使用grep正则表达式方式,匹配qq 163 sina的email地址。

[root@manager grep]# cat grep_email.sh 
#!/bin/bash

read -p "请输入你要验证的email Allow [ qq | 163 | sina ]: " Action

if [[ $Action =~ ^([a-z]|[A-Z]|[0-9])+@(163|qq|sina)\..+$ ]];then
	echo "Email $Action 验证成功"
else
	echo "Email $Action 验证失败"
fi

需求8:使用grep正则表达式方式,匹配合法的email地址。

[root@manager grep]# cat grep_email_2.sh 
#!/bin/bash

read -p "请输入你要验证的email Allow [ qq | 163 | sina ]: " Action
if [[ $Action =~ ^([a-z]|[A-Z]|[0-9])+@([a-Z]|[0-9])+\..+$ ]];then
	echo "Email $Action 验证成功"
else
	echo "Email $Action 验证失败"
fi

需求9:使用grep正则表达式方式,匹配a b c 三类私网IP地址。

10.0.0.0     ~ 	10.255.255.255 
172.16.1.0   ~ 	172.16.31.254
192.168.1.0  ~ 	192.168.255.255 

[root@manager grep]# cat grep_ip.sh 
#!/bin/bas

read -p "请输入需要校验的IP地址: " Action
if [[ $Action =~ ^(10)\.([0-9]|[1][0-9]{0,2}|[2][0-9]|[2][0-4][0-9]|[2][0-5][0-5]|[3-9][0-9])\.([0]|[1][0-9]{0,2}|[2][0-9]|[2][0-4][0-9]|[2][0-5][0-5]|[3-9][0-9])\.([0]|[1][0-9]{0,2}|[2][0-9]|[2][0-4][0-9]|[2][0-5][0-5]|[3-9][0-9])$ ]];then
	echo " $Action 属于A类地址"

elif [[ $Action =~ ^(172)\.([1][6-9]|[2][0-9]|[3][0-1])\.([0]|[1][0-9]{0,2}|[2][0-9]|[2][0-4][0-9]|[2][0-5][0-5]|[3-9][0-9])\.([0]|[1][0-9]{0,2}|[2][0-9]|[2][0-4][0-9]|[2][0-5][0-5]|[3-9][0-9])$ ]];then
	echo "$Action 属于B类地址"

elif [[ $Action =~ ^(192)\.(168)\.([0]|[1][0-9]{0,2}|[2][0-9]|[2][0-4][0-9]|[2][0-5][0-5]|[3-9][0-9])\.([0]|[1][0-9]{0,2}|[2][0-9]|[2][0-4][0-9]|[2][0-5][0-5]|[3-9][0-9])$ ]];then
	echo "$Action 属于C类地址"

else
	echo "$Action 不属于地址"
fi

需求10:取出身份证,匹配是哪个省,是什么出生,是男还是女,是第几个出生的。

身份证位数: 18    
最后一位x:  0   
年龄:		 从第7位开始到12位
倒数第二位: 奇数为男 偶数为女
最后四位:	 代表是本省第多少个出生。

甘肃:	 620
江西:	 360
河北: 	 130
山东:	 370
湖北:   420
上海:	 310
北京:	 110
新疆:	 650

	1.判断输入输入的是否是纯数字
		1.1 判断变量传进来的是否足够18位
		1.2 判断开头前三位 符合哪个地区
		1.3 输出内容--》函数 (变量值进行切片)
[root@manager grep]# cat sfz.sh
#!/bin/bash
#********************************************************************
#Author: yd
#QQ: 2729664582
#Date: 2019-11-07
#FileName: sfz.sh
#URL: https://www.yangdan.com.cn
#Description: The test script
#********************************************************************
mem_option () {

cat <<-EOF

1.省份
2.出生年月日
3.性别
4.第几个出生的
5.exit

-----------------------------

EOF
}

while true
do
read -p "请输入你要查询的身份证:" Action
if [[ ! $Action =~ ^[0-9]{18}$ ]];then
    echo "请输入正确的身份证!"

else
    mem_option
    while true
    do
        sfz=$(echo ${Action:0:3})
        nl=$(echo ${Action:6:8})
        xb=$(echo ${Action:0-2:1})
        dj=$(echo ${Action:0-4:4})
        dj2=$(echo ${Action:0-4:3})

	 read -p "请选择以上菜单中你想查询的选项:" Action2
  	 case $Action2 in
   		1)
       			case $sfz in
           		130)
               			echo "河北省"
               			;;
           		140)
               			echo "山西省"
               			;;
           		370)
               			echo "山东省"
               			;;
           		430)
               			echo "湖南省"
               			;;
           		622)
               			echo "甘肃省"
               			;;
           		420)
               			echo "湖北省"
               			;;
           		110)
               			echo "北京"
               			;;
           		650)
               			echo "新疆"
               			;;
           		310)
               			echo "上海"
               			;;
           		*)
               			echo "你会查身份证吗"
       			esac
               		;;
   		2)
       			echo "$nl 出生"
       			;;
   		3)
       			if [ $[$xb%2] -eq 0 ];then
           			echo "女"
       			else
           			echo "男"
       			fi
       			;;
   		4)
       			if [[ $dj =~ ^[0-9]+$ ]];then
           			echo "是第${dj}个出生的"
      			else
           			echo "是第${dj2}个出生的"
       			fi
       			;;
   		5)
       			break
       			;;
   		*)
       			echo "USAGE: $0 [ 1 | 2 | 3 | 4 | 5 ]"
   
   	esac
done

fi

   read -p "是否要继续查询:[ yes | no ]" Action3
   case $Action3 in
       y|yes)
           continue
           ;;
       n|no)
           exit 1
           ;;
       *)
           echo "USAGE $0 [ yes | no ]"
   esac
done

sed

1.打印/etc/passwd中第20行

cat /etc/passwd |sed -n 20p

2.打印/etc/passwd中从第8行开始,到第15行结束的内容

cat /etc/passwd |sed -n '8,15p'

3.打印/etc/passwd中从第8行开始,然后+5行结束的内容

sed -n '8,+5p' /etc/passwd

4.打印/etc/passwd中开头匹配bin字符串的内容

sed -n '/^bin/p' /etc/passwd

5.打印/etc/passwd中开头为root的行开始,到开头为ftp的行结束的内容

sed -n '/^root/,/^ftp/'p /etc/passwd
~~

###6.打印/etc/passwd中第8行开始,到含有/sbin/nologin的内容的行结束内容

sed -n '8,//sbin/nilogin/p' /etc/passwd

1) passwd文件第10行后面住家“Add Line”

sed -i '10aAdd Line Behind' /etc/passwd

2)passwd文件第10行到第20行,没一行后面都追加 "Test Line"

sed -i '10,20a Test Line Behind' /etc/passwd

3)passwd文件匹配到/bin/bash的行后面追加 "Insert Line"

sed -i '//bin/bash/a Insert Line For /bin/bash Behind' /etc/passwd

4)passwd文件匹配到以bin开头的行,在匹配的行前住家 "Add Line Before"

sed -i '/^bin/i Add Line Before' /etc/passwd

5)passwd文件每一行前面都追加 “Insert Line Before”

sed -i 'a Insert Line Before Every Line' /etc/passwd

6)将/etc/fstab文件的内容追加到passwd文件的第10行后面

sed -i '10r /etc/fstab' /etc/passwd

7)将/etc/inittab文件内容追加到passwd文件匹配/bin/sync行的后面

sed -i '//bin/sync/r /etc/inittab' /etc/passwd

8)将/etc/hosts文件内容追加到passwd文件中10行的后面

sed -i '10r /etc/hosts' /etc/passwd

9)将passwd文件匹配到/bin/bash的行追加到/tmp/sed.txt文件中

sed -i '//bin/bash/w /tmp/sed.txt' /etc/passwd

10)将passwd文件丛第10行开始,到匹配到nfsnobody开头的所有行内容追加到/tmp/sed-1.txt

sed -i '10,/^nfsnobody/w /tmp/sed-1.txt' /etc/passwd


###1.sed基本概述

3.sed基础语法
第一种形式:stdout | sed [option] "pattern command"
第二种形式: sed [option] "pattern command" file


###2.sed常用选项	-i -r

0.sed相关示例文件

[root@manager opt]# cat file.txt
I love shell
I love SHELL
This is test file

1.sed-n、-e选项示例

取消默认输出

[root@manager opt]# sed -n '/shell/p' file.txt
I love shell

编辑多项

[root@manager opt]# sed -n -e '/shell/p' -e '/SHELL/p' file.txt
I love shell
I love SHELL

2.sed -f 选项示例

将pattern写入文件中

[root@manager opt]# cat edit.sed
/shell/p
[root@manager opt]# sed -n -f edit.sed file.txt

3.sed -r 选项示例

[root@manager opt]# sed -n '/shell|SHELL/p' file.txt

扩展正则表达式

[root@manager opt]# sed -rn '/shell|SHELL/p' file.txt
I love shell
I love SHELL

4.sed -i 选项

[root@manager sed]# sed -in '/shell/d' file.txt


###3.sed pattern

sed -n '10p' passwd
sed -n '10,20p' passwd
sed -n '1,+5p' passwd
sed -n '/^root/p' passwd
sed -n '/root/,/ftp/p' passwd
sed -n '/[mysql.*/,/[mysqld_safe]/p' /etc/my.cnf|grep -v "^[.*"
sed -n '2,//bin/sync/p' passwd

1) 打印/etc/passwd中第20行

sed -n '20p' /etc/passwd

2)打印/etc/passwd中从第8行开始,到第15行结束的内容

sed -n '8,15p' /etc/passwd

3)打印/etc/passwd中从第8行开始,然后+5行结束的内容

sed -n '8,+5p' /etc/passwd

4)打印/etc/passwd中开头匹配bin字符串的内容

sed -n '/^bin/p' /etc/passwd

5)打印/etc/passwd中开头为root的行开始,到开头为ftp的行结束的内容

sed -n '/^root/,/^ftp/p' /etc/passwd

6)打印/etc/passwd中第8行开始,到含有/sbin/nologin的内容的行结束内容

sed -n '8,/\/sbin\/nologin/p' /etc/passwd

###4.sed追加命令

[root@manager sed]# sed -i '/^root/i server {\n\tlisten 80;\n\tserver_name oldxu.com;\n\tindex index.html;\n\troot /code;\n}' passwd
server {
listen 80;
server_name oldxu.com;
index index.html;
root /code;
}


###sed练习

1) passwd文件第10行后面追加“Add Line”

sed -i '10a "Add Line"' passwd

2)passwd文件第10行到第20行,没一行后面都追加 "Test Line"

sed -i '10,20a "Test Line"' passwd

3)passwd文件匹配到/bin/bash的行后面追加 "Insert Line"

sed -i '/\/bin\/bash/a "Insert Line"' passwd

4)passwd文件匹配到以bin开头的行,在匹配的行前追加 "Add Line Before"

sed -i '/^bin/i "Add Line Before"' passwd

5)passwd文件每一行前面都追加 "Insert Line Before"

sed -i 'i "Insert Line Before"' passwd

6)将/etc/fstab文件的内容追加到passwd文件的第10行后面

sed -i '10r /etc/fstab' passwd

7)将/etc/inittab文件内容追加到passwd文件匹配/bin/sync行的后面

sed -i '/\/bin\/sync/r /etc/inittab' passwd

8)将/etc/hosts文件内容追加到passwd文件中10行的后面

sed -i '10r /etc/hosts' passwd

9)将passwd文件匹配到/bin/bash的行追加到/tmp/sed.txt文件中

sed -i '/\/bin\/bash/w /tmp/sed.txt' passwd

10)将passwd文件丛第10行开始,到匹配到nfsnobody开头的所有行内容追加到/tmp/sed-1.txt

sed -i '10,/^nfsnobody/w /tmp/sed-1.txt' passwd

###5.sed删除命令

1)删除passwd中的第15行

sed -i '15d' passwd

2)删除passwd中的第8行到第14行的所有内容

sed -i '8,14d' passwd

3)删除passwd中以/sbin/nologin结尾的行

sed -i '/\/sbin\/nologin$/d' passwd

4)删除passwd中以bin开头的行,到以ntp开头的行的所有内容

sed -i '/^bin/,/^ntp/d' passwd

5)删除passwd中第3行到以ftp开头的所有行内容

sed '3,/^ftp/d' passwd

6)典型需求:删除Nginx配置文件中所有的注释以及空行

sed -ri '/^#|^$| #/d' nginx.conf

###6.sed修改命令	s///g   <--替换    c  修改

sed '/^SELINUX=/c SELINUX=disabled'

1.修改passwd文件第1行中第一个root为ROOT

sed -i  '1s/root/ROOT/' passwd

2.修改passwd文件中第5行到第10行中所有的/sbin/nologin为/bin/bash

sed -i '5,10s/\/sbin\/nologin/\/bin\/bash/' passwd
sed -i '5,10s#/sbin/nologin#/bin/bash#' passwd

3.修改passwd文件中匹配到/sbin/nologin的行,将匹配到行中的login为该大写的LOGIN

sed -i '/\/sbin\/nologin/s#login#LOGIN#g' passwd
sed -i '/\/sbin\/nologin/s/login/LOGIN#g' passwd

4.修改passwd文件中从匹配到以root开头的行,到匹配到以bin开头行,修改bin为BIN

sed -i '/^root/,/^bin/s/bin/BIN/g' passwd

5.修改SELINUX=enforcing修改为SELINUX=disabled。(可以使用c替换方式)

sed -i '/^SELINUX=/c SELINUX=disabled' selinux

6.将nginx.conf配置文件添加注释。 ^ $

sed -i 's/^/# /' nginx.conf

7.使用sed提取eth0网卡的IP地址

ifconfig eth0 | sed -rn '2s/^.*et //p' | sed -rn 's/ ne.*//p' 
ifconfig eth0 |sed -nr '2s/(^.*et) (.*) (net.*)/\2/p'

##AWK
###1.Awk基础介绍

2.awk语法格式
第一种形式:awk 'BEGIN{} pattern {commands} END {}' file_name
第二种形式:standard output | awk BEGIN{} pattern {commands} END {}
第三种形式:awk [options] -f awk-script-file filenames


###2.Awk工作原理

awk -F: '{print $1,$3}' /etc/passwd

1.awk将文件中的每一行作为输入, 并将每一行赋给内部变量$0, 以换行符结束
2.awk开始进行字段分解,每个字段存储在已编号的变量中,从$1开始[默认空格分割]
3.awk默认字段分隔符是由内部FS变量来确定, 可以使用-F修订
4.awk行处理时使用了print函数打印分割后的字段
5.awk在打印后的字段加上空格,因为$1,$3 之间有一个逗号。逗号被映射至OFS内部变量中,称为输出字段分隔符, OFS默认为空格.
6.awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕.


###3.Awk内部变量

$0 #将读入进来的一行数据存储至$0中,读入进来默认按行为分割由RS变量控制
$1 #经过FS变量字段分割后,将一行内容拆分成几段,分别赋值给$1 $2 $3.....
NF #统计每一行由FS分割之后多少列,多少个字段
NR #给每一行载入进来的内容,都添加一个编号
FS #指定字段分隔符,默认空格为分割
RS #指定读入进来的内容分隔符,默认按照 \n 换行符
OFS #输出字段分割符,默认是空格为分割
ORS #输出行分割符,默认是换行
print #打印


###4.Awk格式输出

格式符 含义
%s 打印字符串
%d 打印十进制数
%f 打印一个浮点数
%x 打印十六进制数
%o 打印八进制数

修饰符 含义

  • 左对齐
  • 右对齐

[root@manager awk]# awk '
BEGIN {
printf "%-20s%-20s%-20s%-20s\n",
"Name","shuxue","yuwen","yinx"
}
{
printf "%-20s%-20s%-20s%-20s\n", $1,$2,$3,$4
}' file3.txt

Name shuxue yuwen yinx
Oldxu 20 30 40
oldqiang 10 5 2
oldguo 1 1 1
oldgao 1 2 3
oldboy 10 2 0


###5.Awk模式匹配

1.正则匹配
2.运算符 < > +-/*
3.与或非

符号 含义
< 小于

  大于

<= 小于等于

= 大于等于
== 等于
!= 不等于
~ 匹配正则表达式
!~ 不匹配正则表达式

1、以:为分隔符,匹配/etc/passwd文件中第3个字段小于50的所有行信息

awk 'BEGIN{FS=":"}$3<50{print $0}' passwd

2、以:为分隔符,匹配/etc/passwd文件中第3个字段大于50的所有行信息

awk 'BEGIN{FS=":"}$3>50{print $0}' passwd

3、以:为分隔符,匹配/etc/passwd文件中第7个字段为/bin/bash的所有行信息

awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' passwd

4、以:为分隔符,匹配/etc/passwd文件中第7个字段不为/bin/bash的所有行信息

awk 'BEGIN{FS=":"}$7!="/bin/bash"{print $0}' passwd

5、以:为分隔符,匹配/etc/passwd文件中第3个字段包含3个数字以上的所有行信息

awk 'BEGIN{FS=":"}$3 ~ /[0-9]{3,}/{print $0}' passwd

布尔运算符匹配示例
符号 含义
|| 或
&& 与
! 非

1、以:为分隔符,匹配passwd文件中包含ftp或mail的所有行信息。

awk 'BEGIN{FS=":"}$1"ftp" || $1"mail" {print $0}' passwd

2、以:为分隔符,匹配passwd文件中第3个字段小于50并且第4个字段大于50的所有行信息。

awk 'BEGIN{FS=":"}$3<50 && $4>50{print $0}' passwd

3.匹配没有/sbin/nologin 的行。

awk 'BEGIN{FS=":"} $0 !~ //sbin/nologin/{print $0}' passwd
awk 'BEGIN{FS=":"} $7 != "/sbin/nologin"' passwd

awk的 + - * / % 支持小数
运算符 含义
+ 加
- 减
* 乘
/ 除
% 余

[root@manager awk]# cat student.txt
oldxu 80 90 96 98
oldqiang 93 98 92 91
oldguo 78 76 87 92
oldli 86 89 68 92
oldgao 85 95 75 90

1.找出/etc/passwd文件中uid为0的。

awk 'BEGIN{FS=":"} $3==0' passwd

2.找出/etc/passwd文件中uid小于10的。

awk 'BEGIN{FS=":"} $3<10' passwd

3.找出/etc/passwd文件中uid 小于50,且bash为/bin/bash 的行

awk 'BEGIN{FS=":"} $3<50 && /\/bin\/bash$/' passwd
awk 'BEGIN{FS=":"} $3<50 && $7 == "/bin/bash"' passwd

4.匹配用户名为root并且打印uid小于15的行

awk 'BEGIN{FS=":"} $3<15 && $1=="root"' passwd

5.匹配用户名为root或uid大于5000

awk 'BEGIN{FS=":"} $3>5000 || $1=="root"' passwd

6.匹配uid为3位及以上的行

awk 'BEGIN{FS=":"} $3 ~ /[0-9]{3,}/' passwd

7.匹配到 /sbin/nologin 的行

awk '$0 ~ /\/sbin\/nologin/' passwd
awk 'BEGIN{FS=":"} $7 ~ "/sbin/nologin" passwd
awk 'BEGIN{FS=":"} $7 == "/sbin/nologin" passwd

8.磁盘使用率大于多少则,则打印可用的值。

df  |awk 'NR==2 { if ($4 < 35092400) {print $4} }

9.正则匹配nginx开头的行

awk '!/^#|^$|^ +#/' /etc/nginx/nginx.conf

###6.Awk条件判断

if语句格式: { if(表达式){语句;语句;... } }

1.以:为分隔符,打印当前管理员用户名称

awk 'BEGIN{FS=":"} { if($3==0) { print $1,"是管理员"} }' /etc/passwd

2.以:为分隔符,统计系统用户数量

awk 'BEGIN{FS=":"}  { if($3<1000) { i++ }} END { print i,"系统用户" }' /etc/passwd

3.以:为分隔符,统计普通用户数量

awk 'BEGIN{FS=":"} { if ($3>=1000) { i++ } } END { print i,"个普通用 户"} /etc/passwd

4.以:为分隔符,只打印/etc/passwd中第3个字段的数值在50-100范围内的行信息

awk 'BEGIN{FS=":"} $3>=50 && $3<100 {print $0}' /etc/passwd

###if...else 语句格式: {if(表达式){语句;语句;... }else{语句;语句;...}}
统计当前的超级管理员有几个   统计当前的普通用户有多少   统计当前的系统用户有多少个

awk 'BEGIN {FS=":"} {if($30){print $1} else {print $7}}' /etc/passwd
awk 'BEGIN {FS=":"} {if($3
0) {count++} else{i++} }' /etc/passwd
awk 'BEGIN {FS=":"} {if($3==0){count++} else{i++}} END{print " 管理员个数: "count ; print " 系统用户数: "i}' /etc/passwd


###if...else if...else 语句格式: { if(表达式 1){语句;语句;... }else if(表达式 2){语句;语句;. .. }else{语句;语句;... }}
1.使用awk if打印出当前/etc/passwd文件管理员有多少个,系统用户有多少个,普通用户有多少个

[root@manager awk]# cat awk_l.awk
BEGIN{
FS=":";OFS="\n"
}

{
if ($3==0)
{ i++ }
else if ($3>=1 && $3<=999)
{ j++ }
else
{ k++ }
}
END {
print i "个超级管理员",
j "个系统用户" ,
k "个普通用户"
}


###1.打印/etc/passwd文件中UID小于50的、或者UID大于50小于100、或者UID大于100的用户名以及UID。
UID<50    		root    	0
UID<50    		bin    		1
50<UID<100      nobody    	99
50<UID<100      dbus    	81
UID>100         systemd    	192
UID>100         chrony    	998

多分支if
[root@manager awk]# cat awk_2
BEGIN {
FS=":"
printf "%-20s%-20s%-20s\n",
"fw","user","uid"
}
{
if ($3<50)
{
printf "%-20s%-20s%-20d\n" ,
"UID<50" , $1 , $3
}
else if ($3>50 && $3<100 )
{
printf "%-20s%-20s%-20d\n" ,
"50<UID<100" ,$1 ,$3
}
else
{
printf "%-20s%-20s%-20d\n" ,
"UID>100" ,$1 ,$3
}
}
[root@manager awk]# awk -f awk_2 /etc/passwd


###2.计算下列每个同学的平均分数,并且只打印平均分数大于90的同学姓名和分数信息

[root@manager ~]# cat student.txt
oldxu 80 90 96 98
oldqiang 93 98 92 91
oldguo 78 76 87 92
oldli 86 89 68 92
oldgao 85 95 75 90

[root@manager awk]# cat awk_3
BEGIN{
printf "%-10s%-10s%-10s%-10s%-10s%-10s%-10s\n",
"Name","yuwen","shuxue","yinyu","it","Total","AVG"
}

{
total=$2+$3+$4+$5
AVG=($2+$3+$4+$5)/4
if (AVG > 90 )
{
printf "%-10s%-10d%-10d%-10d%-10d%-10d%-10.2f\n",
$1,$2,$3,$4,$5,total,AVG
}
}


###3.统计Nginx的状态,请分别打出200类 300类 400类 500类状态  出现了多少次

[root@manager awk]# cat awk_4
BEGIN {
OFS="\n"
}
{
if ($9>=200 && $9<300)
{
i++
}
else if ($9>=300 && $9<400)
{
j++
}
else if ($9>=400 && $9<500)
{
k++
}
else
{
l++
}

}
END {
print "200: " i, "300: " j, "400: " k, "500+: " l
}


###7.Awk循环语句

需求:计算1+2+3+4+...+100的和,请使用while、for两种循环方式实现

while
[root@manager awk]# cat while_awk
BEGIN {
i=1;
while (i<=100)
{
sum+=i
i++
}

print "sum: " sum

}

for----------------------------------------------------
[root@manager awk]# cat for_awk
BEGIN {
for (i=1;i<=100;i++) {
sum+=i
}
print "sum: " sum
}


###8.Awk数组

[root@manager awk]# cat array_awk_1
BEGIN {
#指定分隔符
FS=":"
}
#遍历所有的文件行
{
#设定数组,如果数组的索引相同则自增
shells[$NF]++
}
#等待行遍历完成,然后在进行循环统计
END{
#遍历数组,将数组的索引赋值给item
for ( item in shells ) { /bin/bash

	#打印数组的索引,打印数组索引对应的次数,
	print item , shells[item]
}

}
#最后就完成了统计


###1.统计访问TOP10的IP地址

[root@manager nginx]# cat ngx_ip_top_10
{
ips[$1]++
}
END{
for ( item in ips ) {
print item, ips[item]
}
}
[root@manager nginx]# awk -f ngx_ip_top_10 access.log | sort -k 2 -rn|head


###2.统计访问TOP10的IP地址,显示大于10000次的IP

[root@manager nginx]# cat ngx_ip_top_10_2
{
ips[$1]++
}
END{
for ( item in ips ) {

	if ( ips[item] > 10000) {
	    print item, ips[item]
	}
}

}
[root@manager nginx]# awk -f ngx_ip_top_10_2 access.log
58.220.223.62 12049
112.64.171.98 10856


###3.统计访问最多的10个页面($request top 10)

[root@manager nginx]# cat ngx_url_top_10
{
url[$7]++
}

END{
for ( item in url ) {
print item, url[item]
}
}
[root@manager nginx]# awk -f ngx_url_top_10 access.log |sort -k2 -nr | head


###4.统计访问最多的10个页面($request top 10),访问次数大于1000以上的页面才显示

[root@manager nginx]# cat ngx_url_top_10_2
{
url[$7]++
}

END{
for ( item in url ) {
if ( url[item] > 1000) {
print item, url[item]
}
}
}

[root@manager nginx]# awk -f ngx_url_top_10_2 access.log


###4.统计每个URL访问内容总大小($body_bytes_sent)

[root@manager nginx]# cat ngx_url_size
{
#count统计他的次数
count[$7]++

#相同的url,让他们的大小相加
url[$7]+=$10

}
END{
for (item in url) {
if (url[item]/1024/1024 > 50) {
print count[item],item, url[item]/1024/1024"Mb"
}
}
}


###5.访问状态码为404及出现的次数($status) 

[root@manager nginx]# cat ngx_code_status_count
{
code[$9]++
}
END{
for ( item in code ) {
if ( item == "404" ) {
print item, code[item]
}
}
}


{
code[$9]++
}
END{
print "404", code[404]
}


##数组

1.统计2015年11月22日,当天的PV量 (awk是无法统计pv piwiki 腾讯云分析)

[root@manager nginx]# cat ngx_pv 
	$0 ~ /22\/Nov\/2015/
[root@manager nginx]# awk -f ngx_pv access.log |wc -l
166945

2.统计2015年11月22日,一天内访问最多的10个IP

[root@manager nginx]# cat ngx_ip_top10
{
if ($0 ~ "22/Nov/2015") {
ips[$1]++
}
}
END {
for ( item in ips ) {
print item,ips[item]
}
}

3.统计2015年11月22日,访问大于1000次的IP

[root@manager nginx]# cat ngx_ip_top10
{
if ($0 ~ "22/Nov/2015") {
ips[$1]++
}
}
END {
for ( item in ips ) {
if (ips[item] > 1000) {
print item,ips[item]
}
}
}

4.统计2015年11月22日,访问最多的10个页面($request top 10)

[root@manager nginx]# cat ngx_ip_top10
{
if ($0 ~ "22/Nov/2015") {
url[$7]++
}
}
END {
for ( item in url ) {
print item,url[item]
}
}

5.统计2015年11月22日,每个URL访问内容总大小,以及每个url的访问次数($body_bytes_sent)

1.次数拿到

[root@manager nginx]# cat ngx_url_size
{
if ($0 ~ "22/Nov/2015") {
url[$7]++
size[$7]+=$10
}
}
END {
for ( item in url) {
if (size[item]/1024/1024 > 100) {
print size[item]/1024/1024"Mb" , item, url[item]
}
}
}

6.统计2015年11月22日,每个IP访问状态码出现的次数($status)

	172.16.1.1 200 10次
	172.16.1.1 304 10次

[root@manager nginx]# cat ngx_code_status
{
ips[$1 " " $9]++
}
END{
for ( item in ips ) {
print item , ips[item]
}
}

8.统计2015年11月22日,8:30-9:00访问状态码是404

[root@manager nginx]# awk '$4>="[22/Nov/2015:11:30:00" && $4<="[22/Nov/2015:11:31:00" && $9=="404"' access.log

9.统计2015年11月22日,各种状态码数量

if
array

2019-11-08 16:30:35 2 user: oldguo insert 19198 records into datebase:product table:detail, insert 13653 records successfully,failed 5545 records
2019-11-08 16:30:35 3 user: oldqiang insert 27237 records into datebase:product table:detail, insert 19115 records successfully,failed 8122 records

用户: $5
总共写入了多少条记录 $7
成功写入了多少条记录 $13
失败写入了多少条记录 $16 $(NF-1)

需求1:统计每个人分别插入了多少条records进数据库

[root@manager nginx]# cat awk_insert_1
BEGIN {
printf "%-10s%-10s\n" ,
"Name","Records"
}
{
records[$5]+=$7
}
END {
for ( item in records ) {
printf "%-10s%-10d\n" ,
item, records[item]
}
}

需求2:统计每个人分别插入成功了多少record,失败了多少record

[root@manager nginx]# cat awk_insert_2
BEGIN {
printf "%-10s%-20s%-20s\n" ,
"Name","Success Records","Failed Records"
}
{
success[$5]+=$13
failed[$5]+=$16
}
END {
for ( item in success) {
printf "%-10s%-20d%-20d\n" ,
item, success[item],failed[item]
}
}

需求3:将需求1和需求2结合起来,一起输出,输出每个人分别插入多少条数据,多少成功,多少失败,并且要格式化输出,加上标题

[root@manager nginx]# cat awk_insert_3
BEGIN {
printf "%-10s%-20s%-20s%-20s\n" ,
"Name","Success Records","Failed Records","Total Records"
}
{
total[$5]+=$7
success[$5]+=$13
failed[$5]+=$16
}
END {
for ( item in success) {
printf "%-10s%-20d%-20d%-20d\n" ,
item, success[item],failed[item],total[item]
}
}

需求4:在例子3的基础上,加上结尾,统计全部插入记录数,成功记录数,失败记录数。

[root@manager nginx]# cat awk_insert_4
BEGIN {
printf "%-10s%-20s%-20s%-20s\n" ,
"Name","Success Records","Failed Records","Total Records"
}
{
total[$5]+=$7
success[$5]+=$13
failed[$5]+=$16

total_sum+=$7
success_sum+=$13
failed_sum+=$16

}
END {
for ( item in success) {
printf "%-10s%-20d%-20d%-20d\n" ,
item, success[item],failed[item],total[item]
}
printf "%-10s%-20d%-20d%-20d\n" ,
"Total_ALl:" ,success_sum,failed_sum,total_sum
}

需求5:查找丢失数据的现象,也就是成功+失败的记录数不等于一共插入的记录数,找出这些数据并显示行号和对应行的日志信息

[root@manager nginx]# awk '{ if ($7 != $13+$16) {print $0} }' db.log.20191108

推荐阅读