shell编程从入门到高级教程

一.shell编程初识

1.1 shell能做什么

1. 自动化批量系统初始化程序 (update,软件安装,时区设置,安全策略...)
2. 自动化批量软件部署程序 (LAMP,LNMP,Tomcat,LVS,Nginx)
3. 应用管理程序 (KVM,集群管理扩容,MySQL,DELLR720批量RAID)
4. 日志分析处理程序(PV, UV, 200, !200, top 100, grep/awk)
5. 自动化备份恢复程序(MySQL完全备份/增量 + Crond)
6. 自动化管理程序(批量远程修改密码,软件升级,配置更新)
7. 自动化信息采集及监控程序(收集系统/应用状态信息,CPU,Mem,Disk,Net,TCP Status,Apache,MySQL)
8. 配合Zabbix信息采集(收集系统/应用状态信息,CPU,Mem,Disk,Net,TCP Status,Apache,MySQL)
9. 自动化扩容(增加云主机——>业务上线)zabbix监控CPU 80%+|-50%  Python API  AWS/EC2(增加/删除云主机) + Shell Script(业务上线)
10. 俄罗斯方块,打印三角形,打印圣诞树,打印五角星,运行小火车,坦克大战,排序算法实现,等众多功能的一个实现
11. Shell可以做任何事(一切取决于业务需求)

1.2 shell编程初识

shell的定义

Shell 是命令解释器
Shell 也是一种程序设计语言,它有变量,关键字,各种控制语句,有自己的语法结构,利用shell程序设计语言可以编写功能很强、代码简短的程序**

shell的分类和更改

cat /etc/shells

/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh

默认shell: bash

注意:各种脚本里凡是/bin/sh表示的是使用默认bash

查看当前使用的shell:
#echo $SEHLL

shell 的更改:
#chsh
#vim /etc/passwd

适用范围
什么时候不适合使用Shell编程:
1. 资源紧张的项目,特别是那些速度是重要因素的地方(排序,散序,等等)
2. 程序要进行很复杂的数学计算,特别是浮点计算,任意精度的计算,或者是复数计算
3. 要求交叉编译平台的可移植性(使用C或者是Java代替)
4. 需要结构化编程的复杂应用(需要变量类型检查和函数原型等等)
5. 对于影响系统全局性的关键任务应用。
6. 安全非常重要。你必须保证系统完整性和抵抗入侵,攻击和恶意破坏。
7. 项目由连串的依赖的各个部分组成。
8. 多种文件操作要求(Bash被限制成文件顺序存取,并且是以相当笨拙,效率低下的逐行的存取方式)
9. 需要良好的多维数组支持。
10. 需要类似链表或树这样的数据结构。
11. 需要产生或操作图象或图形用户界面。
12. 需要直接存取系统硬件。
13. 需要端口号或是socket I/O。
14. 需要使用可重用的函数库或接口。
15. 所有的私有的不开源的应用程序(Shell脚本的源代码是直接可读,能被所有人看到的)

如果你需要有上面的任意一种应用,请考虑其他的更强大的脚本语言――Perl,Tcl,Python,Ruby,或者可能是其他更高级的编译型语言,例如C,C++或者是Java

实例(仅展示用,后续有详细讲解)

相对于shell脚本是可以实现大多数自动化部署功能,可以快速的提升工作效率,比如如下脚本,实现众多 批量化部署

