shell编程
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($30) {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