[root@master1 ~]# cat jiaoben.sh
#!/usr/bashliu () {cat <<-EOF1.关闭防火墙,一键三连,修改selinux
2.查看系统状态[磁盘大小和使用率 内存大小和使用率 cpu负载 运行时间 版本号]
3.一键配置yum源,一键三联,关闭防火墙,
4.修改主机名,配置静态IP
5.yum安装mysql-5.7
6.安装yum安装 nginx
7.安装jdk8.tomcat8版本      EOF
}one (){systemctl stop firewalld iptables -X && iptables -F && iptables -Zsystemctl disable firewalld && systemctl status firewalld sed -ri s/SELINUX=enforcing/SELINUX=disabled/g /etc/selinux/config && getenforce
}two () {cat <<-EOF
1.磁盘大小和使用率
2.内存大小和使用率
3.cpu负载
4.运行时间
5.版本号          }
EOFprintf "\e[1;31m 请选择你想使用的功能(1/2/3/4/5): \e[0m" && read ww
case $ww in1)a=`df -Th |awk '{print $1,$2,$5}'`     ##查询所有磁盘内存信息echo "磁盘大小是使用率分别为: $a";;2)b=`free -h |grep 'Mem' |awk '{print $2,$3}'`echo "内存大小和使用率分别为: $b";;3)c=`uptime |awk '{print $11,$12,$13}'`echo "cpu 负载为:  $c";;4)d=`uptime |awk '{print $3,$4}'`echo "运行时间为:  $d";;5)e=`uname -r`echo "版本号为:  $e";;*)echo "error select";;
esac
}tree () {f=`cat /etc/redhat-release  |awk '{print $4}' |awk -F'.' '{print $1}'`
if [ $f -eq 7 ];thenecho "此版本为centos $f 的版本"read -p "是否重新配置yum源 (y|n): " ynif [ "$yn" = "y" ];thenyum install -y wget ntpdate net-tools vim bash-completion ShellChecksystemctl stop firewalldiptable -X && iptable -F && iptable -Zsystemctl disable firewalldsed -ri s/SELINUX=enforcing/SELINUX=disabled/g /etc/selinux/configsetenforce 0cp /etc/yum.repos.d/* /tmp/ && rm -rf  /etc/yum.repos.d/*curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repocurl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repoyum clean all && yum makecache fastntpdate -b ntp1.aliyun.comelseecho "不需要重新配置yum源"fi
fi
}four () {cat <<-EOF
"请输入您的选项"
1.修改主机名
2.配置静态ip
EOFprintf "\e[1;31m 请选择你想使用的功能(1/2): \e[0m" && read wen
case $wen in1)read -p "请输入你的主机名" namehostnamectl set-hostname  $name &&bash;;2)cp /etc/sysconfig/network-scripts/ifcfg-ens33 /tmp/ifcfg-ens33.bakread -p "请输入你的ip的末尾" ipname
echo "TYPE=Ethernet
BOOTPROTO=static
DEFROUTE=yes
NAME=ens33
DEVICE=ens33
ONBOOT=yes
IPADDR=192.168.229.$ipname
PREFIX=24
GATEWAY=192.168.229.2
DNS1=223.5.5.5
DNS2=223.6.6.6" >/etc/sysconfig/network-scripts/ifcfg-ens33systemctl restart network;;*)echo "eroor select";;
esac}five () {if rpm -qa |grep "mysql" |egrep -v grep > /dev/nullthenecho cunzai!elseecho no !sed -ri s/SELINUX=enforcing/SELINUX=disabled/g /etc/selinux/configsystemctl stop firewalld && systemctl disable firewalldyum -y groupinstall "Development Tools"cd /usr/local/src/wget https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpmrpm -ivh mysql80-community-release-el7-1.noarch.rpmsed -ri 21s/enabled=0/enabled=1/g  /etc/yum.repos.d/mysql-community.reposed -ri 28s/enabled=1/enabled=0/g  /etc/yum.repos.d/mysql-community.repoyum -y install mysql-community-serversystemctl start mysqld && systemctl enable mysqldgrep "password" /var/log/mysqld.logfi
}six (){if rpm -qa |grep "nginx" |egrep -v grep > /dev/nullthen echo cunzai!elseecho no !yum -y install gcc gcc-c++ pcre pcre-develyum -y install   nginxfi
}liu
printf "\e[1;31m 请选择你想要实现的功能(1/2/3/4/5/6):  \e[0m" && read sbcase $sb in1)one;;2)two;;3)tree;;4)four;;5)five;;6)six;;
*)echo "eroor select"
esac

1.3 shell编程特点

bash特性

    补全历史别名快捷键前后台作业重定向管道命令排序执行;   &&    ||通配符{}      ?  *正则表达式脚本

历史命令

查看历史命令history                        /etc/profile  下的historysize 可以修改
调用历史命令上下健     !关键字   !历史命令行号      !! 执行上一条命令!$  上一条命令alt+.   esc    .   上一条命令的最后一个参数    Ctrl+r   在历史命令中查找,输入关键字调出之前的命令关键字+pgup/phdn  可以切换关键字相关的历史命令显示历史命令执行时间:
1.设置变量:HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S"
2.再次执行history查看结果 别名查看别名alias设置别名临时设置

Bash部分快捷键(常用) ,这里采用的都是Linux编辑器上的常用快捷键,有利于高效的展开工作

 Ctrl+a 切换到命令行开始(跟home一样,但是home在某些unix环境下无法使用)Ctrl+e 切换到命令行末尾Ctrl+u 清除剪切光标之前的内容Ctrl+k 清除剪切光标之后的内容ctrl+y  粘贴刚才锁删除的字符Ctrl+r   在历史命令中查找,输入关键字调出之前的命令

通配符置换

*,?,[],{}例:
字符          含义                          实例
*           匹配 0 或多个字符           a*b  a与b之间可以有任意长度的任意字符, 也可以一个也没有, 如aabcb, axyzb, a012b, ab。
?           匹配任意一个字符                 a?b  a与b之间必须也只能有一个字符, 可以是任意字符, 如aab, abb, acb, a0b。
[list]      匹配 list 中的任意单一字符    a[xyz]b   a与b之间必须也只能有一个字符, 但只能是 x 或 y 或 z, 如: axb, ayb, azb。
[!list]     匹配 除list 中的任意单一字符   a[!0-9]b  a与b之间必须也只能有一个字符, 但不能是阿拉伯数字, 如axb, aab, a-b。
[^list]     匹配 除list 中的任意单一字符   a[^0-9]b  a与b之间必须也只能有一个字符, 但不能是阿拉伯数字, 如axb, aab, a-b。
[c1-c2]     匹配 c1-c2 中的任意单一字符 如:[0-9] [a-z]  a[0-9]b  0与9之间必须也只能有一个字符 如a0b, a1b... a9b。
{string1,string2,...}   匹配 sring1 或 string2 (或更多)其一字符串  a{abc,xyz,123}b    a与b之间只能是abc或xyz或123这三个字符串之一。

1.4shell脚本规范


[root@master1 ~]#  vim helloworld.sh   ---.sh代表这个文件是个shell脚本,拓展名后缀,如果省略.sh则不易判断该文件是否为shell脚本
1. #!/usr/bin/env bash    ---shebang蛇棒, 解释器, 翻译
2. #
3. # Author: tiger
3. # Email: tigerfive@163.com
4. # Github: https://github.com/tigerfive           ---这就是注释, 你没看错
5. # Date: 2019/**/**
6.
7. printf "hello world\n"[root@master1 ~]# sh helloworld.sh      #sh命令是启动脚本
hello world
[root@master1 ~]# ./helloworld.sh      #./   也是启动sh 脚本命令第一行: “#!/usr/bin/env bash”叫做shebang, shell语法规定shell脚本文件第一行为整个文件的解释器第二行: 为“#”开头的行为注释行默认不会被程序所读取, 用来说明文件及标定所属人员使用, 也可用来解释程序第七行: 为格式化打印语句printf, printf可以把后面的“hello world”打印到指定的终端中, \n为换行符

1.5 脚本运行方式

创建bash脚本

 1.创建脚本文件指定命令解释器注释编写bash指令集合2.修改权限

bash脚本的执行

bash
#./scripts
#/shelldoc/scripts
#. ./scripts               使用当前shell执行
#source ./scripts      使用当前shell执行  比如cd /tmp会改变当前shell环境,但是其他的方式不会
#bash scripts

子shell

(cmds)   表示开启子shell# pwd/root/shell# (cd /tmp;touch test;)# ls /tmp/test/tmp/test# pwd/root/shell子shell能够继承父shell的一些属性,但是子shell不能够反过来改变父shell的属性子shell的好处之一可以将复杂的任务分成多个小任务,并行处理,加快执行速度。所有shell的父shell父进程:init    {cmds}  不开启子shell# { cd /tmp;touch test1; }# pwd/tmp

bash脚本测试

 •sh –x script这将执行该脚本并显示所有变量的值•sh –n script不执行脚本只是检查语法模式,将返回所有错误语法•sh –v script执行脚本前把脚本内容显示在屏幕上

1.6变量的类型 【要点】

变量
shell 变量? 用一个固定的字符串去表示不固定的内容
bash作为程序设计语言和其它高级语言一样也提供使用和定义变量的功能

变量分类
预定义变量、环境变量、自定义变量、位置变量

变量的类型:1. 自定义变量定义变量:        变量名=变量值 变量名必须以字母或下划线开头,区分大小写   ip1=192.168.2.115 引用变量:      $变量名 或 ${变量名}查看变量:       echo $变量名  set(所有变量:包括自定义变量和环境变量)取消变量:        unset 变量名作用范围:       仅在当前shell中有效[root@master ~]# a=8
[root@master ~]# echo $a
8
[root@master ~]# echo $a2[root@master ~]# echo ${a}2
82环境变量:shell在开始执行时已经定义好的env       查看所有环境变量set        查看所有变量环境变量拥有可继承性:export之后就拥有继承性export   导出变量(作用范围)临时生效永久生效写道4个登陆脚本中     ~/.bashrc   ~/profile                更好放在/etc/profile.d/* 下建立独立的环境变量配置文件jdk常用环境变量:USER UID HOME       HOSTNAME  PWD     PS1    PATHPATH:存储所有命令所在的路径3. 位置变量$1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}4. 预定义变量$0    脚本名$*       所有的参数$@    所有的参数$#     参数的个数$$     当前进程的PID$!     上一个后台进程的PID$?        上一个命令的返回值 0表示成功 示例1:# vim test.shecho "第2个位置参数是$2"echo "第1个位置参数是$1"echo "第4个位置参数是$4"echo "所有参数是: $*"echo "所有参数是: $@"echo "参数的个数是: $#"echo "当前进程的PID是: $$"echo '$1='$1echo '$2='$2echo '$3='$3echo '$*='$*echo '$@='$@echo '$#='$#echo '$$='$$了解$*和$@区别

变量赋值

变量的赋值方式:
1. 显式赋值变量名=变量值示例:ip1=192.168.229.61school="BeiJing 1000phone"today1=`date +%F`today2=$(date +%F)2. read 从键盘读入变量值read 变量名read -p "提示信息: "  变量名read -t 5 -p "提示信息: "  变量名read -n 2 变量名示例一:ping,采用变量写一个,判断ip地址能否ping通
[root@master ~]# cat ping2.sh
#!/bin/bash
read -p "Input IP: " ip
ping -c2 $ip &>/dev/null
if [ $? = 0 ];then                 echo "host $ip is ok"
else                                            echo "host $ip is fail"
fi      [root@master ~]# sh ping2.sh
Input IP: 192.168.229.61          #输入您需要ping的IP地址
host 192.168.229.61 is ok        #显示ok则以完成测试定义或引用变量时注意事项:
" "       弱引用
' '       强引用
[root@master ~]# school=1000phone
[root@master ~]# echo   "${school} is good"
1000phone is good
[root@master ~]# echo '${school} is good'
${school} is good` `      命令替换 等价于 $()   反引号中的shell命令会被先执行
[root@master ~]# touch `date +%F`_file1.txt
[root@master ~]# touch $(date +%F)_file2.txt [root@master ~]# disk_free3="df -Ph |grep '/$' |awk '{print $4}'"    错误
[root@master ~]# disk_free4=$(df -Ph |grep '/$' |awk '{print $4}')
[root@master ~]# disk_free5=`df -Ph |grep '/$' |awk '{print $4}'`

变量运算

1. 整数运算方法一:exprexpr 1 + 2expr $num1 + $num2             +  -  \*  /  %方法二:$(())echo $(($num1+$num2))       +  -  *  /   %echo $((num1+num2))echo $((5-3*2))   echo $(((5-3)*2))echo $((2**3))sum=$((1+2)); echo $sum方法三:$[]echo $[5+2]                              +  -  *  /  %echo $[5**2]方法四:letlet sum=2+3; echo $sumlet i++; echo $i2. 小数运算echo "2*4" |bcecho "2^4" |bcecho "scale=2;6/4" |bcawk 'BEGIN{print 1/2}'echo "print 5.0/2" |python2.浮点运算:
bash本身不能做小数计算:需要bc命令转换
#echo "2*4" | bc
#echo "2^4" | bc
#echo "scale=2;6/4" | bcscale: 精度
#awk 'BEGIN{print 1/2}'
#echo "print 5.0/2" | python计算我的信用卡一个月的利息,假设我欠10000块钱#!/bin/bash m=$( echo 5/10000|bc -l)#因为shell不支持小数,所以要用bc转换一下sum=10000for i in {1..365} do    sum=$(echo $sum+$sum*$m | bc )echo $sum doneecho $sum3.变量引用
转义:\为了显示元字符,需要引用。当一个字符被引用时,其特殊含义被禁止把有意义的变的没意义,把没意义的变的有意义\n  \t  \r# echo -e '5\\n6\n7'5\n67# yum install httpd mysql  -y# yum groupinstall  KDE\ Plasma\ Workspaces完全引用:''    //强引  硬引
部分引用:""   //弱引  软引
#ls -lh --sort=size | tac
#echo hello;world
#echo you own $1250例子:  从这个例子举出的是,弱引和强引的区别,强引打印原文,弱引打印变量
[root@master ~]# num=15
[root@master ~]# echo 1793班有$num个女生
1793班有15个女生
[root@master ~]# echo "1903班有$num个女生"
1903班有15个女生
[root@master ~]# echo '1903班有$num个女生'
1903班有$num个女生读取用户标准输入:read    【重点参数】
read:功能就是读取键盘输入的值,并赋给变量
#read  -t  5  var
#read -p "提示信息" var示例:
#!/bin/bash
read system  setting network
echo "This is computer function $system"
echo "This is computer function $setting"
echo "This is computer function $network"示例:2
暂停用户输入:
[root@master ~]# shiyan.sh
read  -p "如果你同意以上协议请按回车继续! "  answer
echo 这是下面的操作了
sleep 1
echo 这是下面的操作了
sleep 1
echo 这是下面的操作了
sleep 1
echo 这是下面的操作了
sleep 1
echo 这是下面的操作了[root@master ~]# sh shiyan.sh
如果你同意以上协议请按回车继续!
这是下面的操作了
这是下面的操作了
这是下面的操作了
这是下面的操作了
这是下面的操作了示例3:
[root@master ~]# vim shiyan2.sh
#!/bin/bash
read  -p "Do you want to continue [Y/N]? "  answer
case $answer in
Y|y) echo "fine ,continue";;
N|n) echo "ok,good bye";;
*) echo "error choice";;
esac
exit 0[root@master ~]# sh shiyan2.sh
Do you want to continue [Y/N]? Y
fine ,continue
[root@master ~]# sh shiyan2.sh
Do you want to continue [Y/N]? N
ok,good bye-s 选项能够使read命令中输入的数据不显示在监视器上(实际上,数据是显示的,只是read命令将文本颜色设置成与背景相同的颜色
#!/bin/bash
read  -s  -p "Enter your password: " pass
echo "your password is $pass"
exit 0取消屏幕回显:
stty -echo
stty echo变量长度
[root@master ~]# a=123
[root@master ~]# echo ${#a}        # 表示$var的长度
3变量嵌套
[root@master ~]# a=8
[root@master ~]# name8=9
[root@master ~]# eval echo \$name$a
9~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·~·~~~~~~~~~~~~~~~~~~~~~~~~~~~~示例4:  【这个脚本参数内容需要熟记,后续经常用到的】
[root@master ~]# vim shiyan4.sh    #操作选项脚本,简单实现
#!/bin/bash
echo -e '1.配置yum客户端'
echo 2.添加A记录
echo 3.一键安装lamp环境
echo '4.一键配置静态IP'
read -p "请选择你想使用的功能(1/2/3/4):" numcon_ip(){echo 这是配置IP地址的小工具
}case $num in1):;;2):;;3):;;4)con_ip;;*):;;
esac[root@master ~]# sh shiyan4.sh
1.配置yum客户端
2.添加A记录
3.一键安装lamp环境
4.一键配置静态IP
请选择你想使用的功能(1/2/3/4):1
[root@master ~]# sh shiyan4.sh
1.配置yum客户端
2.添加A记录
3.一键安装lamp环境
4.一键配置静态IP
请选择你想使用的功能(1/2/3/4):2
[root@master ~]# 

1.7 i++和++i

++在前就是先算++
++在后就是后算++

i++ 和 ++i (了解)对变量的值的影响:
[root@master ~]# i=1
[root@master ~]# let i++
[root@master ~]# echo $i
2
[root@master ~]# j=1
[root@master ~]# let ++j
[root@master ~]# echo $j
2对表达式的值的影响:
[root@master ~]# unset i
[root@master ~]# unset j
[root@master ~]# i=1
[root@master ~]# j=1
[root@master ~]# let x=i++         先赋值,再运算
[root@master ~]# let y=++j         先运算,再赋值
[root@master ~]# echo $i
2
[root@master ~]# echo $j
2
[root@master ~]# echo $x
1
[root@master ~]# echo $y
2

二.shell变成

1.shell条件测试

测试
test 条件
条件为真返回 0,条件为假返回 1    【这个必须要记住,0为真,1为假】[ 条件 ]test能够理解3中类型的表达式
1.文件测试
2.字符串比较
3.数字比较字符串-n STRINGthe length of STRING is nonzero-z STRINGthe length of STRING is zeroSTRING1 = STRING2the strings are equalSTRING1 != STRING2the strings are not equal数字             【重点参数】
eq 等于equal         ne 不等于
ge 大于等于           gt 大于
le 小于等于           lt 小于文件
-f 存在且是普通文件
-d 存在且是目录
-l 存在且是符号链接
-b 块设备
-c 字符设备
-e 文件存在
-r
-w
-x
file1 -nt file2    file1 比 file2 新(修改时间)
file1 -ot file2    file1 比 file2 旧(修改时间)=========格式1: test 条件表达式
格式2: [ 条件表达式 ]
格式3: [[ 条件表达式 ]]man test===文件测试 [ 操作符 文件或目录 ]
[root@master ~]# test -d /home
[root@master ~]# echo $?
0      #零说明改目录存在
[root@master ~]# test -d /home11111
[root@master ~]# echo $?
1      #一说明改目录存在
[root@master ~]# [ -d /home ][ -e dir|file ]
[ -d dir ]
[ -f file ]     是否存在,而且是文件
[ -r file ]     当前用户对该文件是否有读权限
[ -x file ]
[ -w file ]
[ -L file ]
[root@master ~]# [ ! -d /ccc ]  && mkdir /ccc
[root@master ~]# [ -d /ccc ]  || mkdir /ccc===数值比较 [ 整数1 操作符 整数2 ]   【重点】
[ 1 -gt 10 ]        大于
[ 1 -lt 10 ]        小于
[ 1 -eq 10 ]        等于
[ 1 -ne 10 ]        不等于
[ 1 -ge 10 ]        大于等于
[ 1 -le 10 ]        小于等于===字符串比较
提示:使用双引号
[root@master ~]# [ $(id -u) -eq 0 ] || echo "必须是超级用户才能执行"
[root@master ~]# [ "$USER" = "root" ];echo $?
0
[root@master ~]# [ "$USER" = "alice" ];echo $?
1
[root@master ~]# [ "$USER" != "alice" ];echo $?
0
[root@master ~]# [ 1 -lt 2 -a 5 -gt 10 ];echo $?
1
[root@master ~]# [ 1 -lt 2 -o 5 -gt 10 ];echo $?
0
[root@master ~]# [[ 1 -lt 2 && 5 -gt 10 ]];echo $?
1
[root@master ~]# [[ 1 -lt 2 || 5 -gt 10 ]];echo $?
0
[root@master ~]# [[ "$USER" =~ ^r ]];echo $?          # 使用正则  正则只能使用[[]]
0==C语言风格的数值比较
[root@master ~]# ((1<2));echo $?
0
[root@master ~]# ((1==2));echo $?
1
[root@master ~]# ((1>2));echo $?
1
[root@master ~]# ((1>=2));echo $?
1
[root@master ~]# ((1<=2));echo $?
0
[root@master ~]# ((1!=2));echo $?
0
[root@master ~]# ((`id -u`>0));echo $?
1
[root@master ~]# (($UID==0));echo $?
0示例1:
判断变量是不是数字:
[root@master ~]# num1=123
[root@master ~]# num2=sss1414ss
[root@master ~]# [[ "$num1" =~ ^[0-9]+$ ]];echo $?     #判断是数字,则成功得出值为0
0
[root@master ~]# [[ "$num1" =~ ^[0-9]+$ ]];echo $?     #判断结果为英文加数字。得出结果是错误的
1示例2:判断是否输入的是一个数值
[root@master ~]# vim shiyan5.sh
#!/bin/bash
#判断用户输入的是否是数字
read -p "请输入一个数值: " num           #设立条件
while :
do                                                                               if [[ $num =~ ^[0-9]+$ ]];then       #if语句进行判断               break                                                        else                                                       read -p "不是数字,请重新输入数值: " num    #判断失败则需要冲i重新输入 fi
done
echo "你输入的数字是: $num"      #判断成功
[root@master ~]# sh shiyan5.sh    #执行脚本
请输入一个数值: 123               #输入数字匹配成功
你输入的数字是: 123
[root@master ~]# sh shiyan5.sh
请输入一个数值: abc         #输入的不是数值,则需要重新输入
不是数字,请重新输入数值: 123
你输入的数字是: 123示例3:判断限定用户输入八位数的数值
[root@master ~]# vim shiyan6.sh
#!/usr/bin/env bash
read -p "其请输入一个8位数数字: " NUM
if [ ${#NUM} -eq 8 ];thenecho "你输入的是一个8位数"elseecho "你输入的不是8位数字:拜拜嘞,您!"exit
fi
if [[ ! $NUM =~ ^[0-9]+$ ]];thenecho "你输入的不是8位数字!"else echo "你输入的是8位数字: good"
fi[root@master ~]# sh shiyan6.sh
其请输入一个8位数数字: 123455
你输入的不是8位数字:拜拜嘞,您!
[root@master ~]# sh shiyan6.sh
其请输入一个8位数数字: 14725836
你输入的是一个8位数
你输入的是8位数字: good需要注意:shell是一门很强大的编程语言,所有的判断条件都可以灵活应用,采用if语句判断发,条件筛选法,以及后续所用到的函数结合法,精通shell可以高效率的完成多数机器自动化部署

2. shell分支if语句

流程控制:if
•在一个shell脚本中的命令执行顺序称作脚本的流。大多数脚本会根据一个或多个条件来改变它们的流。
•流控制命令:能让脚本的流根据条件而改变的命令称为条件流控制命令
•exit语句:退出程序的执行,并返回一个返回码,返回码为0正常退出,非0为非正常退出,例如:
•exit 0if语句架构框架:   【必会技能】
单分支结构
if 条件测试
then 命令序列
fi双分支结构
if 条件测试
then 命令序列
else 命令序列
fi多分支结构
if 条件测试1
then 命令序列[elif 条件测试2
then 命令序列elif 条件测试3
then 命令序列]...else 命令序列
fi示例1:
read -p "确认开始安装KVM [y]: " kvm_install
if [ ! "${kvm_install}" = "y" ];thenecho -e "$red_col输入不正确! $reset_col"exit
fi当然你也可以这样写,但是这样写不太好看:
if list1;then list2;elif list3;then list4;else list5;fi;示例2:  编写脚本输出一个数值
[root@master ~]# cat shiyan7.sh
#!/usr/bin/env bash
if [ "$1" = "hello" ]; then      #添加hello值echo "Hello! How are you ?"
elif [ "$1" = "" ]; then        #添加空 值echo "You MUST input parameters"
elseecho "The only accept parameter is hello"
fi[root@master ~]# sh shiyan7.sh  hello     #输入变量参数hello数值 则会打印出如下
Hello! How are you ?
[root@master ~]# sh shiyan7.sh      #后面未输入参数,则代表输入的是空,则会输出如下内容
You MUST input parameters示例3:  写出一个输入不同脚本得出不同输入结果的sh文件
[root@master ~]# vim shiyan8.sh
#/usr/bash
echo "Press y to continue"
read yn
if [ "$yn" = "y" ]; then
echo "script is running..."
else
echo "STOP!"
fi
[root@master ~]# sh shiyan8.sh
Press y to continue
y      #输入y 得出以下值
script is running...
[root@master ~]# sh shiyan8.sh
Press y to continue
yn    #输入yn得出以下值
STOP!多个条件联合
逻辑与if [ $condition1 ] && [ $condition2 ]if [ $condition -a $condition2 ]if [[ $condition1 && $condition2 ]]逻辑或if [ $condition1 ] || [ $condition2 ]if [ $condition -o $condition2 ]if [[ $condition1 || $condition2 ]]case  命令  【这个也是一个重点模式,必须记住】case 语句是 shell 中流控制的第二种方式,语法如下:case 变量 in模式1)命令序列1;;模式2)命令序列2;;模式3)命令序列3;;*)无匹配后命令序列;;
esac    命令;;表明流应该跳转到case语句的最后,类似C语言中的break指令。示例4: 写出一个多项选项的操作脚本命令,比如abcd四个选项项目
[root@master ~]# cat shiyan9.sh
#!/usr/bin/env bash
cat <<-EOF
+-------------------------------------------------------------------------+
|                       System_tools V1.0                                 |
+-------------------------------------------------------------------------+
|               a. Stop And Disabled Firewalld.                           |
|               b. Disabled SELinux Secure System.                        |
|               c. Install Apache Service.                                |
|               d. Quit                                                   |
+-------------------------------------------------------------------------+
EOF
printf "\e[1;31m Please input your select:  \e[0m" && read var
case "$var" in"a")systemctl stop firewalld && systemctl disable firewalld;;"b")setenforce 0 && sed -ri s/SELINUX=enforcing/SELINUX=disabled/g /etc/selinux/config;;"c")yum -y install httpd httpd-toolsecho "httpd is installd";;"d")exit;;*)printf "请按照上方提供的选项输入!!!\n";;
esac[root@master ~]# sh shiyan9.sh    #执行脚本
+-------------------------------------------------------------------------+
|                       System_tools V1.0                                 |
+-------------------------------------------------------------------------+
|               a. Stop And Disabled Firewalld.                           |
|               b. Disabled SELinux Secure System.                        |
|               c. Install Apache Service.                                |
|               d. Quit                                                   |
+-------------------------------------------------------------------------+Please input your select:  a
[root@master ~]# sh shiyan9.sh
+-------------------------------------------------------------------------+
|                       System_tools V1.0                                 |
+-------------------------------------------------------------------------+
|               a. Stop And Disabled Firewalld.                           |
|               b. Disabled SELinux Secure System.                        |
|               c. Install Apache Service.                                |
|               d. Quit                                                   |
+-------------------------------------------------------------------------+Please input your select:  b
setenforce: SELinux is disabled[root@master ~]# vim shiyan10.sh
#!/usr/bin/env bash
printf "\e[1;31m 确定要继续删除吗 yes/no: \e[0m" && read var    #\e[1;31m 这个是给字体添加颜色
case $var in"yes"|"y"|'Y'|"YES")echo "继续删除";;*)echo "停止删除";;
esac
[root@master ~]# sh shiyan10.sh    #执行脚本确定要继续删除吗 yes/no: yes    #选择yes
继续删除示例:使用函数实现选项条件内容,函数名字可自己随意定义,如hepl () { }
[root@master ~]# vim shiyan10.sh
#!/usr/bin/env bashhelp () {cat <<-EOF
System_tools V1.0
h   显示命令帮助
f   显示磁盘分区
d   显示磁盘挂载
m   查看内存使用
u   查看系统负载
q   退出程序
EOF
}
help
printf "\e[5;7;31m 确定要继续删除吗 yes/no: \e[0m" && read var
case $var in"h"|"H")help;;"f"|"F")fdisk -l;;"d"|"D")df -Th;;"m"|"M")free -h;;"u"|"U")uptime;;"q"|"Q")exit;;
esac[root@master ~]# sh shiyan10.sh 确定要继续删除吗 yes/no: yes
继续删除
[root@master ~]# vim shiyan11.sh
[root@master ~]# sh shiyan11.sh    #输入得出以下选项内容
System_tools V1.0
h   显示命令帮助
f   显示磁盘分区
d   显示磁盘挂载
m   查看内存使用
u   查看系统负载
q   退出程序         确定要继续删除吗 yes/no: h
System_tools V1.0
h   显示命令帮助
f   显示磁盘分区
d   显示磁盘挂载
m   查看内存使用
u   查看系统负载
q   退出程序     案例4:简单的JumpServer跳板主机1)mysql12)mysql23)bj-web1h)  helpq)  exit#跳板主机可以通过脚本实现主机之间的来回切换
#!/usr/bin/env bash
cat <<-EOF跳板主机1)master22)master33)master4h)  helpq)  exit
EOF
printf "\e[5;7;31m 请输入密码 : \e[0m" && read pass
if [ $pass = "ppp" ];thenelse echo "password is error" && exit
fi
printf "\e[5;7;31m 请输入你要连接的机器 : \e[0m" && read var
## 先免密和解析
case $var in1)ssh master2             ;;2)ssh master3;;3)ssh master4;;h)echo "you need help!!!";;q)exit;;
esac [root@master ~]# sh shiyan12.sh
跳板主机
1)master2
2)master3
3)master4
h)  help
q)  exit请输入密码 : ppp请输入你要连接的机器 : master2

3. shell循环for于语句

循环次数是固定的for i in {取值范围}
do循环体
done下面用for循坏语句采用的脚本,【实战技术非常强悍,需牢记】
示例1:  1-150数字求和
[root@master ~]# cat shiyan13.sh
#!/usr/bin/env bash
num=0
for i in {1..150}                      # {1..150}/(1,2,3,4,5, 100)/`seq 100`
donum=$[$num+$i]
done
echo $num
[root@master ~]# sh shiyan13.sh
11325                        #求和的结果示例2:找出1-20中能被2整除的数字
[root@master ~]# cat sy1.sh
#!/usr/bash
for i in {1..20}
doa=$[$i%2]if [ $a -eq 0 ]; thenecho $ifi
done[root@master ~]# sh sy1.sh    #执行脚本以下都是能被2整除的数字
2
4
6
8
10
12
14
16
18
20示例3:检测主机存活性,把229网段的主机能ping通的ip全部列出,当然还有一种更简单的方法
采用:nmap -sP 192.168.229.0/24 |grep "report for"   #可直接在命令行过滤所有ip
[root@master ~]# cat sy2.sh
#!/usr/bin/env bash
for i in {1..254}
do( ping -c1 -W1 192.168.229.$i &>/dev/nullif [ $? -eq 0 ]; then echo "192.168.229.$i is tong"fi)&
done[root@master ~]# sh sy2.sh
192.168.229..1 is tong
192.168.229..2 is tong
192.168.229..51 is tong
192.168.229..53 is tong
192.168.229..54 is tong
192.168.229..52 is tong
192.168.229..61 is tong
192.168.229.100 is tong示例4:计算文件lxw.txt中数值之和
[root@master ~]# cat lxw.txt
6324346
341241
34632151
34621125
36126
1512616
3461261
126162161253[root@master ~]# cat sy3.sh
#!/usr/bash
sum=0
for i in `cat lxw.txt`     #选择文件绝对路径
dosum=$[$sum+$i]          #采用变量
done
echo $sum         #得出结果值
[root@master ~]# sh sy3.sh
126243090119示例5. C 语言风格的 求1-500之和
[root@master ~]# cat sy4.sh
#!/usr/bash
for (( i=1; i<=500; i++))
dosum=$[$sum+$i]
doneecho $sum
[root@master ~]# sh sy4.sh
125250

4.shell循环while语句

循环次数不一定是固定的
可以固定
可以不固定
while循环语句 框架如下:while 条件
do循环体
done
==当条件测试成立(条件测试为真),执行循环体##完善系统工具的输出及操作性
#!/usr/bin/env bash
while 1>0
docat <<-EOF+-------------------------------------------------------------------------+|                   System_tools V1.0                                     |+-------------------------------------------------------------------------+|           a. Stop And Disabled Firewalld.                               ||           b. Disabled SELinux Secure System.                            ||           c. Install Apache Service.                                    ||           d. Quit                                                       |+-------------------------------------------------------------------------+
EOFprintf "\e[1;35m Please input your select: \e[0m" && read varcase "$var" in"a")systemctl stop firewalld && systemctl disable firewalld;;"b")sed -ri s/SELINUX=enforcing/SELINUX=disabled/g /etc/selinux/config;;"c")yum -y install httpd httpd-tools;;"d")exit;;*)printf "请按照上方提供的选项输入!!!\n";;esacif [ $? -eq 0 ];thenclearelseprintf "\e[1;31m Warning: Your program exist ERROR!!! \e[0m\n"breakfi
done示例:判断是否是字母
[root@master ~]# vim sy2.sh
#!/usr/bin/env bash
read -p "请输入一个字母" var
if [ ${#var} -eq 1 ]; thenecho "$var"
elseecho "$var 不是一个字母"exit 4
fi[root@master ~]# sh sy2.sh
请输入一个字母123
123 不是一个字母
[root@master ~]# sh sy2.sh
请输入一个字母abc
abc 不是一个字母
[root@master ~]# sh sy2.sh
请输入一个字母a
a示例:用while循环打印出乘法表格
#!/usr/bin/env bash
num=9
row=1
while [ $row -le $num ] ;docol=1while [ $col -le $row ] ;doprintf "$row*$col=$[$row*$col]\t"col=$[col+1]doneechorow=$[row+1]
done[root@master ~]# sh sy7.sh
1*1=1
2*1=2  2*2=4
3*1=3  3*2=6  3*3=9
4*1=4  4*2=8  4*3=12 4*4=16
5*1=5  5*2=10 5*3=15 5*4=20 5*5=25
6*1=6  6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7  7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8  8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9  9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 [root@master ~]# cat sy9.sh
#!/usr/bash
i=1while  [ $i -le 16 ]
do n=16while [ $n -ge $i ] doecho -n " "n=$[$n-1]donem=1while [ $m -le $i ]doecho -n "* "m=$[$m+1]doneecho i=$[$i+1]
done[root@master ~]# sh sy9.sh * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

6.shell循环until语句

循环次数不一定是固定的
可以固定
可以不固定until 条件
do循环体
done
==当条件测试成立(条件测试为假),执行循环体[root@host ~]# cat until.sh
#!/bin/bash
x=1
until [ $x -ge 8 ]
do   echo $xx=`expr $x + 1`
done
x=1
while [ ! $x -ge 10 ]
doecho $xx=`expr $x + 1`
done[root@master ~]# sh sy6.sh     #执行脚本 结果打印为1-7  1-9
1
2
3
4
5
6
7
1
2
3
4
5
6
7
8
9

7.shell循环控制shift、continue、break、exit

shift命令
位置参数可以用shift命令左移。比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1、$2、$3丢弃,$0不移动。不带参数的shift命令相当于shift 1。
对于位置变量或命令行参数,其个数必须是确定的,或者当 Shell 程序不知道其个数时,可以把所有参数一起赋值给变量$*。
若用户要求 Shell 在不知道位置变量个数的情况下,还能逐个的把参数一一处理,也就是在 $1 后为 $2,在 $2 后面为 $3 等,则需要用shift把所有参数变成$1示例1:
[root@master ~]# cat sy10.sh
#!/usr/bin/env bash
a=1
until [ $# -eq 0 ]
do
echo "第$a个参数为: $1 参数个数为: $#"
shift
a=$[a+1]
done[root@master ~]# sh sy10.sh  1 2 3 4 5 a
第1个参数为:1参数个数为:6
第2个参数为:2参数个数为:5
第3个参数为:3参数个数为:4
第4个参数为:4参数个数为:3
第5个参数为:5参数个数为:2
第6个参数为:a参数个数为:1
从上可知 shift 命令每次执行一次,变量的个数($#)减一,而变量值提前一位示例2:用 until 和 shift 命令计算所有命令行参数的和。[root@master ~]# cat  sy12.sh
#!/usr/bash
sum=0
until [ $# -eq 0 ]
dosum=`expr $sum + $1`shift
done
echo "sum is: $sum"[root@master ~]# sh sy12.sh  89 999 4564 5644
sum is: 11296     #求出的总和Shift 命令还有另外一个重要用途:Bash 定义了9个位置变量,从 $1 到 $9,这并不意味着用户在命令行只能使用9个参数,借助 shift 命令可以访问多于9个的参数。Shift 命令一次移动参数的个数由其所带的参数指定。例如当 shell 程序处理完前九个命令行参数后,可以使用 shift 9 命令把 $10 移到 $1。

8.Linux脚本中的break continue exit return

Linux脚本中的break continue exit return     【下面的参数能记住多少算多少,这些都是非常使用的参数】break
结束并退出循环continue
在循环中不执行continue下面的代码,转而进入下一轮循环exit
退出脚本,
常带一个整数给系统,如 exit 0return
在函数中将数据返回
或返回一个结果给调用函数的脚本可理解为:break是立马跳出循环;continue是跳出当前条件循环,继续下一轮条件循环;exit是直接退出整个脚本例如:
在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell使用两个命令来实现该功能:break和continue。break命令break命令允许跳出所有循环(终止执行后面的所有循环)。下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,需要使用break命令。[root@master shell]# cat sy1.sh     #这个脚本加了continue,不会跳出循坏,输入比5大的数值即可跳出循环!
#!/usr/bash
while :
do echo -n "input a number between 1 to 5:"read anumcase $anum in1|2|3|4|5) echo "you number is $anum!";;*) echo "you do not select a number between 1 to 5,game is over!"break;;esac
done
continue[root@master shell]# sh sy1.sh
input a number between 1 to 5:1
you number is 1!
input a number between 1 to 5:2
you number is 2!
input a number between 1 to 5:3
you number is 3!
input a number between 1 to 5:4
you number is 4!
input a number between 1 to 5:6
you do not select a number between 1 to 5,game is over
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。示例: 对上面的例子进行修改:添加continue这个参数就可以陷入无限循环!!!!
[root@master shell]# vim sy2.sh
#!/bin/bash
while :
doecho -n "Input a number between 1 to 5: "read aNumcase $aNum in1|2|3|4|5) echo "Your number is $aNum!";;*) echo "You do not select a number between 1 to 5!"continueecho "Game is over!";;esac
done[root@master shell]# sh sy2.sh
Input a number between 1 to 5: 1
Your number is 1!
Input a number between 1 to 5: 2
Your number is 2!
Input a number between 1 to 5: 3
Your number is 3!
Input a number between 1 to 5: 4
Your number is 4!
Input a number between 1 to 5: ^C
[root@master shell]# 运行代码发现,当输入大于5的数字时,该例中的循环不会结束,语句代码如下:
echo "Game is over!"#实战--shell版本jumpserver开发  模板,测试自己的搭建shell脚本思路
#!/usr/bin/env bash
#
# Author: 可以先添加上账密验证环节while :
dotrap ':' INT EXIT TSTP TERM HUPclearcat <<-EOF+-------------------------------------+|  JumpServer @Version1.0           |+-------------------------------------+|    a. WebServer Apache.             ||    b. MySQL Databases Server.        ||    c. PHP Development Computer.     ||    d. Quit                        |+-------------------------------------+
EOFread -p "Please input your jump to server's number: " computercase $computer ina)ssh jumper@192.168.229.62                  //可以嵌套子case循环;;b)ssh jumper@192.168.229.63;;c)ssh jumper@192.168.229.64;;d)exit;;*)printf "ERROR: Please redo your select!";;esac
done

三.shell函数与正则 【重中之重高级进阶版】

1.shell编程之函数

函数,是搭建整个shell脚本的一个强大得多功能,之前我们学的都是如何搭建局部模式,正如盖一栋房子,只把边边角角建筑好,接下来就需要各大部门的协调整合才能进行一个竣工验收的效果,函数正式如此!function (功能) 功能函数定义函数
调用函数
取消函数
函数传参 命名空间 local
返回值 return valuevalue不能超过0-255

shell函数function

1.函数声明function_name () { list of commands
}函数名 function_name,这就是你将使用它从其他地方在你的脚本调用。
取消函数
unset myfunc    //取消函数示例1:通过函数调取字符值
[root@master shell]# cat sy3.sh
#!/usr/bash
myfunc()   #添加函数,可随意定义
{echo “This is my first shell function”
}
myfunc         #调用函数,这一步必须有,比如你添加是个函数就得在最后调用十个函数
[root@master shell]# sh sy3.sh
“This is my first shell function”2.函数传参
在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数
示例:
[root@master shell]# cat sy4.sh
#!/bin/bash
funParam(){echo "第一个参数为 $1 !"echo "第二个参数为 $2 !"echo "第十个参数为 $10 !"echo "第十个参数为 ${10} !"echo "第十一个参数为 ${11} !"echo "参数总数有 $# 个!"echo "作为一个字符串输出所有参数 $* !"
}
funParam 1 2 3 4 5 6 7 8 9 34 73
[root@master shell]# sh sy4.sh     #把函数参数进行参数传递调用
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !

2.shell编程之数组


数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小(与 PHP 类似)。与大部分编程语言类似,数组元素的下标由0开始。数组、数组名称、数组成员(a[0])、下标、数组成员值  数组定义:
[root@master shell]# cat sy5.sh
#!/usr/bash
declare -a myarry=(5 6 7 8)echo ${myarry[3]}     #这里选择数组从上面数字6开始为第一个,选择3则是第8个,所以输出结果等于8
[root@master shell]# sh sy5.sh
8定义方法2:# array=( one two three four five six )# array2=(tom jack alice)# array3=(`cat /etc/passwd`)        将该文件中的每一个行作为一个元素赋值给数组array3# array4=(`ls /var/ftp/Shell/for*`)# array5=(tom jack alice "bash shell")# colors=($red $blue $green $recolor)         //先给变量赋值 或者重新定义数组# array5=(1 2 3 4 5 6 7 "linux shell" [20]=saltstack)   //直接指定下标位置,数组下标不一定连续,可以为空定义方法3:#!/bin/basharea[11]=23area[13]=37area[51]="UFOs"#  数组成员不必一定要连贯或连续的.
#  数组的一部分成员允许不被初始化.
#  数组中空缺元素是允许的.访问数组
当您设置任何数组变量,并可访问它,如下所示:
${array_name[index]}
示例:
[root@master shell]# cat sy6.sh
#!/bin/sh
NAME[0]="BJ"
NAME[1]="SH"
NAME[2]="SZ"
NAME[3]="GZ"
NAME[4]="HZ"
echo "First Index: ${NAME[0]}"     #这里是可以调用函数数组比如0对应BJ
echo "Second Index: ${NAME[1]}"[root@master shell]# sh sy6.sh
First Index: BJ
Second Index: SH您可以访问数组中的所有项目通过以下方式之一:
${array_name[*]}
${array_name[@]}[root@master shell]# cat sy7.sh
#!/usr/bin
NAME[0]="BJ"
NAME[1]="SH"
NAME[2]="SZ"
NAME[3]="GZ"
NAME[4]="HZ"
echo "First Index: ${NAME[*]}"     #调取所有
echo "Second Index: ${NAME[@]}"[root@master shell]# sh sy7.sh
First Index: BJ SH SZ GZ HZ
Second Index: BJ SH SZ GZ HZ'疑难点
shell数组中"*" 和 "@" 区别
关于在shell脚本中数组变量中 “*”跟 “@” 区别
“*”当变量加上“” 会当成一串字符串处理.
“@”变量加上“” 依然当做数组处理.
在没有加上“” 的情况下 效果是等效的.'示例:
[root@master shell]# cat sy8.sh
#!/usr/bin/env bash
array=('gz' 'cloud' '19')
echo "case 1"
for line in "${array[@]}"
do
echo $line
done
echo "case 2"
for line in "${array[*]}"
do
echo $line
done
echo "case 3"
for line in ${array[*]}
do
echo $line
done
echo "case 4"
for line in ${array[@]}
do
echo $line
done[root@master shell]# sh sy8.sh
case 1
gz
cloud
19
case 2
gz cloud 19
case 3
gz
cloud
19
case 4
gz
cloud
19

3. 正则表达式RE [重点正则表达式,必会技能]

正则表达式基本元字符
正则表达式拓展元字符

正则表达式(regular expression, RE)是一种字符模式, 用于在查找过程中匹配指定的字符. 在大多数程序里, 正则表达式都被置于两个正斜杠之间;例如/l[oO]ve/就是由正斜杠界定的正则表达式, 它将匹配被查找的行中任何位置出现的相同模式. 在正则表达式中,元字符是最重要的概念正则表达式与通配符:1.正则表达式一般用于处理文本内容,常用命令有grep,sed,awk,vim等通配符一般用于匹配文件名,常用命令有find,ls,cp等2.各符号的含义不尽相同.什么地方使用正则表达式vim grep sed awk  nginx apache mail垃圾邮件过滤。。。  perl java python 等等都使用正则构成  1.元字符(基本元字符、扩展元字符)        2.除元字符之外的任意字符都是表示他字面意思的正则表达式

正则表达式的匹配过程

正则表达式是按照从表达式最左端第一个字符开始,左到右依次一个一个字符进行匹配.当字符串中有字符成功匹配到正则表达式中字符,则从这个位置开始尝试正则表达式中的下一个字符进行匹配,如果匹配成功则继续从这个位置开始匹配正则表达式中下一个字符;如果匹配不成功,则“回溯”到第一次匹配的字符处重新从正则表达式中第一个字符开始匹配。

No.1 正则表达式基本元字符 【以下所有的参数最好能记住多少记住多少,在企业实战是最能体现工作效益的】

基本正则表达式元字符
元字符                           功能                                示例
^                               行首定位符                           ^love
$                               行尾定位符                           love$
.                               匹配单个字符                          l..e
*                               匹配前导符0到多次                   ab*love
.*                              任意多个字符
[]                              匹配方括号中的任意一个字符           [lL]ove
[ - ]                           匹配指定范围内的一个字符                [a-z0-9]ove
[^]                             匹配不在指定组内的字符              [^a-z0-9]ove
\                               用来转义元字符                      love\.
\<                               词首定位符                            \<love
\>                               词尾定位符                            love\>:% s/172.16.130.1/172.16.130.5/
:% s/\(172.16.130.\)1/\15/
:% s/\(172.\)\(16.\)\(130.\)1/\1\2\35/
:3,9 s/\(.*\)/#\1/x\{m\}                            字符x重复出现m次                  o\{5\}
x\{m,\}                         字符x重复出现m次以上              o\{5,\}
x\{m,n\}                        字符x重复出现m到n次             o\{5,10\}   

No.2 正则表达式拓展元字符

powershell
扩展正则表达式元字符
+                              匹配一个或多个前导字符         [a-z]+ove
?                               匹配零个或一个前导字符         lo?ve
a|b                             匹配a或b                        love|hate
()                              组字符loveable|rs            love(able|rs) ov+  ov+ (ov)+
(..)(..)\1\2                    标签匹配字符                  (love)able\1er
x{m}                            字符x重复m次                  o{5
x{m,}                           字符x重复至少m次               o{5,}
x{m,n}                          字符x重复m到n次                o{5,10}编写正则表达式的3 个步骤:1 知道要匹配的内容以及它如何出现在文本中。2 编写一个模式来描述要匹配的内容3 测试模式来查看它匹配的内容,不能错,不能漏,不能多

shell文本处理三剑客 【重点戏文本处理三剑客】

1.正则表达式RE

正则表达式RE
========================================================
重要的文本处理工具:vim、sed、awk、grep一、什么是正则表达式?
正则表达式(regular expression, RE)是一种字符模式,用于在查找过程中匹配指定的字符。
在大多数程序里,正则表达式都被置于两个正斜杠之间;例如/l[oO]ve/就是由正斜杠界定的正则表达式,它将匹配被查找的行中任何位置出现的相同模式。在正则表达式中,元字符是最重要的概念。匹配数字:     ^[0-9]+$                                       123 456 5y7
匹配Mail:  [a-z0-9_]+@[a-z0-9]+\.[a-z]+                  tigerfive2010@126.com
匹配IP:        [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}或[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}[root@master shell]# egrep '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' /etc/sysconfig/network-scripts/ifcfg-ens33
IPADDR=172.16.100.1
NETMASK=255.255.255.0
GATEWAY=172.16.100.254
[root@master shell]# egrep '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' /etc/sysconfig/network-scripts/ifcfg-ens33
IPADDR=172.16.100.1
NETMASK=255.255.255.0
GATEWAY=172.16.100.254二、元字符
定义:元字符是这样一类字符,它们表达的是不同于字面本身的含义
shell元字符(也称为通配符)       由shell来解析,如rm -rf *.pdf,元字符* Shell将其解析为任意多个字符
正则表达式元字符                   由各种执行模式匹配操作的程序来解析,比如vi、grep、sed、awk、python[root@master shell]# rm -rf *.pdf[root@master shell]# grep 'abc*' /etc/passwd
abrt:x:173:173::/etc/abrt:/sbin/nologinvim示例:
:1,$ s/tom/David/g             //如tom、anatomy、tomatoes及tomorrow中的“tom”被替换了,而Tom确没被替换
:1,$ s/\<[Tt]om\>/David/g1. 正则表达式元字符:
===基本正则表达式元字符
元字符         功能                                          示例
========================================================
^                   行首定位符                               ^love
$                   行尾定位符                               love$
.                   匹配单个字符                              l..e
*                   匹配前导符0到多次                       ab*love
.*                  任意多个字符
[]                  匹配指定范围内的一个字符                  [lL]ove
[ - ]               匹配指定范围内的一个字符                  [a-z0-9]ove
[^]                 匹配不在指定组内的字符                 [^a-z0-9]ove
\                   用来转义元字符                         love\.
\<                   词首定位符                               \<love
\>                   词尾定位符                               love\>
\(..\)              匹配稍后使用的字符的标签          :% s/172.16.130.1/172.16.130.5/:% s/\(172.16.130.\)1/\15/:% s/\(172.\)\(16.\)\(130.\)1/\1\2\35/:3,9 s/\(.*\)/#\1/ x\{m\}          字符x重复出现m次                       o\{5\}
x\{m,\}         字符x重复出现m次以上                 o\{5,\}
x\{m,n\}        字符x重复出现m到n次                 o\{5,10\}                   ===扩展正则表达式元字符
+                  匹配一个或多个前导字符         [a-z]+ove
?                   匹配零个或一个前导字符         lo?ve
a|b                 匹配a或b                                   love|hate
()                  组字符                                     loveable|rs    love(able|rs)    ov+  ov+ (ov)+
(..)(..)\1\2        标签匹配字符                          (love)able\1er
x{m}                字符x重复m次                         o{5}
x{m,}               字符x重复至少m次                       o{5,}
x{m,n}              字符x重复m到n次                       o{5,10}2. POSIX字符类:
表达式           功能                                        示例
[:alnum:]        字母与数字字符                            [[:alnum:]]+
[:alpha:]        字母字符(包括大小写字母)                   [[:alpha:]]{4}
[:blank:]        空格与制表符                              [[:blank:]]*
[:digit:]        数字字母                                 [[:digit:]]?
[:lower:]        小写字母                                  [[:lower:]]{5,}
[:upper:]        大写字母                                 [[:upper:]]+
[:punct:]        标点符号                                  [[:punct:]]
[:space:]        包括换行符,回车等在内的所有空白            [[:space:]]+正则匹配示例:vim
/love/
/^love/                           love开头的行
/love$/                           love结尾的行
/l.ve/                            l和ve间可以存在任意一个字符
/lo*ve/                           l和ve间可以存在任意多个o
/[Ll]ove/                         Love love
/love[a-z]/                       lovea loveb .. lovez
/love[^a-zA-Z0-9]/                love_ love/ /.*/                              整行
/^$/                              空行  /^[ ]*$/
/^[A-Z]..$/                       一个大写字母加两个任意字符的行
/^[A-Z][a-z]*3[0-5]/
/[a-z]*\./                        任意多个小写字母加上一个.
/^ *[A-Z][a-z][a-z]$/
/^[A-Za-z]*[^,][A-Za-z]*$/
/\<fourth\>/
/\<f.*th\>/                         f为词首 th为词尾的任意单词
/5{2}2{3}\./                      55222.
/^$/                                空行
/^[ \t]*$/                           空行注释行
/^#/
/^[ \t]*#/
:1,$ s/\([Oo]ccur\)ence/\1rence/
:1,$ s/\(square\) and \(fair\)/\2 and \1/   

2.shell变成之grep


grep家族
========================================================grep:   在文件中全局查找指定的正则表达式,并打印所有包含该表达式的行
egrep:  扩展的egrep,支持更多的正则表达式元字符
fgrep:  固定grep(fixed grep),有时也被称作快速(fast grep),它按字面解释所有的字符一、grep命令格式
grep [选项] PATTERN filename filename ...
# grep 'Tom' /etc/passwd
# grep 'bash shell' /etc/test
找到:                      grep返回的退出状态为0
没找到:                 grep返回的退出状态为1
找不到指定文件:     grep返回的退出状态为2grep 程序的输入可以来自标准输入或管道,而不仅仅是文件,例如:
# grep 'tom'
# ps aux |grep 'sshd'
# ll |grep '^d'
# grep 'alice' /etc/passwd /etc/shadow /etc/group二、grep使用的元字符
grep:                       使用基本元字符集    ^, $, ., *, [], [^], \< \>,\(\),\{\}, \+, \|
egrep(或grep -E):    使用扩展元字符集    ?, +, { }, |, ( )
注:grep也可以使用扩展集中的元字符,仅需要对这些元字符前置一个反斜线\w                            所有字母与数字,称为字符[a-zA-Z0-9]       'l[a-zA-Z0-9]*ve'            'l\w*ve'
\W                      所有字母与数字之外的字符,称为非字符   'love[^a-zA-Z0-9]+'      'love\W+'
\b                          词边界                                                      '\<love\>'                 '\blove\b'                        三、grep 示例
grep -E 或 egrep
# egrep 'NW' datafile
# egrep 'NW' d*
# egrep '^n' datafile
# egrep '4$' datafile
# egrep TB Savage datafile
# egrep 'TB Savage' datafile
# egrep '5\..' datafile
# egrep '\.5' datafile
# egrep '^[we]' datafile
# egrep '[^0-9]' datafile
# egrep '[A-Z][A-Z] [A-Z]' datafile
# egrep 'ss* ' datafile
# egrep '[a-z]{9}' datafile
# egrep '\<north' datafile
# egrep '\<north\>' datafile
# egrep '\<[a-r].*n\>' datafile
# egrep '^n\w*\W' datafile
# egrep '\bnorth\b' datafile# egrep 'NW|EA' datafile
# egrep '3+' datafile
# egrep '2\.?[0-9]' datafile
# egrep '(no)+' datafile
# egrep 'S(h|u)' datafile
# egrep 'Sh|u' datafile三、grep选项
-i, --ignore-case                   忽略大小写
-l, --files-with-matches        只列出匹配行所在的文件名
-n, --line-number               在每一行前面加上它在文件中的相对行号
-c, --count                         显示成功匹配的行数
-s, --no-messages               禁止显示文件不存在或文件不可读的错误信息
-q, --quiet, --silent               静默--quiet, --silent
-v, --invert-match              反向查找,只显示不匹配的行
-R, -r, --recursive             递归针对目录
--color                             颜色
-o, --only-matching         只显示匹配的内容
-B, --before-context=NUM  print NUM lines of leading context
-A, --after-context=NUM     print NUM lines of trailing context
-C, --context=NUM           print NUM lines of output context示例:
[root@master ~]# egrep 'ifcfg' /etc/*          文件
[root@master ~]# grep -R 'ifcfg' /etc           目录[root@master ~]# egrep 'root' /etc/passwd /etc/shadow /etc/hosts
/etc/passwd:root:x:0:0:root:/root:/bin/bash
/etc/passwd:operator:x:11:0:operator:/root:/sbin/nologin
/etc/shadow:root:$6$gcO6Vp4t$OX9LmVgpjtur67UQdUYfw7vJW.78.uRXCLIxw4mBk82Z99:7:::[root@master ~]# egrep -l 'root' /etc/passwd /etc/shadow /etc/hosts
/etc/passwd
/etc/shadow[root@master ~]# egrep -n 'root' /etc/passwd /etc/shadow /etc/hosts
/etc/passwd:1:root:x:0:0:root:/root:/bin/bash
/etc/passwd:11:operator:x:11:0:operator:/root:/sbin/nologin
/etc/shadow:1:root:$6$gcO6Vp4t$OX9LmVgpjtur67UQdUy8.M78.uRXCLIxw4mBk82ZrNlxyf54[root@master ~]# egrep '54:04:A6:CE:C2:1F' /etc/sysconfig/*
[root@master ~]# egrep 'ifcfg' /etc/*           文件
[root@master ~]# grep -R 'ifcfg' /etc           目录
[root@master ~]# egrep -R '54:04:A6:CE:C2:1F' /etc/sysconfig/[root@master ~]# egrep '^IPADDR' /etc/sysconfig/network-scripts/ifcfg-eth0 |egrep -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
192.168.2.254
[root@master ~]# egrep '^IPADDR' /etc/sysconfig/network-scripts/ifcfg-eth0 |egrep -o '([0-9]{1,3}\.){3}[0-9]{1,3}'
192.168.2.254
[root@master ~]#  grep -r 'ifcfg' ./* -l       #谨慎使用
[root@master ~]# grep --help |grep '\-R'-R, -r, --recursive       equivalent to --directories=recurse[root@master ~]#  grep --help |egrep -A5 '\-R'

shell编程之SED [强调实战必备技能之一]

文本的操作
sed是一个“非交互式的”面向字符流的编辑器。
awk是一种负责模式匹配的程序设计语言,,的典型示例是将数据转换成格式化的报表。sed  stream editor是一种文本编辑器,默认情况下是不会修改原文件的。也是一种非交互式的编辑器工作原理sed 是一种在线的、非交互式的编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区
中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容
送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。语法:sed    [选项]   '行的定位 动作'  文件...sed [options] 'command' file(s)sed [options] -f scriptfile file(s)
注:
sed和grep不一样,不管是否找到指定的模式,它的退出状态都是0
只有当命令存在语法错误时,sed的退出状态才是非0 支持正则表达式与grep一样,sed在文件中查找模式时也可以使用正则表达式(RE)和各种元字符。正则表达式是
括在斜杠间的模式,用于查找和替换,以下是sed支持的元字符。
使用基本元字符集    ^, $, ., *, [], [^], \< \>,\(\),\{\}
使用扩展元字符集    ?, +, { }, |, ( )使用扩展元字符的方式:
\+
sed -r==地址(定址)  模式:1. 空模式,表示所有的行都执行动作2. 以行号作为模式1). 单独的行号如:1   就是处理第1行$   处理最后一行2). 起始行,结束行如:1,5     处理第1到5行3). 起始行~步长每隔多少行操作一次如:2~2 从第2行开始,每隔1行4). 起始位置,+N表示从起始位置开始,后面的N行都进行处理如:3,+5   处理3-8行3. 以正则作为模式             1). /正则表达式/如:/^root/2). /正则表达式1/,/正则表达式2/表示从第一次匹配到正则表达式1开始到第一次匹配到正则表达式2之间的所有行如:/^bin/,/sh$/
==动作        动作-----处理命令:   ! 非 : 放在命令前面表示取反1.  d    删除                                delete               2.  p    打印                                print3.  r    读取                                read              4.  w    写                                  write5.  a    追加   在匹配的行下面插入内容           append   6.  i    插入   在匹配行的上一行插入内容         insert7.  c    修改    本行替换                      change8.  y    转换的命令,一一对应转换9.  n    处理下一行                            next10. q    退出,不会再向模式空间读入新的行          quit11. s    查找替换'模式s/旧的内容(正则表达式)/替换内容(新的内容)/[修饰符]'修饰符:g:全局替换n:n为数字,1-512    替换第n个匹配到的内容p:打印      -nw:把处理过的行写入到另一个文件12. l   列出非打印字符扩展:
h               把模式空间里的内容复制到暂存缓冲区(覆盖)
H               把模式空间里的内容追加到暂存缓冲区
g               取出暂存缓冲区的内容,将其复制到模式空间,覆盖该处原有内容
G               取出暂存缓冲区的内容,将其复制到模式空间,追加在原有内容后面
x               交换暂存缓冲区与模式空间的内容\u   upper   大写字母\l    lower    小写字母将文件中所有小写字母替换成大写字母:# sed  's/[a-z]/\u&/g'  /tmp/pass==选项:-n:静默输出,关闭模式空间的输出,不会输出未匹配到的行 一般与p命令结合使用-e:允许进行多项编辑,也就是说对同一行做多次处理、. 可以做多点编辑  -e '动作1'  -e '动作2'   ==  '动作1;动作2'-f: 后接sed脚本,指定执行的sed脚本(将模式动作写到文件中)-r:允许使用扩展正则-i:直接作用于原文件    没有输出  在使用-i之前一定先不加-i看看效果-i.bak:修改原文件之前进行备份控制流!  命令取反 例: 1!d 删除第一行以外的行{} 命令组合 命令用分号分隔 {1h;G} 可以理解为 -e 参数的另一种写法=  打印行号(输入行的号码,而非处理的次数行号) 例如: sed -n '2{=;p}' infilen  读入下一行到模式空间 例:'4{n;d}' 删除第5行N  追加下一行到模式空间.P  输出多行模式空间的第一部分,直到第一个嵌入的换行符为止。在执行完脚本的最后一个命令之后,模式空间的内容自动输出。P命令经常出现在N命令之后和D命令之前。d: 删除pattern中的所有⾏行,并读入下一新行到P中  [P来表示模式空间,M来表示保持空间]D:D 删除M ,P中的第一行,不读入下一行           [P来表示模式空间,M来表示保持空间]这三个命令能建立一个输入. 输出循环,用来维护两行模式空间,但是一次只输出一行。这个循环的目的是只输出模式空间的第一行,然后返回到脚本的顶端将所有的命令应用于模式空间的第二行。没有这个循环,当执行脚本中的最后一个命令时,模式空间中的这两行都将被输出。#### sed命令示例
删除命令:d
# sed -r '3d' datafile
# sed -r '3{d;}' datafile
# sed -r '3{d}' datafile# sed -r '3,$d' datafile
# sed -r '$d' datafile
# sed -r '/north/d' datafile
# sed -r '/sout/d' datafile替换命令:s
# sed -r 's/west/north/g' datafile
# sed -r 's/^west/north/' datafile
# sed -r 's/[0-9][0-9]$/&.5/' datafile                //&代表在查找串中匹配到的内容
# sed -r 's/Hemenway/Jones/g' datafile
# sed -r 's/(Mar)got/\1ianne/g' datafile
# sed -r 's#3#88#g' datafile          读文件命令:r
# sed -r '/Suan/r /etc/newfile' datafile
# sed -r '2r /etc/hosts' a.txt
# sed -r '/2/r /etc/hosts' a.txt写文件命令:w
# sed -r '/north/w newfile' datafile
# sed -r '3,$w /new1.txt' datafile追加命令:a
# sed -r '2a\1111111111111' /etc/hosts
# sed -r '2a\1111111111111\
> 222222222222\
> 333333333333' /etc/hosts插入命令:i
# sed -r '2i\1111111111111' /etc/hosts
# sed -r '2i111111111\
> 2222222222\
> 3333333333' /etc/hosts修改命令:c
# sed -r '2c\1111111111111' /etc/hosts
# sed -r '2c\111111111111\
> 22222222222\
> 33333333333' /etc/hosts获取下一行命令:n
# sed -r '/eastern/{ n; d }' datafile
# sed -r '/eastern/{ n; s/AM/Archile/ }' datafile         暂存和取用命令:h H g G
# sed -r '1h;$G' /etc/hosts
# sed -r '1{h;d};$G' /etc/hosts
# sed -r '1h; 2,$g' /etc/hosts
# sed -r '1h; 2,3H; $G' /etc/hosts暂存空间和模式空间互换命令:x
# sed -r '4h; 5x; 6G' /etc/hosts反向选择: !
# sed -r '3d' /etc/hosts
# sed -r '3!d' /etc/hosts多重编辑选项:-e
# sed -r -e '1,3d' -e 's/Hemenway/Jones/' datafile
# sed -r '1,3d; s/Hemenway/Jones/' datafile   # sed -r '2s/WE/1000phone/g; 2s/Gray/YYY/g' datafile
# sed -r '2{s/WE/1000phone/g; s/Gray/YYY/g}' datafile七、sed常见操作
删除配置文件中#号注释行
sed -ri '/^#/d' file.conf
sed -ri '/^[ \t]*#/d' file.conf删除配置文件中//号注释行
sed -ri '\Y^[ \t]*//Yd' file.conf删除无内容空行
sed -ri '/^[ \t]*$/d' file.conf删除注释行及空行:
# sed -ri '/^[ \t]*#/d; /^[ \t]*$/d' /etc/vsftpd/vsftpd.conf
# sed -ri '/^[ \t]*#|^[ \t]*$/d' /etc/vsftpd/vsftpd.conf
# sed -ri '/^[ \t]*($|#)/d' /etc/vsftpd/vsftpd.conf修改文件:
# sed -ri '$a\chroot_local_user=YES' /etc/vsftpd/vsftpd.conf
# sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config
# sed -ri '/UseDNS/cUseDNS no' /etc/ssh/sshd_config
# sed -ri '/GSSAPIAuthentication/cGSSAPIAuthentication no' /etc/ssh/sshd_config给文件行添加注释:
# sed -r '2,6s/^/#/' a.txt
# sed -r '2,6s/(.*)/#\1/' a.txt
# sed -r '2,6s/.*/#&/' a.txt                                             &匹配前面查找的内容示例二:
示例文件
file1.txt
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post Road, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA用Massachusetts替换MA:
#sed 's/MA/Massachusetts/' file1.txt使用多重指令:
# sed 's/ MA/, Massachusetts/ ; s/ PA/, Pennsylvania/' file1.txt
或者:
#sed -e's/ MA/, Massachusetts/' -e's/ PA/, Pennsylvania/' file1.txt使用脚本文件:
脚本:namestate
s/ MA/, Massachusetts/
s/ PA/, Pennsylvania/
s/ CA/, California/
s/ VA/, Virginia/
s/ OK/, Oklahoma/$ sed -f namestate file1.txt保存输出:
$ sed -f namestate file1.txt > newfile.txt阻止输入行自动显示:
$ sed -n 's/MA/Massachusetts/p' file1.txt常见出错信息:
‘’不匹配
s/src/dst/ 缺少最后的“/”sed流编辑器用法及解析sed: stream editor(流编辑器)的缩写. 它们最常见的用法是进行文本的替换. [root@master ~]# sed '1d' passwd   //删除文件的第1行bin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologin[root@master ~]# sed '1,2d' passwd  //删除文件的第1,2行daemon:x:2:2:daemon:/sbin:/sbin/nologin[root@master ~]# cat e.txt /etc/abc/456etc
[root@master ~]# sed -r 's#/etc/abc#/var/lib#' e.txt /var/lib/456etc[root@master ~]# cat passwd root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@master ~]# sed '2,$d' passwd       //删除第2行到最后一行sroot:x:0:0:root:/root:/bin/bash
[root@master ~]# sed '/root/d' passwd    //匹配到root,删除此行bin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@master ~]# sed '/root/,2d' passwd  //匹配到root行,到此行的第2行daemon:x:2:2:daemon:/sbin:/sbin/nologin[root@master ~]# cat -n passwd 1  root:x:0:0:root:/root:/bin/bash2  bin:x:1:1:bin:/bin:/sbin/nologin3  daemon:x:2:2:daemon:/sbin:/sbin/nologin4  adm:x:3:4:adm:/var/adm:/sbin/nologin5  lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin6  sync:x:5:0:sync:/sbin:/bin/sync7  shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown8  halt:x:7:0:halt:/sbin:/sbin/halt9  mail:x:8:12:mail:/var/spool/mail:/sbin/nologin10  operator:x:11:0:operator:/root:/sbin/nologin[root@master ~]# sed '1~2d' passwd         //删除奇数行bin:x:1:1:bin:/bin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/synchalt:x:7:0:halt:/sbin:/sbin/haltoperator:x:11:0:operator:/root:/sbin/nologin[root@master ~]# sed '0~2d' passwd         //删除偶数行root:x:0:0:root:/root:/bin/bashdaemon:x:2:2:daemon:/sbin:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownmail:x:8:12:mail:/var/spool/mail:/sbin/nologin1. sed可以从stdin中读取内容$ cat filename | sed 's/pattern/replace_string/'
2. 选项-i会使得sed用修改后的数据替换原文件$ sed -i 's/pattern/replace_string/' filename
3. g标记可以使sed执行全局替换$ sed 's/pattern/replace_string/g' filename
4. g标记可以使sed匹配第N次以后的字符被替换$ echo "thisthisthisthis" | sed 's/this/THIS/2g'
5. sed中的分隔符可以替换成别的字符, 因为s标识会认为后面的字符为分隔符$ sed 's:text:replace_text:'$ sed 's|text|replace_text|'
6. sed可以利用指令来删除文件中的空行$ sed '/^$/d' filename
7. 替换指定的字符串或数字$ cat sed_data.txt11 abc 111 this 9 file contains 111 11 99 numbers 0000$ sed -i 's/\b[0-9]\{3\}\b/NUMBER/g' sed_data.txt$ cat sed_data.txt11 abc NUMBER this 9 file contains NUMBER 11 99 numbers 0000
8. 由于在使用-i参数时比较危险, 所以我们在使用i参数时在后面加上.bak就会产生一个备份的文件,以防后悔$ sed -i.bak 's/pattern/replace_string/' filename
9. sed如果在脚本中使用的话, 不可避免的要调用变量, 所以以下这种方式可以用来调用变量即‘’换成了“”$ text=hello$ echo "hello world" | sed "s/$text/HELLO/"
10. 模式空间保持空间示例1. 在每行下面添加一个空行  sed 'G' a.sh   2. 将第一行换到最后一行   sed -r '1{h;d};$G' a.sh           3. 交换第一行和第二行内容      sed -r '1{h;d};2G' a.sh      4. 将第一行复制到每个偶数行下面   sed '1h;2~2G;' a.sh5. 交换第一行和第三行的内容     sed '1{h;d};2{x;H;d};3G' a.sh   6. 用sed实现tac的效果sed '1!G;h;$!d' a.sh   7. 实现行列转化sed -r 'H;${x;s/\n/ /g};$!d' a.shsed -n 'H;${x;s/\n/ /g;p}' a.shsed  -n '1p' aa.txt
sed  '' aa.txt
sed  -n '$p' aa.txt
sed  -n '1,4p' aa.txt
sed  -n '1~2p' aa.txt
sed  -n '2~2p' aa.txt
sed  -n '2,+3p' aa.txt
sed -n  '/Alice/p'  aa.txt
sed -n  '/A/p'  aa.txt
sed -n  '/A.*/p'  aa.txt
sed -n  '/A$/p'  aa.txt
sed -n  '/MA$/p'  aa.txt
sed -n  '/MA$/,/VA$/p'  aa.txt
sed -n  '/MA$/,/VA$/!p'  aa.txt
sed 's/[a-z]/\u&/g' aa.txt
sed -n '/Alice/n;p' aa.txt sed -n '1~2n;p' aa.txt
sed -n '1~2p' aa.txt sed -n '6q;p' aa.txt
sed -n 'p;6q' aa.txtsed -n 'p;6r /etc/hosts' aa.txtsed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0sed -in 'p;1r /etc/hosts' aa.txtsed  '1d' aa.txt
sed  '1!d' aa.txtsed -r 's/\<[0-9][0-9]\>/&.5/' aa.txt sed -nr '3{n;p}' aa.txt
sed -nr '3n;p' aa.txt暂存和取用命令:h H g G
# sed -r '1h;$G' /etc/hosts
# sed -r '1{h;d};$G' /etc/hosts
# sed -r '1h; 2,$g' /etc/hosts
# sed -r '1h; 2,3H; $G' /etc/hosts暂存空间和模式空间互换命令:x
# sed -r '4h; 5x; 6G' /etc/hostssed -r '1h;2,$g' aa.txt
sed -r '1h;2,$G' aa.txt
sed -r '1H;2,$g' aa.txt
sed -r '1H;2,$G' aa.txt  sed -r '1g;$x' aa.txt
sed -r '1h;$x' aa.txtsed -r '4h; 5x; 6G'  aa.txt1. 在每行下面添加一个空行  sed 'G' a.sh
2. 将第一行换到最后一行   sed -r '1{h;d};$G' a.sh
3. 交换第一行和第二行内容      sed -r '1{h;d};2G' a.sh
4. 将第一行复制到每个偶数行下面   sed '1h;2~2G;' a.sh
5. 交换第一行和第三行的内容     sed '1{h;d};2{x;H;d};3G' a.sh
6. 用sed实现tac的效果sed '1!G;h;$!d' a.sh
7. 实现行列转化sed -r 'H;${x;s/\n/ /g};$!d' a.shsed -n 'H;${x;s/\n/ /g;p}' a.sh

shell编程之AWK

awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息
awk处理过程: 依次对每一行进行处理,然后输出
默认分隔符是空格或者tab键

awk简介awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个
或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix
下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定
模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(
屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。awk分别代表其作者姓氏的第一个字
母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的
GNU版本,它提供了Bell实验室和GNU的一些扩展。awk的两种形式语法格式
awk [options] 'commands' filenames
awk [options] -f awk-script-file filenames==options:
-F   定义输入字段分隔符,默认的分隔符是空格或制表符(tab)
BEGIN{}            {}              END{}行处理前            行处理            行处理后
[root@master ~]# awk 'BEGIN{print 1/2} {print "ok"} END{print "----"}' /etc/hosts
0.5
ok
----BEGIN{}     通常用于定义一些变量,例如BEGIN{FS=":";OFS="---"}==awk命令格式:
awk 'pattern' filename                        示例:awk -F: '/root/' /etc/passwd
awk '{action}' filename                       示例:awk -F: '{print $1}' /etc/passwd
awk 'pattern {action}' filename           示例:awk -F: '/root/{print $1,$3}' /etc/passwd       示例:awk 'BEGIN{FS=":"} /root/{print $1,$3}' /etc/passwd
command |awk 'pattern {action}'      示例:df -P| grep  '/' |awk '$4 > 25000 {print $4}'awk工作原理
awk -F":" '{print $1,$3}' /etc/passwd
(1)awk使用一行作为输入,并将这一行赋给变量$0,每一行可称作为一个记录,以换行符结束
(2)然后,行被:分解成字段,每个字段存储在已编号的变量中,从$1开始
(3)awk如何知道空格来分隔字段的呢?因为有一个内部变量FS来确定字段分隔符,初始时,FS赋为空格或者是tab
(4)awk打印字段时,将以设置的方法,使用print函数打印,awk在打印的字段间加上空格,因为$1,$3间有一个,逗号。逗号比较特殊,映射为另一个变量,成为输出字段分隔符OFS,OFS默认为空格
(5)awk打印字段时,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程持续到处理文件结束。
awk中的特殊变量:- NR: 表示记录编号, 当awk将行为记录时, 该变量相当于当前行号
- NF: 表示字段数量, 当awk将行为记录时, 该变量相当于当前列号
- $0: 表示当前记录的文本内容
- $1: 表示当前记录的第一列文本内容
- $2: 表示当前记录的第二列文本内容RS(输入记录分隔符)        (record sign) The input record separator, by default a newline.FS(输入字段分隔符)        (filed sign)NR(Number of record)行数FNR按不同的文件飞开      ORS(输出记录分隔符)       (output frecord sign)The output record separator, by default a newline. OFS(输出字段分隔符)       (output filed sign)NF 字段个数              (Number of filed)FS(输入字段分隔符) (filed sign)FS(输入字段分隔符) (filed sign)awk -F':' '{print $1}' pass
awk  'BEGIN{FS=":"} {print $1}' passOFS(输出字段分隔符)    (output filed sign)
awk  'BEGIN{FS=":";OFS="===="} {print $1,$2}' passNR   表示记录编号, 当awk将行为记录时, 该变量相当于当前行号
awk  '{print NR,$0}' pass
awk 'NR==3{print $0}' pass                   FNR  表示记录编号, 当awk将行为记录时, 该变量相当于当前行号(不同文件分开)
awk  '{print FNR,$0}' pass aa.txtRS(输入记录分隔符)
awk  'BEGIN{RS=":"} {print NR,$0}' passORS(输出记录分隔符)
awk  'BEGIN{RS=":";ORS="~~"} {print NR,$0}' pass    [root@host ~]# awk 'BEGIN{FS=":"} {print $1}' /etc/passwdrootbindaemonadmlpsyncshutdownhaltmailoperatorgamesOFS(输出字段分隔符)    (output filed sign)[root@host ~]# awk 'BEGIN{FS=":";OFS=".."} {print $1,$2}' /etc/passwdroot..xbin..xdaemon..xadm..xlp..xsync..xshutdown..xNR   表示记录编号, 当awk将行为记录时, 该变量相当于当前行号[root@host ~]# awk -F: '{print NR,$0}' a.txt file1.txt 1 love2 love.3 loove4 looooove5 6 isuo7 IPADDR=192.168.6.58 hjahj1239 GATEWAY=192.168.1.110 NETMASK=255.255.255.011 DNS=114.114.114.114FNR  表示记录编号, 当awk将行为记录时, 该变量相当于当前行号(不同文件分开)[root@host ~]# awk -F: '{print FNR,$0}' a.txt file1.txt 1 love2 love.3 loove4 looooove5 1 isuo2 IPADDR=192.168.6.53 hjahj1234 GATEWAY=192.168.1.15 NETMASK=255.255.255.06 DNS=114.114.114.114RS(输入记录分隔符)       [root@master ~]# cat passwd root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologin[root@master ~]# awk -F: 'BEGIN{RS="bash"} {print $0}' passwd root:x:0:0:root:/root:/bin/bin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinORS(输出记录分隔符)[root@master ~]# cat passwd root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologin[root@master ~]# awk -F: 'BEGIN{ORS=" "} {print $0}' passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin练习:将文件合并为一行[root@master ~]# awk 'BEGIN{ORS="" } {print $0}' /etc/passwd练习:把一行内容分为多行[root@master ~]# cat d.txt root:x:0:0:root:/root:/bin/bash[root@master ~]# awk 'BEGIN{RS=":"} {print $0}' d.txt rootx00root/root/bin/bashawk实用理解案例:1. 打印一个文件中的第2列和第3列$ awk '{ print $2, $3}' filename
2. 打印指定行指定列的某个字符$ awk -F: 'NR==3{ print $7 }' /etc/passwd
3. 统计一个文件的行数$ awk '{ print NR}' filename
4. 在脚本中, 传递变量到awk中$ var=1000$ echo | awk -v VARIABLE=$var '{ print VARIABLE }'5. 指定字段分隔符-F活在BEGIN{ FS=":" }$ awk -F: '{ print $2, $3 }' filename$ awk 'BEGIN{ FS=":" }{ print $2, $3 }' filename
6. 在awk中使用for循环$ grep '05/Sep/2017' cd.mobiletrain.org.log | awk '{ ips[$1]++ } END {for (i in ips){print i,ips[i]}}' | sort -k2 -rn | head -n10 182.140.217.111 138121.12.22.33 10010.19.3.2 9023.29.112.23 80121.31.30.189 45187.23.43.123 40
7. 在awk中使用if条件判断$ awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd统计系统用户$ awk -F":" '{if($3>0 && $3<1000){i++}} END{print i}' /etc/passwd

脚本大全:

【脚本1】  批量建立用户
编写shell脚本,批量建立用户user_00, user_01, ... user_100并且所有用户同属于users组:
[root@master ~]# vim user.sh
#!/bin/bash
group=`cat /etc/group |grep -o users`
if [ $group == "users" ]
thenfor i in `seq 0 100`doif [ $i -lt 10 ]thenuseradd -g users user_0$ielseuseradd -g users user_$ifidone
elseecho "users group not found!"exit 1
fi[root@master ~]# sh user.sh
[root@master ~]# ls /home/
Display all 102 possibilities? (y or n)
tom/      user_11/  user_24/  user_37/  user_50/  user_63/  user_76/  user_89/
user_00/  user_12/  user_25/  user_38/  user_51/  user_64/  user_77/  user_90/
user_01/  user_13/  user_26/  user_39/  user_52/  user_65/  user_78/  user_91/
user_02/  user_14/  user_27/  user_40/  user_53/  user_66/  user_79/  user_92/
user_03/  user_15/  user_28/  user_41/  user_54/  user_67/  user_80/  user_93/
user_04/  user_16/  user_29/  user_42/  user_55/  user_68/  user_81/  user_94/
user_05/  user_17/  user_30/  user_43/  user_56/  user_69/  user_82/  user_95/
user_06/  user_18/  user_31/  user_44/  user_57/  user_70/  user_83/  user_96/
user_07/  user_19/  user_32/  user_45/  user_58/  user_71/  user_84/  user_97/
user_08/  user_20/  user_33/  user_46/  user_59/  user_72/  user_85/  user_98/
user_09/  user_21/  user_34/  user_47/  user_60/  user_73/  user_86/  user_99/
user_10/  user_22/  user_35/  user_48/  user_61/  user_74/  user_87/
user_100/ user_23/  user_36/  user_49/  user_62/  user_75/  user_88/  删除以上脚本批量添加的用户:
[root@master ~]# vim user1.sh
#!/bin/bash
for i in `seq 0 100`
doif [ $i -lt 10 ]thenuserdel -r user_0$ielseuserdel -r user_$ifi
done
[root@master ~]# sh user1.sh
[root@master ~]# ls /home/
tom后面的脚本就自己多动手实验吧:需要注意有些地方需要修改哦!!!!!!【脚本2】每日生成一个文件
要求:请按照这样的日期格式(xxxx-xx-xx)每日生成一个文件,例如今天生成的文件为)2017-07-05.log, 并且把磁盘的使用情况写到到这个文件中,(不用考虑cron,仅仅写脚本即可)
[root@master ~]# vim file.sh
#!/bin/bash
fileName=`date +%F`      #这里格式为输入时间年月日时分,f代表每日
c=`df -h`
echo "$c" > /root/$fileName.log【脚本3】统计内存使用
写一个脚本计算一下linux系统所有进程占用内存大小的和。实现代码:
[root@master ~]# vim free.sh
#!/bin/bash
count=0
# 这个循环会遍历出每个进程占用的内存大小
for i in `ps aux |awk '{print $6}' |grep -v 'RSS'`
do# 将遍历出来的数字进行累加count=$[$count+$i]
done
# 就得到所有进程占用内存大小的和了
echo "$count/kb"[root@master ~]# sh free.sh
759524/kb【脚本4】简单的监控脚本
设计一个简单的脚本,监控远程的一台机器(假设ip为192.168.229.61)的存活状态,当发现宕机时发一封邮件给你自己。#!/bin/bash
ip="192.168.229.61"
email="user@example"while 1
doping -c10 $ip > /dev/null 2>/dev/nullif [ $? != "0" ]then# 调用一个用于发邮件的脚本python /usr/local/sbin/mail.py $email "$ip down" "$ip is down"fisleep 30
done【脚本5】简单的监控脚本
需求:
写一个脚本,判断本机的80端口(假如服务为httpd)是否开启着,如果开启着什么都不做,如果发现端口不存在,那么重启一下httpd服务,并发邮件通知你自己。脚本写好后,可以每一分钟执行一次,也可以写一个死循环的脚本,30s检测一次。
发邮件的脚本参考【脚本11】的示例代码。
代码:#!/bin/bash
email="user@example.com"
if netstat -lntp |grep ':80' |grep 'httpd'
thenecho "80 port no problem"exit
else/usr/local/apache2.4/bin/apachectl restartpython mail.py $email "check_80port" "The 80 port is down."n=`ps aux |grep httpd|grep -cv grep`if [ $n -eq 0 ]then/usr/local/apache2/bin/apachectl start 2>/tmp/apache_start.errfiif [ -s /tmp/apache_start.err ]thenpython mail.py  $mail 'apache_start_error' `cat /tmp/apache_start.err`fi
fi【脚本6】备份数据库
需求:设计一个shell脚本来备份数据库,首先在本地服务器上保存一份数据,然后再远程拷贝一份,本地保存一周的数据,远程保存一个月。假定,我们知道mysql root账号的密码,要备份的库为discuz,本地备份目录为/bak/mysql, 远程服务器ip为192.168.229.61,远程提供了一个rsync服务,备份的地址是 192.168.229.61::backup . 写完脚本后,需要加入到cron中,每天凌晨3点执行。
脚本代码:#!/bin/bash
PATH=$PATHi:/usr/local/mysql/bin
week=`date +%w`
today=`date +d`
passwd="123456"
backdir="/data/mysql"
r_backupIP="192.168.123.30::backup"exec 1>/var/log/mysqlbak.log 2>/var/log/mysqlbak.log
echo "mysql backup begin at `date +%F %T`."# 本地备份
mysqldump -uroot -p$passwd --default-character-set=utf8 discuz >$backdir/$week.sql
# 同步备份到远程机器
rsync -az $backdir/$week.sql $r_backupIP/$today.sqlecho "mysql backup end at `date +%F %T`."
然后加入cron
0 3 * * * /bin/bash /usr/local/sbin/mysqlbak.sh【脚本7】自动重启php-fpm服务
服务器上跑的是LNMP环境,近期总是有502现象。502为网站访问的状态码,200正常,502错误是nginx最为普通的错误状态码。由于502只是暂时的,并且只要一重启php-fpm服务则502消失,但不重启的话,则会一直持续很长时间。所以有必要写一个监控脚本,监控访问日志的状态码,一旦发生502,则自动重启一下php-fpm。我们设定:access_log /data/log/access.log
脚本死循环,每10s检测一次(假设每10s钟的日志条数为300左右)
重启php-fpm的方法是 /etc/init.d/php-fpm restart
脚本代码:#!/bin/bash
access_log="/data/log/access.log"
N=10
while :
do# 因为10秒大概产生300条日志记录tail -n300 $access_log > /tmp/log# 拿出log中包含502的日志行数n_502=`grep -c "502" /tmp/log`# 如果行数大于10if [ $n_502 -ge $N ]then# 就记录一下系统状态top -bn1 > /tmp/`date +%H%M%S`-top.logvmstat 1 5 > /tmp/`date +%H%M%S`-vm.log# 然后才重启服务,并把错误信息重定向/etc/init.d/php-fpm restart 2> /dev/null# 重启php-fpm服务后,应先暂缓1分钟,而后继续每隔10s检测一次sleep(60)fisleep(10)
done【脚本8】监控mysql服务
假设,当前MySQL服务的root密码为123456,写脚本检测MySQL服务是否正常(比如,可以正常进入mysql执行show processlist),并检测一下当前的MySQL服务是主还是从,如果是从,请判断它的主从服务是否异常。如果是主,则不需要做什么。实现代码:#!/bin/bash
Mysql_c="mysql -uroot -p123456"
$Mysql_c -e "show processlist" >/tmp/mysql_pro.log 2>/tmp/mysql_log.err
n=`wc -l /tmp/mysql_log.err|awk '{print $1}'`if [ $n -gt 0 ]
thenecho "mysql service sth wrong."
else$Mysql_c -e "show slave status\G" >/tmp/mysql_s.logn1=`wc -l /tmp/mysql_s.log|awk '{print $1}'`if [ $n1 -gt 0 ]theny1=`grep 'Slave_IO_Running:' /tmp/mysql_s.log|awk -F : '{print $2}'|sed 's/ //g'`y2=`grep 'Slave_SQL_Running:' /tmp/mysql_s.log|awk -F : '{print $2}'|sed 's/ //g'`if [ $y1 == "Yes" ] && [ $y2 == "Yes" ]thenecho "slave status good."elseecho "slave down."fifi
fi【脚本9】抽签脚本
1、写一个脚本执行后,输入名字,产生随机数01-99之间的数字。
2、如果相同的名字重复输入,抓到的数字还是第一次抓取的结果,
3、前面已经抓到的数字,下次不能在出现相同数字。
4、第一个输入名字后,屏幕输出信息,并将名字和数字记录到文件里,程序不能退出
继续等待别的学生输入。参考代码:while :
doread -p  "Please input a name:" nameif [ -f /work/test/1.log ];thenbb=`cat /work/test/1.log | awk -F: '{print $1}' | grep "$name"`if [ "$bb" != "$name" ];then  #名字不重复情况下aa=`echo $RANDOM | awk -F "" '{print $2 $3}'`while :dodd=`cat  /work/test/1.log |  awk -F: '{print $2}'  | grep "$aa"`if [ "$aa"  ==  "$dd" ];then   #数字已经存在情况下echo "数字已存在."aa=`echo $RANDOM | awk -F "" '{print $2 $3}'`elsebreakfidoneecho "$name:$aa" | tee -a /work/test/1.logelseaa=`cat /work/test/1.log |  grep "$name" | awk -F: '{print $2}'` #名字重复echo $aaecho "重复名字."fielseaa=`echo $RANDOM | awk -F "" '{print $2 $3}'`echo "$name:$aa" | tee -a  /work/test/1.logfi
done【脚本10】检查服务
先判断是否安装http和mysql,没有安装进行安装,安装了检查是否启动服务,若没有启动则需要启动服务。说明:操作系统为centos6,httpd和mysql全部为rpm包安装。参考代码:#!/bin/bashif_install()
{n=`rpm -qa|grep -cw "$1"`if [ $n -eq 0 ]thenecho "$1 not install."yum install -y $1elseecho "$1 installed."fi
}if_install httpd
if_install mysql-serverchk_ser()
{p_n=`ps -C "$1" --no-heading |wc -l`if [ $p_n -eq 0 ]thenecho "$1 not start."/etc/init.d/$1 startelseecho "$1 started."fi
}chk_httpd
chk_mysqld【脚本11】监控网卡
1.每10分钟检测一次指定网卡的流量
2.如果流量为0,则重启网卡参考代码:#!/bin/bashLANG=en
n1=`sar -n DEV 1 60 |grep eth0 |grep -i average|awk '{print $5}'|sed 's/\.//g'`
n2=`sar -n DEV 1 60 |grep eth0 |grep -i average|awk '{print $6}'|sed 's/\.//g'`
if [ $n1 == "000" ] && [ $n2 == "000" ]
thenifdown eth0ifup eth0
fi【脚本12】杀死进程
把当前用户下所有进程名字中含有”java”的进程关闭。
ps -u $USER |awk '$NF ~ /java/ {print $1}'|xargs kill【脚本13】监控节点
一个网站,使用了cdn,全国各地有几十个节点。需要你写一个shell脚本来监控各个节点是否正常。
假如:
监控的url为www.xxx.com/index.php
源站ip为88.88.88.88
参考代码:#!/bin/bash
url="www.xxx.com/index.php"
s_ip="88.88.88.88"
curl -x $s_ip:80 $url > /tmp/source.html 2>/dev/nullfor ip in `cat /tmp/ip.txt`
docurl -x $ip:80 $url 2>/dev/null >/tmp/$ip.html[ -f /tmp/$ip.diff ] && rm -f /tmp/$ip.difftouch /tmp/$ip.diffdiff /tmp/source.html /tmp/$ip.html > /tmp/$ip.diff 2>/dev/nulln=`wc -l /tmp/$ip.diff|awk '{print $1}'`if [ $n -lt 0 ]thenecho "node $ip sth wrong."fi
done【脚本14】监控cpu使用率
用shell写一个监控服务器cpu使用率的监控脚本。思路:用top -bn1 命令,取当前空闲cpu百份比值(只取整数部分),然后用100去剑这个数值。参考代码:#!/bin/bashwhile :
doidle=`top -bn1 |sed -n '3p' |awk '{print $5}'|cut -d . -f1`use=$[100-$idle]if [ $use -gt 90 ]then echo "cpu use percent too high."#发邮件省略fisleep 10
done【脚本15】自动增加公钥
写一个shell脚本,当我们执行时,提示要输入对方的ip和root密码,然后可以自动把本机的公钥增加到对方机器上,从而实现密钥认证。参考代码:#!/bin/bashread -p "Input IP: " ip
ping $ip -w 2 -c 2 >> /dev/null## 查看ip是否可用
while [ $? -ne 0 ]
doread -p "your ip may not useable, Please Input your IP: " ipping $ip -w 2 -c 2 >> /dev/null
done
read -p "Input root\'s password of this host: " password## 检查命令子函数check_ok() {if [ $? != 0 ]
thenecho "Error!."exit 1
fi
}## yum需要用到的包
myyum() {if ! rpm -qa |grep -q "$1"
thenyum install -y $1check_ok
elseecho $1  already installed
fi
}for p in openssh-clients openssh expect
domyyum $p
done## 在主机A上创建密钥对if [ ! -f ~/.ssh/id_rsa ] || [ ! -f ~/.ssh/id_rsa.pub ]
thenif [ -d ~/.ssh ]thenmv ~/.ssh/  ~/.ssh_oldfiecho -e "\n" | ssh-keygen -t rsa -P ''check_ok
fi## 传私钥给主机Bif [ ! -d /usr/local/sbin/rsync_keys ]
thenmkdir /usr/local/sbin/rsync_keys
fi
cd /usr/local/sbin/rsync_keys
if [ -f rsync.expect ]
thend=`date +%F-%T`mv rsync.expect $d.expect
fi#创建远程同步的expect文件cat >  rsync.expect <<EOF
#!/usr/bin/expect
set host [lindex \$argv 0]
#主机B的密码
set passwd [lindex \$argv 1]
spawn rsync -av /root/.ssh/id_rsa.pub root@\$host:/tmp/tmp.txt
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "\$passwd\r" }
}
expect eof
spawn ssh root@\$host
expect {
"password:" { send "\$passwd\r" }
}
expect "]*"
send "\[ -f /root/.ssh/authorized_keys \] && cat /tmp/tmp.txt >>/root/.ssh/authorized_keys \r"
expect "]*"
send "\[ -f /root/.ssh/authorized_keys \] || mkdir -p /root/.ssh/ \r"
send "\[ -f /root/.ssh/authorized_keys \] || mv /tmp/tmp.txt /root/.ssh/authorized_keys\r"
expect "]*"
send "chmod 700 /root/.ssh; chmod 600 /root/.ssh/authorized_keys\r"
expect "]*"
send "exit\r"
EOFcheck_ok
/usr/bin/expect /usr/local/sbin/rsync_keys/rsync.expect $ip $password
echo "OK,this script is successful. ssh $ip  to test it"

shell运维脚本实战

当各位读者掌握了前面的内容,那么久尝试一下下面的实战技巧技术吧!!!!!下面内容具有一定难度

• 实战项目1: sed实现网络配置
• 实战项目2: sed实现sshd配置
• 实战项目3: sed实现nginx配置
• 实战项目4: 关闭本机SELinux的功能
• 实战项目5: 在/etc/sudoers配置文件中添加内容
• 实战项目6: 将固定文件的内容添加到nginx配置文件
• 实战项目7: zabbix_agentd.conf配置文件修改
• 实战项目8: awk统计/etc/password各种shell数量
• 实战项目9: awk统计网站访问各种状态数量
• 实战项目10: awk统计当前访问的每个IP的数量
• 实战项目11: 统计Nginx日志中某一天的PV量
• 实战项目12: 获取获得内存使用情况
• 实战项目13: 基于时间戳的备份程序
• 实战项目14: 批量主机软件部署程序
• 实战项目15: Web日志访问量分析程序
• 实战项目16: 编写系统初始化脚本
• 实战项目17: LAMP终级部署
• 实战项目18: Linux系统状态收集及分析
• 实战项目19: Web访问日志全文分析

shell编程,实战高级进阶教学相关推荐

  1. shell编程实战之read函数基础

    shell编程实战 文章目录 shell编程实战 1.用法: 2.语法: 参数说明: 3.参数解读实例: 3.1 -a 参数 3.2 -d 3.3 -p 3.4 -n 3.5 -r 3.6 -s 3. ...

  2. 第13章代码《跟老男孩学习Linux运维:Shell编程实战》

    本书历史上已出版最实战的Shell高级编程实战书籍,没有之一,和市面书籍不同,本书是作者经过18年的运维工作及教学工作后,创新类企业级实战书籍,适合所有学习及从事Linux相关工作的读者. <跟 ...

  3. Shell编程实战范例

    前言: 本部分主要参考此博客: https://www.w3cschool.cn/shellbook/uglqdozt.html 数值运算: 进制转换: 其他进制转换为10进制, 可以使用Shell内 ...

  4. Linux Shell编程实战---以逆序形式打印行

    以逆序形式打印行 使用awk或tac可以搞定. tac这个命令的名称其实就是反过来书写的cat. (1).使用tac 该命令的语法如下: tac file1file2 - 它也可以从stdin中读取: ...

  5. Linux Shell 编程实战技巧

    目前,越来越多的企业应用会部署在 Linux 系统上的,而 Linux Shell 脚本可以极大地帮助我们完成这些应用的运维任务.这使得 Linux Shell 开发技能成为开发人员的一项重要的.有竞 ...

  6. Java并发编程实战(进阶篇 - 上)

    通过上一篇的学习我们就可以运用这些方法来构建线程安全的类,那么本篇我们会着重学习Java中的同步容器类.并发容器和框架.并发工具类.Executor 框架,看看这些并发类库或者框架是怎样实现的. 一. ...

  7. shell编程实战案列归纳

    1.shell脚本编写监控本机内存和硬盘剩余空间,剩余内存小于 500M.根分区剩余空间小于 1000M时,发送报警邮件给 root 管理员 #!/bin/bash #提取根分区剩余空间 size=$ ...

  8. 一道企业shell编程实战题-看看谁能快速搞定

    问题如下: 已知老男孩教育于2015年5月21日发布了如下最新运维经典课程, http://edu.51cto.com/course/course_id-839.html   要求:把课程地址里的所有 ...

  9. python高级教程_Python高级进阶教程

    这个系列的教程是在刘金玉编程的<零基础python教程>基础上的高级进阶应用. 教程列表: Python高级进阶教程001期 pycharm+anaconda3+pyqt5可视化界面开发环 ...

最新文章

  1. 暑期集训1:C++STL 例2:UVA-10935
  2. 公司网络推广浅析网站想要“久居”首页的方法有哪些?
  3. MySQL获取Schema表名和字段信息
  4. 从烤箱到蒸烤箱、到蒸烤箱集成灶,功能做加法,价格做乘法
  5. 裸奔浏览器_【大数据早报】上网=“裸奔”?单凭浏览器历史记录就能锁定身份...
  6. java定义一个getsize方法,long getSize()
  7. sqlserver sa
  8. CodeForces - 1422E Minlexes(dp+字符串)
  9. 对代理商的评价怎么写_简历中的自我评价怎么写才能更吸引人?
  10. 2 s锁是什么_《演员请就位》:一场戏拿了2张S卡,任敏凭什么打败老戏骨?
  11. aptana 代码折行
  12. 安卓手机用久了会卡顿,那么到底应该删掉手机里的哪些东西?
  13. 可计算行与计算复杂性多带图灵机实例
  14. Length of Last Word
  15. Ubuntu20.04安装WPS
  16. PB的特点及Powerscript的语言基础
  17. 关于对比型数据与分布型数据的图表可视化
  18. 使用代理ccproxy设置outlook2013 收QQ邮箱(IMAP-SMTP方式)
  19. 网吧无盘服务器2021,云更新无盘客户端
  20. 苹果官方付费升级内存_趁双十一大促销,赶紧升级苹果一体机升级SSD固态和液态内存吧...

热门文章

  1. 细说ASCII、GB2312/GBK/GB18030、Unicode、UTF-8/UTF-16/UTF-32编码
  2. 【超级无敌详细的黑马前端笔记!即时更新~】
  3. python实现图形旋转_python实现旋转和水平翻转的方法
  4. HTML中列表、表格与媒体元素
  5. cmd命令行返回上一级目录、切换到其他的盘、看一下该目录都有什么文件、打开该目录的某文件、改变命令颜色、快速进入某文件目录的方法
  6. table()函数用法
  7. 鼠标中键失灵可以怎么解决
  8. ntdll.dll故障(资源管理器无法打开)
  9. 华为畅享10plus搭在s鸿蒙系统,华为畅享10 Plus 好看又好用,这是真的香
  10. android7.12新功能,安卓7.0值得注意的新功能 新增分屏和更合理的通知栏