Shell编程课堂笔记
目录
Shell编程课堂笔记.............................................................................................................................................. 1
shell编程第一天.................................................................................................................................................... 3
一.为什么要学习Shell编程..................................................................................................................... 3
二.什么是shell.............................................................................................................................................. 4
三.什么是Shell脚本................................................................................................................................... 4
四.脚本语言的种类..................................................................................................................................... 6
五.shell脚本的执行..................................................................................................................................... 8
六.shell脚本开发级别规范及习惯......................................................................................................... 8
Shell编程第二天................................................................................................................................................... 9
一. bash shell特性...................................................................................................................................... 9
二. 变量常见类型........................................................................................................................................ 9
三. 变量赋值方式..................................................................................................................................... 11
四. 变量数值运算..................................................................................................................................... 12
shell编程第三天................................................................................................................................................. 14
一.shell条件测试....................................................................................................................................... 14
shell编程第四天........................................................................................................................................ 21
二.shell流程控制....................................................................................................................................... 21
四.实例.安装nginx.................................................................................................................................... 22
五. 根据不同的系统安装不同的yum源.......................................................................................... 23
六. 安装不同版本的PHP....................................................................................................................... 24
七. 流程控制语句case........................................................................................................................... 25
八. 实现简单的JumpServer................................................................................................................. 27
九. 使用case实现多级菜单................................................................................................................. 29
十. expect进行参数传递,执行命令或其他操作......................................................................... 30
十一. 批量获取在线主机, 进行秘钥批量分发............................................................................... 30
Shell编程第五天................................................................................................................................................. 33
一.for循环语句.......................................................................................................................................... 34
二. while循环语句.................................................................................................................................... 35
三. 监控网站,每隔10秒确定一次网站是否正常...................................................................... 36
四. Shell内置命令..................................................................................................................................... 37
shell编程第六天................................................................................................................................................. 37
一. 回顾........................................................................................................................................................ 37
二. shell脚本之函数................................................................................................................................. 38
三. 函数变量作用域................................................................................................................................. 40
四. wgret命令参数,curl命令参数....................................................................................................... 40
shell编程第七天................................................................................................................................................. 41
一. shell数组应用...................................................................................................................................... 41
shell编程第八天................................................................................................................................................. 45
一.shell正则应用....................................................................................................................................... 45
二. 基础正则表达式................................................................................................................................. 46
三. 扩展正则表达式................................................................................................................................. 47
四. 正则表达式实战................................................................................................................................. 47
五. sed文本处理........................................................................................................................................ 48
六. sed匹配替换........................................................................................................................................ 51
七. awk文本处理....................................................................................................................................... 52
八. awk工作原理....................................................................................................................................... 53
九. awk模式动作....................................................................................................................................... 55
十. awk条件表达式.................................................................................................................................. 56
十一. 运算表达式..................................................................................................................................... 56
十二. 逻辑操作符和复合模式.............................................................................................................. 56
十三. Awk条件判断................................................................................................................................. 57
十四. awk 循环语句................................................................................................................................. 58
十五. awk数组实战.................................................................................................................................. 58
十六. Awk数组案例................................................................................................................................. 59
shell编程第一天
一.为什么要学习Shell编程
1.Shell脚本语言是实现linux/unix系统管理及自动化运维重要且必备的工具,linux/unix系统的底层及基础应用软件的核心大都涉及shell脚本内容.每一个合格的linux系统管理员或运维工程师,都需要熟练shell脚本语言的编写,并能够阅读系统及各类软件附带的shell脚本内容,只有这样才能提升运维人员的工作效率,适应日益复杂的工作环境,减少不必要的重复工作,从而为个人的职场发展奠定较好的基础 2.学好shell编程所需的基础知识 学好shell编程并设想轻松地通过shell脚本自动化管理企业生产系统的必备基础如下: (1)对vim编辑器能熟练使用,熟练SSH终端机”.vimrc”等的配置 (2)要有一定的linux命令基础,至少掌握80个以上linux常用命令并能熟练使用 (3)要熟练掌握linux正则表达式以及三剑客命令(grep ,sed,awk) (4)熟悉常见的linux网络服务部署,优化,日志分析及排错 精简系统启动服务的方法 (1)setup (2)ntsysv (3)脚本 #!/bin/bash for srv in `chkconfig --list|grep “3:on”|awk ‘{print $1}’` do chkconfig $srv off done for srv in crond network sshd rsyslog do chkconfig $srv on done or for Srv in `chkconfig --list | grep "3:on" | awk ‘{print $1}‘ | grep -vE "crond|network|sshd|rsyslog"` do chkconfig $Srv off done 3 如何才能学好Shell编程 学好Shell编程的核心:多练→多思考→再练→再思考,坚持如此循环即可! 学习的来源: 1、耳朵 2、眼睛 3、手 4、大脑 5、总结 (1)掌握Shell脚本的基本语法方法 (2)掌握Shell脚本的各种常见语法 (3)形成自己的脚本开发风格 (4)从简单做起,简单判断,简单循环 (5)多模仿、多离开参考资料练习、多思考 (6)学会分析问题,逐渐形成编程思维 (7)编程变量名字规范,采用驼峰语法表示 (8)不要拿来主义,特别针对新手 |
二.什么是shell
Shell是一个命令解释权,它的作用是介绍执行用户输入的命令及程序等,用户诗人一天命令,shell就解释执行一条.这种从键盘一输入命令,就可以立即回应的对话方式,备称为较好的方式 Shell存在于操作系统的最外层,负载直接与用户对话,把用户的输入介绍给操作系统,并基础各种各样的操作系统的输出结果,输出到屏幕返回给用户,当我们输入系统用户名和密码,登录到linux后的所有操作都由shell解释并执行 |
三.什么是Shell脚本
系统目录的堆积 特定的格式+特定的语法+系统的命令=文件 范例1:清除/var/log下messages日志文件的简单命令脚本 把所有命令放在一个文件里堆积起来就形成脚本,下面就是一个由最简单的命令堆积而成的shell脚本.要注意的是,得使用root身份来运行 #清除日志脚本 cd /varlog cat /devnull >messages echo “logs cleaned up” 提示: /varlog/messages是linux系统日志文件很重要. 这个脚本其实是有一些问题的,读者有没有看出来?它所在的问题如下: (1)如果不是root用户,就无法执行脚本清理日志,并且会提示系统权限报错. (2)没有任何流程控制语句,简单地说就是只顺序操作,没有成功判断和逻辑严密性. 范列2:写一个包含命令,变量和流程控制语句的清除/var/log下messages日志文件的shell脚本. #/bin/bash #清除日志脚本 LOG_DIR=/varlog #$uid为0的用户,即root用户 ROOT_UID=0 #脚本需要使用root用户来运行,因此,对当前用户进行判断,不合要求的给出友好提示,并终止程序运行。 if [ "$UID" -ne "$ROOT_UID" ] #如果当前用户不是root,不允许执行脚本。 then echo "Must be root to run this script." #给出提示后退出。 exit 1 #<==退出脚本。 fi #如果切换到指定目录不成功,给出提示,并终止程序运行。 cd $LOG_DIR || { echo "Cannot change to necessary directory." exit 1 } #经过上述两个判断后,此处的用户权限和路径就应该是对的,只有清空成功,才打印成功提示. cat /dev/null>messages && { echo "Logs cleaned up." exit 0 #退出之前返回0表示成功. 返回1表示失败。 } echo "Logs cleaned up fail." exit 1 初学者如果想快速掌握shell脚本的编写方法,最有效的思路就是采用电子游戏中过关的方式,比如范列2的脚本可以分成如下几关来设计: 第一关,必须是root才能执行脚本,否则给出友好提示并终止脚本运行. 第二关,成功切换目录(cd /var/log),否则给出友好提示并终止脚本运行. 第三关,清理日志( cat /dev/null >messages),清理成功给出正确提示. 第四关,通关或失败,给出相应提升(echo输出). Shell脚本在linux运维工作中的地位 Shell脚本语言很擅长处理纯文本类型的数据,而linux系统中几乎所有的配置文件,日志文件(如NFS,Rsyanc,Httpd,Nginx,LVS,MySQL),以及绝大多数的启动文件读书纯文本类型的文件.自然学好shell脚本语言,就可以利用它在linux系统中发货巨大的作用. 1.自动化的完成基础配置 系统初始化操作,系统更新,内存调整,网络时区,SSH优化 2.自动化安装程序 LNMP,LAMP,MySQL,Nginx,Redis 3自动化调整配置文件 nginx.conf . my.cnf 4.自动化部署业务 部署php,java秒级回退 5.自动化定期备份恢复 MySQL全备 + 增量 + binlog + crond + shell脚本 6.自动化信息的采集 Zabbix + shell:硬件,系统,服务,网络,等等 7.自动化日志分析 ELK 取值->排序->去重->统计->分析 8.自动化扩容/缩容 Zabbix + shell -扩容:监控服务器cup,如cpu负载持续80%+ 触发动作(脚本) -脚本: 调用api开通云主机->初始化环境->加入集群->对外提供 -缩容: 监控服务器CUP使用率20%->判断有多高wed节点->判断是否超过预设->缩减到对应的预设状态->变更负载配置 |
四.脚本语言的种类
1.shell脚本语言的种类 [root@oldboy ~]# cat /etc/shells /bin/sh /bin/bash /sbin/nologin /bin/dash /bin/tcsh /bin/csh bash特点: 命令补全: tab 命令别名: alias unalias 命令修改 命令历史:history 问题:history查看命令历史时,可以带上时间戳么? 答: export HISTTIMEFORMAT="%F %T `whoami` history
Linux系统中的主流shell是bash,bash是由bourne shell(sh)发展而来,单bash还包含了csh和ksh的特色. 2.其他常用的脚本语言种类 (1)PHP语言 PHP是网页程序语言.也是脚本语言.它是一款更专注于web页面开发(前端展示)的语言. 例如:wordpress,dedecms,discus等著名开源产品都是用PHP语言开发的 (2)Perl语言 Perl脚本语言,比shell脚本语言强大很多,在2010年以前很流行,它的语法灵活,复杂,在实现不同的功能时可以用多种不同的方式,缺点是不易读,团队协作困难. (3)Python语言 Python是近几年非常流行的语言,它不但可以用于脚本程序开发,也可以实现web页面程序开发(例如:openstack,saltsack都是Python语言开发的),游戏开发.大数据开发.移动端开发 (4)GO语言 Go语言是谷歌推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。 Go 同时具有两种编译器,一种是建立在GCC基础上的Gccgo,另外一种是分别针对64位x64和32位x86计算机的一套编译器(6g和8g)。谷歌目前正在研发其对ARM芯片和Android设备的支持。 3.shell脚本语言与PHP/perl/Python语言的区别和优势 Shell脚本语言的优势在于处理偏操作系统底层的业务. 例如:linux系统内部的很多应用,(有的是应用的一部分)都是使用shell脚本语言开发的,因为有1000多个linux系统命令为他做支撑.特别是linux正则表达式及三剑客 grep awk sed 等命令..
对于一些常见的系统脚本,使用shell开发会更简单快速, 例如:让软件一键自动化安装,优化,监控报警脚本,软件启动脚本,日志分析脚本,虽然PHP/Python语言也能够做到,但是考虑到掌握难度,开发效率,开发习惯等,他们可能就不如用shell脚本语言流行及有优势.对于一些常规的业务应用,使用shell更符合linux运维简单,易用,高效的三大基本原则
PHP语言的优势在于小型网站系统和开发;Python语言的优势在于开发较复杂的运维工具软件,,web界面的管理工具和web业务的开发.(例如:CMDB自动化运维平台,跳板机,批量管理软件saltstack.云计算openstack软件)等.我们开发一个应用根据业务需求结合不同语言优势及自身擅长的语言来选择,扬长避短,从而达到高效开发及一样自身维护等目的. 面向过程: shell 创建一台电脑 面向对象:Python组装一台电脑 4.常用操作系统默认的是shell 通过以下两种方法可以查看CentOS linux系统默认的shell 方法1: [root@oldboy ~]# echo $SHELL /bin/bash 方法2: [root@oldboy ~]# grep root /etc/passwd root:x:0:0:root:/root:/bin/bash 提示:结尾的/bin/bash就是用户登录后的Shell解释器。 5.shell脚本的规范 (1)脚本放在统一目录 mkdir -p /server/seripts (2)推荐使用vim编辑器编辑脚本 (3)以.sh为扩展名 (4)规范的shell脚本第一行会支持由那个程序(解释器)来执行脚本中的内容 #!/bin/bash 或 #!/bin/sh (5)开头的’#!’称为幻数,在执行shell脚本的时候,内核会根据”#!”后的解释器来确定用那个程序解释脚本中的内容. 注意:这一行必须在每个脚本顶端的第一行,如果不是第一行则为脚本注释行 (6)脚本注释 在shell脚本中,跟在#后面的内容表示注释.注释部署不会被执行.仅给人看.注释可以自成一行,也可以跟在命令后面,与命令同行.要养成写注释的习惯,方便自己与他人 最好不用中文注释,因为在不同字符集的系统中会出现乱码 (7)CMD CMD是command的缩写.即命令提示符(CMD),是在OS / 2 , Windows CE与Windows NT平台为基础的操作系统(包括Windows 2000和XP中, Vista中,和Server 2003 )下的“MS-DOS 方式”。中文版Windows XP 中的命令提示符进一步提高了与DOS 下操作命令的兼容性,用户可以在命令提示符直接输入中文调用文件。 在9x系统下输入command就可以打开命令行.而在NT系统上可以输入cmd来打开,在windows2000后被cmd替代,利用CMD命令查询系统的信息或者是判断网络的好坏 |
五.shell脚本的执行
Shell脚本是从上至下,从左至右依次执行每一行的命令及语句,即执行完了一个命令后再执行下一个命令,如果在shell脚本中遇到子脚本(即:脚本嵌套)时,就会先执行子脚本的内容,完成后再返回父脚本继续执行父脚本内的后续命令及语句. 通常情况下,当shell脚本执行时,会向系统内核请求启动一个新的进程,以便在该进程中执行脚本命令以及子shell脚本. Shell脚本的执行通常可以采用以下几种方式: (1):bash script-name或sh (2):path/script-name或./script-name (必须要有执行权限) (3):source script-name或.将脚本里的代码调入到当前环境运行 (4):cat script-name |bash (5):bash < script-name |
六.shell脚本开发级别规范及习惯
Shell脚本开发规范习惯非常重要,虽然这些规范部署必须要遵守的,但有了好的规范和习惯,可以大大提升开发效率,并降低后期对于脚本的维护成本.当多人协作开发时,大家有一个互相遵守的规范就显得更重要.哪怕是一个人开发,最好也采取一套固定的规范,这样脚本更易读,易于后期维护,最主要的是要让自己养成一个一出手就是专业和规范习惯. 注意: (1)登录shell /etc/profile是登录shell启动后运行的第一个启动脚本 它只为登录shell运行;非登入shelll不会引发这个脚本 登入shell加载启动脚本的顺序为: /etc/profile → /etc/profile.d → .bash_profile → .bashrc → /etc/bashrc 每个调用的脚本会依次撤销前一个调用脚本中的改变 在退出登入shell时,我们还可以执行某些任务,如创建自动备份,清除临时文件 把这些任务放在.bash_logout文件中 (2)非登录shell 非登入shell加载启动脚本顺序: .bash → /etc/bashrc → /etc/profile.d |
Shell编程第二天
一. bash shell特性
1.命令补全和文件路径补全,如果写错无法补全. table 2.命令历史记录功能 history 3.命令别名功能 alias unalias 4.常用快捷键 Ctrl+u,k,a,e,l,c,z,d,w,r,y, 5.前后台作业控制 bg, fg, jobs, screen 6.输入输出重定向 > ,>> ,2> ,2>> ,&> ,cat < 7.管道 | 8.命令排序 ; 没有逻辑关系,无论分号前面的命令执行是否成功都执行后者 && 前面执行成功,则执行后者 || 前面执行不成功,则执行后者 rpm -a mysql &>/devnull && echo “已安装” || echo “未安装” 9.shell通配符 * 匹配任意多个字符 ? 匹配任意一个字符 [ ]匹配括号中任意一个字符 a-z, 0-9, A-Z ( )在子shell中执行(cd /boot;ls) (umask 077; touch file1000) { }集合 touch file{1..100} \ 转义符 10.echo输出颜色,printf 格式化输出文件 echo -e “\033[30m 黑色字 \033[0m” echo -e "\033[31m 红色字 \033[0m" echo -e “\033[32m 绿色字 \033[0m” echo -e "\033[33m 黄色字 \033[0m" echo -e "\033[34m 蓝色字 \033[0m" echo -e "\033[35m 紫色字 \033[0m" echo -e "\033[36m 天蓝字 \033[0m" echo -e "\033[37m 白色字 \033[0m" |
二. 变量常见类型
变量说明:用一个固定的字符串去表示不固定的内容 变量 常量 Shell变量如下几类分为 (1)自定义变量 (2)系统环境变量 (3)位置参数变量 (4)预先定义变量 1.自定义变量 变量名=变量值, 步允许数字命名, 不能使用-命名 默认只在当前环境生效 使用export可以在当前用户的所有环境中生效 将export定义变量写入/etc/bashrc,对所有用户永久生效 将export定义变量写入 .bashrc,支队该用户永久生效 (1)引用变量 $变量名 或 ${变量名} (2)查看变量 echo $变量名 set 显示所有变量,包括自定义变量和环境变量 (3)取消变量 unset 变量名 作用范围:仅在当前shell中有效 2.系统环境变量 (1)定义环境变量`export export 变量,将自定义变量转换成环境变量` (2)引用环境变量`$变量名 或 ${变量名}` (3)查看环境变量`echo $变量名 env |grep Name` (4)取消环境变量`unset 变量名` (5)变量作用范围`在当前shell和子shell有效 3.位置参数变量 脚本参数传参: $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} 4.预先定义变量 $0脚本文件名 $* 所有的参数 “$*”显示会不同 $@所有的参数 $# 参数的个数 $$ 当前进程的PID $! 上一个后天进程的PID $? 上一个命令的返回值 0 表示成功 例子: #1.判断用户是否为root if [ $UID -eq 0 ];then echo “continue” else echo “please change user” root exit fi #2.判断软件包是否安装 rpm -q $1 &>/dev/null if [ $? -eq 0 ];then echo “package $1 installed” else echo “package $1 not installed” fi ping $1 -c2 -f &> /dev/null if [ $? -eq 0 ];then echo "$1 up" else echo "$1 down" fi |
三. 变量赋值方式
1.显示赋值(变量名=变量值) 例: ip1=192.168.56.11 school="Oldboyedu" today1=`date +%F` today2=$(date +%F) //例:取根分区使用百分比 [root@oldgirl 02 12:16:28]# df -h|grep /$ | awk ‘{print $5}‘ 2% [root@oldgirl 02 12:17:27]# df -h| awk ‘NR==2{print $5}‘ 2% [root@oldgirl 02 12:19:02]# echo `df -h| awk ‘NR==2{print $5}‘` 2% [root@oldgirl 02 12:19:21]# echo $(df -h| awk ‘NR==2{print $5}‘) 2% 2.read从键盘读入变量值 read -p “提示信息:” 变量名 read -t 5 -p "提示信息: " 变量名 [root@oldgirl 02 12:32:33]# read -p "input username,password: " User Pass input username,password: aaa 123 [root@oldgirl 02 12:33:12]# echo $User aaa [root@oldgirl 02 12:33:18]# echo $Pass 123 3.注意事项: 定义或引用变量时注意事项: " "弱引用,‘ ‘强引用 [root@shell ~]# school=Iphone [root@shell ~]# echo "${school} is good" Iphone is good [root@shell ~]# echo ‘${school} is good‘ ${school} is good 4.``命令替换等价于 $()反引号中的shell命令会被先执行 [root@shell ~]# touch `date +%F`_file1.txt [root@shell ~]# touch $(date +%F)_file2.txt [root@shell ~]# Root_Partition_Usage=$(df -Ph |grep ‘/$‘ |awk ‘{print $5}‘) [root@shell ~]# Root_Partition_Usage=`df -Ph |grep ‘/$‘ |awk ‘{print $5}‘`
|
四. 变量数值运算
1.从前往后输出变量内容 [root@shell ~]# url=www.sina.com.cn //获取变量值的长度 [root@shell ~]# echo ${#url}
//从前往后,最短匹配 [root@shell ~]# echo ${url#*.}
//从前往后,最长匹配(贪婪匹配) [root@shell ~]# echo ${url##*.} 2.从后往前删除变量内容 [root@shell ~]# url=www.sina.com.cn //从后往前,最短匹配 [root@shell ~]# echo ${url%.*} //从后往前,最长匹配 贪婪匹配 [root@shell ~]# echo ${url%%.*} 3.索引及切片 //从0列开始,切出5列,第0-4列 [root@shell ~]# echo ${url:0:5} //从5列开始,切出5列,第5-9列 [root@shell ~]# echo ${url:5:5} //去除前5列 [root@shell ~]# echo ${url:5} 4.变量内容替换 [root@shell ~]# url=www.sina.com.cn //将第一个匹配的sina替换为baidu [root@shell ~]# echo ${url/sina/baidu} //将第一个匹配的n替换为N [root@shell ~]# echo ${url/n/N} //贪婪匹配 [root@shell ~]# echo ${url//n/N} 5.变量替代 ${变量名-新的变量值} 变量没有被赋值:会使用“新的变量值“ 替代 变量有被赋值(包括空值):不会被替代 //例1 [root@Shell ~]# url=www.sina.com [root@Shell ~]# echo $url www.sina.com [root@Shell ~]# echo ${url-www.baidu.com} www.sina.com [root@Shell ~]# unset url [root@Shell ~]# echo ${url-www.baidu.com} //例2 [root@Shell ~]# url2= [root@Shell ~]# echo ${url2-www.baidu.com} ${变量名:-新的变量值} 变量没有被赋值(包括空值): 都会使用“新的变量值“ 替代 变量有被赋值: 不会被替代 //例1 [root@Shell ~]# unset url [root@Shell ~]# echo $url
[root@Shell ~]# url=www.sina.com [root@Shell ~]# echo $url www.sina.com [root@Shell ~]# echo ${url:-www.baidu.com} www.sina.com [root@Shell ~]# unset url [root@Shell ~]# echo ${url:-www.baidu.com} www.baidu.com
//例2 [root@Shell ~]# url2= [root@Shell ~]# echo $url2
[root@Shell ~]# echo ${url2:-www.baidu.com} 6.变量自增 [root@shell ~]# unset i [root@shell ~]# unset j [root@shell ~]# i=1 [root@shell ~]# j=1 [root@shell ~]# let x=i++ 先赋值,再运算 [root@shell ~]# let y=++j 先运算,再赋值
//对变量值不会产生任何影响 [root@shell ~]# echo $i 2 [root@shell ~]# echo $j 2
//对表达式的值的影响 [root@shell ~]# echo $x 1 [root@shell ~]# echo $y 2
对变量的值的影响: [root@shell ~]# i=1 [root@shell ~]# let i++ [root@shell ~]# echo $i 2 |
shell编程第三天
一.shell条件测试
条件测试: 判断某需求是否满足,需要由测试机制来实现: 如何编写测试表达式实现所需的测试: (1)执行命令,并利用命令状态返回值来判断; (2)测试表达式 Test expression [ expression ] [[ expression ]] 注意:expression两端必须有空白字符,否则为语法错误 脚本的状态返回值: 默认是脚本中执行的最后一条命令的状态返回值; 自定义状态退出状态码; 注意shell检查遇到exit时,即会终止,因此,整个脚本执行几位结束; 1.文件测试 存在性测试: -a file -e file 文件的存在性测试,存在则为真,否则则为假; 存在性及类型测试 -b file: 块 -c file: 字符设备 -d file: 目录 -f file: 普通文件 -h file或-L file:符号连接 -p file:命令管道 -s file:套接字 文件权限测试: -r. -w. -x : -u file:是否存在并且拥有suid权限 -g file:是否存在并且拥有sgid权限 -k file:是否存在并且拥有sticky权限 文件是否有内容: -s file:是否有内容,有为真,没有为假; 时间戳测试: -N fiel: 文件自从上一次读操作后,是否被修改过; 从属关系测试; -O fiel:当前用户是否为文件属主; -G fiel:当前用户是否属于文件的属组; 双目测试: file1 -ef file2: file1与file2是否为指向同一个文件系统上的相同inode的硬连接; file1 -nt file2: file1是否新宇file2; file1 -ot file2: fiel1是否旧于file2; 2.常见使用方式 [ ! -d /bbb ] && mkdir /test [ -d /bbb ] || mkdir /test 3.脚本使用方式 #!/bin/bash #定义备份目录站点 back_dir=/var/mysql_back
#test -d $back_dir || mkdir -p $back_dir if [ ! -d $back_dir ];then mkdir -p $dack_dir fi echo “开始备份.....” 4.数值比较 数值比较 [ 整数1操作符 整数 2 ] -gt 大于 -lt 小于 -eq 等于 -ne 不等于 -ge 大于等于 -le 小于等于 例: 1.条件测试, 脚本使用案例, 创建用户 #!/bin/bash read -p “please input a username:” user id $user &>/devnull;then if [ $? -eq 0 ];then echo “user $user already exists” else useradd $user if [ $? -eq 0 ];then echo “$user is created” fi fi 2.查看磁盘当前使用状态,如果使用率超过百分之80%则报警发邮件 #查看磁盘使用率 df -h |grep “/$”|awk ‘{print $5}’|awk -F ‘%’ ‘{print $1}’ #脚本 #!/bin/sbah Root_Partition_Use=$(df -h|grep "/$"|awk ‘{print $5}‘|awk -F ‘%‘ ‘{print $1}‘)
if [ $Root_Partition_Use -ge 30 ];then echo "root partition use:${Root_Partition_Use}%" > /tmp/disk_use.txt fi 3.查看内存/当前使用状态,如果使用率超过80%则报警发邮件 [root@shell]# cat mem_use.sh Mem_Total=$(free -m|grep "^M"|awk ‘{print $2}‘) Mem_Use=$(free -m|grep "^M"|awk ‘{print $3}‘) Mem_Per=$((($Mem_Use*100)/$Mem_Total))
if [ $Mem_Per -ge 30 ];then echo -e "\033[31m Memory usage ${Mem_B}% is too high \033[0m" else echo -e "\033[32m Memory usage ${Mem_B}% is normal \033[0m" fi 5.字符串比较 字符串测试:字符比较 ==:是否等于; >,<,!= =~:左侧字符串是否能够被右侧的PATTERN所匹配; -z "STRING":判断指定的字符串是否为空;空为真,不空为假; -n "STRING":判断指定的字符串是否不空;不空为真,空为假;
注意: (1)字符串要加引用; (2)要使用[[ ]]; (1)字符串比对 [root@shell]# [ "$USER " = "root" ];echo $? 0 [root@shell]# [ "$USER " == "root" ];echo $? 0 [root@shell]# BBB="" [root@shell]# echo ${#BBB} 0 [root@shell]# [ -z "$BBB" ] 字符长度为 0 [root@shell]# echo $? 0 [root@shell]# [ -n "$BBB" ] 字符长度不为 0 [root@shell]# echo $? 1 //小结:变量为空 或未定义: 长度都为0 (2).字符串比对 [root@shell]# [ "$USER" = "root" ];echo $? 0 [root@shell]# [ "$USER" = "shell" ];echo $? 1 [root@shell]# [ "$USER" != "alice" ];echo $? 0 (3).多整数比对条件 [root@shell]# [ 1 -lt 2 -a 5 -gt 10 ];echo $? 1 [root@shell]# [ 1 -lt 2 -o 5 -gt 10 ];echo $? 0 [root@shell]# [[ 1 -lt 2 && 5 -gt 10 ]];echo $? 1 [root@shell]# [[ 1 -lt 2 || 5 -gt 10 ]];echo $? 0 6.正则比对 [root@shell]# [ "$USER" = "root" ];echo $? 0 [root@shell]# [ "$USER" =~ ^r ];echo $? bash: [: =~: binary operator expected 2 [root@shell]# [[ "$USER" =~ ^r ]];echo $? //使用正则 0 //判断变量是不是数字 [root@shell]# num=123 [root@shell]# [[ "$num10" =~ ^[0-9]+$ ]];echo $? 0 [root@shell]# [[ "$num20" =~ ^[0-9]+$ ]];echo $? 1 7.判断用户输入的是否是数字 [root@shell]# cat test02.sh #!/bin/bash
read -p "请输入一个数值: " num if [[ ! "$num" =~ ^[0-9]+$ ]];then echo " 你输入的不是数字,程序退出!!!" exit fi echo "Number Is $num" 8. 批量创建用户脚本, 仅个人使用 #!/usr/bin/bash read -p "Please input number: " num read -p "Please input prefix: " prefix
for i in `seq $num` do user=$prefix$i useradd $user echo "123" |passwd --stdin $user &>/dev/null if [ $? -eq 0 ];then echo "$user is created." fi done 9. 批量创建用户脚本, 改进版 #!/usr/bin/bash read -p "Please input number: " num if [[ ! "$num" =~ ^[0-9]+$ ]];then echo "error number!" && exit 1 fi
read -p "Please input user prefix: " prefix if [ -z "$prefix" ];then echo "error prefix" exit fi
for i in `seq $num` do user=$prefix$i useradd $user echo "123" |passwd --stdin $user &>/dev/null if [ $? -eq 0 ];then echo "$user is created." fi done 企业案例1.输入或通过命令行传入一个字符或数字,如果传入数字等于1,打印1;如果等于2,打印2;其他值,提示输入不对,退出 #echo -n "please input one key:" #read value read -p "please input one key:" value [ ${#value} -ne 1 ] && { echo "please input one key" exit } expr $value + 1 &> /dev/null [ $? -ne 0 ] && { echo "please input number" exit } [ $value -eq 1 ] && { echo $value exit 0 } [ $value -eq 2 ] && { echo $value exit 0 } [[ ! $value =~ [1-2] ]] && { echo "input error" exit 0 } 企业案例2.分别使用传参和read读入方式比较两个整数大小,禁止使用if语句. [ $# -ne 2 ] && { echo "please input two int." exit } int1=$1 int2=$2 expr $int1 + $int2 &> /dev/null [ $? -ne 0 ] && { echo "please input int" exit } [ $int1 -gt $int2 ] && { echo "$int1 > $int2" exit } [ $int1 -lt $int2 ] && { echo "$int1 < $int2" exit } [ $int1 -eq $int2 ] && { echo "$int1 = $int2" exit } 企业案例3.打印选择菜单,按照选择一键安装不同的web服务。 1.install lamp 2.install lnmp 3.exit cat << End 1.install lamp 2.install lnmp 3.exit End read -p "please input number you want:" num expr $num + 1 &> /dev/null [ $? -ne 0 ] && { echo "you input must be {1|2|3}." exit } [ $num -eq 1 ] && { echo "install lamp..." # source lamp_install.sh sleep 3 exit $? } [ $num -eq 2 ] && { echo "install lnmp..." # source lnmp_install.sh sleep 3 exit $? } [ $num -eq 3 ] && { echo "bye" exit $? } [[ ! $num =~ [1-3] ]] && { echo "input error" exit $? } |
shell编程第四天
一.回顾
1.条件判断 test -d filename [ 2 -lt 3 ] [[ 2 -lt 3 ]] ((2<3)) 2.文件比较 文件类型 -f -d 文件权限 2.数值比较 -le (小于等于) -ge (大于等于) -eq (等于) -lt (小于) -gt (大于) -ne (不等于) 3.字符串比较 == (等于) =~ (约等于) != (不等于) 4.逻辑判断 && (前一个命令执行成功,再执行后一个命令) 字符 -a || (前一个美丽执行失败,再执行后一个命令) 字符 -o |
二.shell流程控制
1.流程控制语句if 单分支结构 if [ 如果你有房 ];then 我就嫁给你 fi 双分支结构 if [ 如果你有房 ];then 我就嫁给你 else 再见 fi 多分支结构 if [ 如果你有房 ];then 我就嫁给你 elif [ 你有车 ];then 我就嫁给你 elif [ 你有钱 ];then 我也嫁给你 else 再见 fi
猜数字游戏,0-99之间数字 如果大了,就输出一个信息.重新再猜 如果小了,就输出一个信息,重新再猜 如果猜对了,恭喜,输出猜的次数 脚本内容 #!/bin/bash echo "下面我们玩一个猜数字游戏.取值范围在0-99之间" ran_num=$(expr $RANDOM % 100) while true do read -p "请输入一个数字(0-99):" num
[[ ! "$num" =~ ^[0-9]+$ ]] && { continue } if [ $num -gt $ran_num ];then echo "大了,请继续:" elif [ $num -lt $ran_num ];then echo "小了,请继续:" else echo "恭喜,你猜对了! $count" exit fi done |
四.实例.安装nginx
#!/bin/bash #install nginx #1.判断网络 ping -c1 www.baidu.com $>/dev/null if [ $? -ne 0 ];then echo “请检查你的网络” exit 1 fi #2.yum仓库 yum_repo=$(yum repolist|grep nginx|wc -l) if [ $yum_repo -eq 0 ];then cat >/etc/yum.repos.d/nginx.repo <<-EOF [nginx] name=nginx repo baseurl=http://nginx.org/packages/centos/7/x86_64/ gpgcheck=0 enabled=1 EOF yum makecache elif [ $yum_repo -eq 1 ];then yum install nginx -y &>/dev/null install_nginx=$(rpm -q nginx|wc -l) if [ $install_nginx -eq 1 ];then echo “ nginx已经安装” fi nginx_status=$(systemctl status nginx|grep Active |awk ‘{print $1 $3}’) systemctl start nginx &>/dev/null if [ $? -eq 0 ];then echo “nginx 已经启动完毕” echo ”nginx当前状态是:$nginx_status” else echo “nginx启动失败 $nginx_status” killall httpd &>/dev/null killall nginx &>/dev/null systemctl start nginx if [ $? -eq 0 ];then echo -e “nginx重新启动成功” nginx_status=$(systemctl status nginx |grep Active |awk ‘{print $1 $3}’) echo -e “\033[32m $nginx_status \033[0m” fi fi else echo “未知问题,请手动检查一下” fi |
五. 根据不同的系统安装不同的yum源
#!/bin/bash os_name=$(cat /etc/redhat-release) os_version=$(cat /etc/redhat-release |awk ‘{print $4}’| awk -F ‘.’ ‘{print $1}’) if [ $os_version = “(Final)” ];then os_version=$(cat /etc/redhat-release |awk ‘{print $3}’ |awk -F ‘.’ ‘{print $1}’) fi if [ $os_vesion -eq 7 ];then mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/* .repo /etc/yum.repos.d/backup cat >/etc/yum.repos.d/base.repo<<-EOF [base] name=local base yum source baseurl=ftp://192.168.56.1/base/7/x86_64 enadle=1 gpgcheck=0 EOF Echo “$os_name 系统已经配置好郁闷仓库” elif [ $os_version -eq 6 ];then mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup wget -o /etc/yum.repos.d/Centos-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo &>/dev/null echo "$os_name 系统已经配置好yum仓库" elif [ $os_version -eq 5 ];then mkdir -p /etc/yum.repos.d/backup mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-5.repo &>/dev/null echo "$os_name 系统已经配置好yum仓库" else echo "无法检测当前系统版本,请检查/etc/redhat-release" fi
|
六. 安装不同版本的PHP
#!/bin/bash #install php install_php56() { echo "install php5.6......" } install_php70() { echo "install php7.0......" } install_php71() { echo "install php7.1......" } while : do echo "################################" echo -e "\t1 php-5.6" echo -e "\t2 php-7.0" echo -e "\t3 php-7.1" echo -e "\tq exit" echo "################################"
read -p "version[1-3]: " version if [ "$version" = "1" ];then install_php56 elif [ "$version" = "2" ];then install_php70 elif [ "$version" = "3" ];then install_php71 elif [ "$version" = "q" ];then exit else echo "error" fi done |
七. 流程控制语句case
case语句
case 变量 in 模式 1) 命令序列 1;; 模式 2) 命令序列 2;; 模式 3) 命令序列 3 ;; *) 无匹配后命令序列 Esac 1.批量删除用户
#!/bin/bash read -p "Please enter the username prefix to be deleted: " delname read -p "Please enter the number of users you need to delete:" delnum
echo "You want to delete the following users: Username prefix: $delname User number: $delnum "
for i in $(seq $delnum) do username=$delname$i read -p "are you sure you want to delete ${username}?[y|Y|Yes|n|N|NO] " reday case $reday in y|Y|YES) id $username &>/dev/null if [ $? -eq 0 ];then userdel $username &>/dev/null echo "$username deleted." else echo "$username not exist." fi ;; n|N|no|NO|No) continue ;; *) echo "you can only enter [y|Y|Yes|n|N|NO]" esac done 2.系统管理工具箱
Command action h 显示命令帮助 f 显示磁盘分区 d 显示磁盘挂载 m 查看内存使用 u 查看系统负载 q 退出程序
#!/bin/bash menu(){ cat <<-EOF =================== h 显示命令帮助 f 显示磁盘分区 d 显示磁盘挂载 m 查看内存使用 u 查看系统负载 q 退出程序 ===================== EOF } menu while true do read -p "Command [h|f|d|m|u|q]: " sys case "$sys" in h) clear menu ;; f) clear lsblk ;; d) clear df -h ;; m) clear free -m ;; u) clear uptime ;; q) break ;; *) echo "you can olny enter [h|f|d|m|u|q]." continue esac done |
八. 实现简单的JumpServer
#!/usr/bin/bash
#jumpServer
Mysql_master=192.168.70.160 Mysql_slave1=192.168.70.161 Mysql_slave2=192.168.70.162 Nginx_Up=192.168.70.150 Nginx_WEB1=192.168.70.151 Nginx_WEB2=192.168.56.11
menuinfo(){ cat <<-EOF ------------------------------- | 1) mysql-master | | 2) mysql-slave1 | | 3) mysql-slave2 | | 4) Nginx-Upstream | | 5) Nginx-WebNode1 | | 6) Nginx-WebNode2 | | h) help | --------------------------------- EOF } #调用函数打印菜单 menuinfo #控制不让输入ctrl+c,z trap "" HUP INT TSTP while true do read -p "请输入要连接的主机编号: " num case $num in 1|mysql-master) ssh root@$Mysql_master ;; 2|Mysql_slave1) ssh root@$Mysql_slave1 ;; 3|Mysql_slave2) ssh root@$Mysql_slave2 ;; h|help) clear meminfo ;; #退出脚本后门, 不要让其他人知道 exec) break ;; esac done //无论使用登陆式shell或非登陆式shell都会执行该脚本, 前提root用户不允许登陆 [root@Shell day03]# cat /home/oldboy/.bashrc sh /home/oldboy/jumpserver.sh
4.使用case编写服务启动与停止脚本
#!/usr/bin/bash # manager Nginx start stop restart reload source /etc/init.d/functions
act=$1 te(){ if [ $? -eq 0 ];then action "Nginx Is $act" /bin/true else action "Nginx Is $act" /bin/false fi } start(){ /usr/sbin/nginx &>/dev/null te
} stop(){ /usr/sbin/nginx -s stop &>/dev/null te }
reload(){ /usr/sbin/nginx -s reload te }
status(){ Ngx_status=$(ps aux|grep "[n]ginx"|egrep -v "vi|sh"|grep master|awk ‘{print $2}‘) Nginx_Status_Port=$(netstat -lntp|grep nginx|awk ‘{print $4}‘) echo "Nginx_status_Pid: $Ngx_status" echo "Nginx_status_Port: $Nginx_Status_Port" } case $1 in start) start ;; stop) stop ;; restart) stop sleep 1 start ;; reload) reload ;; status) status ;; *) echo "Usage: $0 {start|stop|status|restart|reload|}" esac |
九. 使用case实现多级菜单
## 3.交互脚本expect 1.expect实现简单的交互登陆
#!/usr/bin/expect spawn ssh root@192.168.70.161
expect { "yes/no" { send "yes\r"; exp_continue } "password:" { send "centos\r" }; } interact
2.expect定义变量实现交互方式
#!/usr/bin/expect set ip 192.168.70.161 set user root set password centos set timeout 5
spawn ssh $user@$ip
expect { "yes/no" { send "yes\r"; exp_continue } "password:" { send "$password\r" }; } #交互方式 interact |
十. expect进行参数传递,执行命令或其他操作
#!/usr/bin/expect #位置传参 set ip [lindex $argv 0] set user root set password centos set timeout 5
spawn ssh $user@$ip
expect { "yes/no" { send "yes\r"; exp_continue } "password:" { send "$password\r" }; }
#当出现#号符执行如下命令 expect "#" send "useradd bgx\r" send "pwd\r" send "exit\r" expect eof |
十一. 批量获取在线主机, 进行秘钥批量分发
cat for_ip.sh #!/usr/bin/bash
#1 拿到IP地址 >ip.txt for i in {160..162} do ip=192.168.70.$i { ping -c1 -W1 $ip &>/dev/null if [ $? -eq 0 ];then echo "$ip" >> ip.txt fi }& done #2.生成对应的密钥 if [ ! -f ~/.ssh/id_rsa ];then ssh-keygen -P "" -f ~/.ssh/id_rsa fi
#3.批量分发密钥 while read line do /usr/bin/expect <<-EOF set pass 1 set timeout 2 spawn ssh-copy-id $line -f expect { "yes/no" { send "yes\r"; exp_continue} "password:" { send "1\r"} } expect eof EOF done<ip.txt [root@oldboy 09]# cat rsyncd.sh #!/bin/bash ############################################################## # File Name: rsyncd.sh # Version: V1.0 # Author: oldboy # Organization: www.oldboyedu.com ############################################################## RETVAL=0 start(){ rsync --daemon RETVAL=$? if [ $RETVAL -eq 0 ] then echo "rsync is ok" else echo "rsync is fail" fi } stop(){ killall rsync RETVAL=$? if [ $RETVAL -eq 0 ] then echo "rsync is stopped" else echo "rsync is stop fail" fi } case "$1" in start) start ;; stop) stop ;; restart) stop sleep 2 start ;; *) echo "Usage:$0 {start|stop|restart}" exit 1 esac 专业一点的 [root@oldboy 09]# cat rsyncd2.sh #!/bin/bash # chkconfig: 2345 20 80 # description: rsync start and stop scripts ############################################################## # File Name: rsyncd.sh # Version: V1.0 # Author: oldboy # Organization: www.oldboyedu.com ############################################################## start(){ rsync --daemon retval=$? if [ $retval -eq 0 ] then echo "rsync startup ok" return $retval else echo "rsync startup fail" return $retval fi } stop(){ killall rsync retval=$? if [ $retval -eq 0 ] then echo "rsync stop ok" return $retval else echo "rsync stop fail" return $retval fi } case "$1" in start) start retval=$? ;; stop) stop retval=$? ;; restart) stop sleep 1 start retval=$? ;; *) echo "usage:$0 {start|stop|restart}" exit 1 esac exit $retval |
Shell编程第五天
一.for循环语句
1.for 循环基础语法 for 变量名 in [ 取值列表 ] do 循环体 done 2.for案例,批量探测主机存活状态 #cat for_ip.sh #循环主机 for i in {1..254} do #并发执行 { ip=10.0.0.$i ping -c1 -W1 $ip &>/dev/null If [ $? -eq 0 ];then Echo “$ip” |tee -a ip.txt fi }& done #等待前台进程结束,在往后执行 wait echo "Get IP Is Finsh!!" 3.for循环批量创建用户 #!/usr/bin/bash
read -p "请输入用户名前缀|密码|数量: " rep pass num
if [[ ! $num =~ ^[0-9]+$ ]];then echo "Error 请重新输入数字" fi
cat <<-EOF 你输入的用户名前缀是: $rep 你输入的统一密码是: $pass 你输入要创建的数量: $num EOF read -p "你确定要创建吗? [y|n]" aredy case $aredy in y|Y|yes|YES) for i in $(seq $num) do username=$rep$i id $usernme &>/dev/null if [ $? -ne 0 ];then useradd $username && \ echo "$pass"|passwd --stdin $username &>/dev/null echo "$username Is OK!" fi done ;; n|N|No|NO) exit 1 ;; *) read -p "你确定要创建吗? [y|n]" aredy esac 4.for循环通过文件批量创建用户 #!/bin/bash
for i in $(cat user.list) do id $i &>/dev/null if [ $? -ne 0 ];then useradd $i && \ echo "123" |passwd --stdin $i &>/dev/null echo "$i created." else echo "$i alreadt exists!!!" fi done
5.批量修改密码
#!/usr/bin/bash for i in {160..162} do ip=192.168.70.$i ping -c1 -W1 $ip &>/dev/null if [ $? -eq 0 ];then ssh $ip "echo 1|passwd --stdin root" &>/dev/null echo "$ip: Is Passwod Successfuly" fi done |
二. while循环语句
while循环基础语法 //当条件测试成立(条件测试为真),执行循环体 while 条件测试 do 循环体 done 1.使用while创建用户 #!/usr/bin/bash while read user do id $user &>/dev/null if [ $? -eq 0 ];then echo "useradd $user is already exists" else useradd $user &>/dev/null echo "useradd $user is Created." fi done<user.list #文件中存在用户和密码 #!/usr/bin/bash while read user do u=$(echo $user|awk ‘{print $1}‘) p=$(echo $user|awk ‘{print $2}‘)
id $u &>/dev/null if [ $? -eq 0 ];then echo "useradd $u is already exists" else useradd $u &&\ echo "$p"|passwd --stdin $u &>/dev/null echo "useradd $u is Created Passwd Is Ok." fi
done<user2.tt |
三. 监控网站,每隔10秒确定一次网站是否正常
#!/bin/bash if [ $# -ne 1 ];then echo $"usage $0 url." exit1 } fi while true do if [ $(curl -o /dev/null --connect-timeout 5 -s -w "%{http_code}" $1 | egrep -w "200|301|302" | wc -l) -ne 1 ];then echo "$1 is error." else echo "$1 is ok." fi sleep 10 done |
四. Shell内置命令
exit 退出整个程序 break 结束当前循环,或跳出本层循环 continue 忽略本次循环剩余的代码,直接进行下一次循环 |
shell编程第六天
一. 回顾
day01: 1.shell脚本结构 #!/bin/bash cmd 2.shell脚本执行 bash/sh:不需要脚本具有执行权限,打开一个子进程使用bash来解释脚本里面的语句. ./:(路径)必须要有执行权限,打开一个字进程,使用bash来解释脚本里面的语句. source/. :不需要执行权限.直接将脚本里面的语句调入当前环境执行. 3.学习shell脚本的基础: 基础命令 如何更优秀: 习惯 标准 day02: 1.变量类型 自定义变量 1.变量名必须用字母或_开头 2.变量名=变量值,export , /etc/bashrc ,~/bashrc 环境变量 1.变量名全大写 2.变量名=变量值,export ,/etc/bashrc , ~/bashrc 位置变量 $n 预定义变量 $# 脚本里一共有几个位置变量 $* 脚本里所有变量值 加””会把所有变量值视为一个整体 $@ 脚本里所有变量值 加””会把所有变量值单个显示 $? 脚本里最后一个命令执行后状态码 0表示成功 非0表示不成功 $0 运行这个脚本的文件名 $! $$ $_ day03: 1.条件测试语句 test [ ] [[ ]] :字符串比较 (( )) day04: 1.判断语句 if 语句: 单分支 双分支 多分支 case语句: day05: 1.循环语句 for while |
二. shell脚本之函数
函数:function,把一段独立功能的代码当作一个整体,并为之取一个名字,命名的代码段,此即为函数. 注意:定义函数的代码段不会自动执行,在调用时执行;所谓调用函数,在代码中给定函数名即可;函数名出现在任何位置,在代码执行时,都会被自动替换为函数代码; 过程式编码:代码重用 模块化编程 结构化编程 语法一: function f-name { ... 函数体... } 语法二:(推荐) f_name() { .....函数体.... } 例1:给定一个用户名.取得用户的id号和默认shell 分析:
例2:服务脚本框架 分析:
返回值 创建锁文件
删除锁文件
函数的生命周期: 每次被调用时创建函数,返回时终止; 其状态返回结果为函数体中运行的最后一个命令的状态; 自定义状态返回值,需要使用”return” return [0-255] 0:成功 1-255:失败 函数的执行结果返回值: (1) 使用echo或printf命令进行输出; (2) 函数体中调用的命令执行结果; 函数的退出状态码: (1) 默认取决于函数中执行的最后一条命令的退出状态码; (2) 自定义:return 例1:添加10个用户,用户名作为参数传给函数 #!/bin/bash #retval 0 :usrt created #retval 5 :user exist adduser() { if id $1 &>/dev/null;then return 5 else useradd $1 return $? fi } for i in `seq 10` do username=$1$i adduser $username RETVAL=$? if [ $RETVAL -eq 5 ];then echo “$username exist.” elif [ $RETVAL -eq 0 ];then echo “$username created.” else echo “no reason,please check it yoursrlf.” fi done 函数可接受参数: 传递参数给函数:在函数体中,可以使用$1,$2,....引用传递给函数的参数,还可以在函数中使用$*或$@引用所有参数,$#引用传递的参数的个数: 在调用函数时,在函数名后面以空白符分隔给定参数列表即可,例如:testfunc arg1 arg2 arg3.... |
三. 函数变量作用域
1.局部变量: 作用域是函数的生命周期:在函数结束时被自动销毁; 定义局部变量的方法:local VARIABLE=VALUE 2.本地变量: 作用域是运行脚本的shell进程的生命周期;因此,其作用范围为当前shell脚本程序文件 示例: #!/bin/bash name=tom setname(){ local name=jerry ceho “Function:$name” } setname echo “shell:$name” |
四. wgret命令参数,curl命令参数
shell编程第七天
一. shell数组应用
1.数组分类 普通数组:只能用整数 作为数组索引 关联数组:可以使用字符串 作为数组索引 2.普通数组 (1)数组赋值方式 针对每个索引进行赋值 [root@oldboy ~]# array1[0]=pear [root@oldboy ~]# array1[1]=apple [root@oldboy ~]# array1[2]=orange [root@oldboy ~]# array1[3]=peach 一次赋多个值,数组名=(多个变量值) [root@oldboy ~]# array2=(tom jack alice) [root@oldboy ~]# array3=(tom jack alice "bash shell") [root@oldboy ~]# array4=(1 2 3 "linux shell" [20]=puppet) 将给文件中的每一个行,作为一个元数赋值给数组 array3 [root@oldboy ~]# array5=(`cat /etc/passwd`) (2)查看数组赋值结果 #定义普通数组 [root@oldboy ~]# declare -a array (3)访问数组元数 统计数组元数的个数 [root@oldboy ~]# echo ${#array1[@]} 4 访问数组中的第一个元数 [root@oldboy ~]# echo ${array1[0]} pear 从数组索引1开始 [root@oldboy ~]# echo ${array1[@]:1} apple orange peach 从数组索引1开始,访问两个元数 [root@oldboy ~]# echo ${array_fruit[@]:1:2} apple orange 访问数组中所有数据,相当于echo ${array1[*]} [root@oldboy ~]# echo ${array_fruit[@]} pear apple orange peach (4)获取数组索引 获取数组元数的索引 [root@oldboy ~]# echo ${!array1[@]} 0 1 2 3 使用值来遍历数组 #!/bin/bash array_fruit=( apple orange pear) for i in ${array_fruit[*]} do echo $i done 使用索引来遍历数组 #!/bin/bash array_fruit=(apple orange prar) for i in ${!array-fruit[*]} do echo ${array_fruit[$i]} done 实例1.利用bash for循环打印下面这句话中字母数不大于6的单词 welcome to oldboyedu my name is oldboy #!/bin/bash declare -a array_word array_word=(welcome to oldboyedu my name is oldboy) for i in ${array-word[@]} do if [ ${#i} -le 6 ];then echo $i fi done 实例2.批量检查多个网站地址是否正常 要求: (1) 使用shell数组方法实现,检测策略尽量模拟用户访问 (2) 每10秒钟做一次所有的检查,无法访问的输出报警 (3) 待检测的地址如下. http://blog.oldboyedu.com http://blog.etiantian.org http://oldboy.blog.51cto.com 分析: 1. 定义一个数组 2. 通过for打印数组列表 3. 通过wget/curl发给我url,通过访问返回值判断 4. 使用while true循环,sleep 10 #!/bin/bash declare -a array_url array_url=( http://blog.oldboyedu.com http://blog.etiantian.org http://oldboy.blog.51cto.com ) while true do for n in ${array_url[*]} do wget -q -T 3 --tries=1 --spider $n if [ $? -eq 0 ];then echo “$n is ok” else echo “$n is fail” fi done sleep 2 done 3.关联数组 (1)定义关联数组,什么是关联数组 [root@oldboy ~]# declare -A tt_array_1 [root@oldboy ~]# declare -A tt_array_2 (2)给关联数组进行赋值 数组名[索引号]=变量值 [root@oldboy ~]# tt_array1[index1]=pear [root@oldboy ~]# tt_array1[index2]=apple [root@oldboy ~]# tt_array1[index3]=orange [root@oldboy ~]# tt_array1[index4]=peach 给关联数组一次赋多个值 [root@oldboy ~]#tt_array2=([index1]=tom [index2]=jack [index3]=alice ) (3)查看关联数组 [root@oldboy ~]#declare -A (4)访问数据元数 访问数组中的第二个元数 [root@oldboy ~]# echo ${tt_array2[index2]} jack 访问数组中所有元数,等同于 echo${array1[*]} [root@oldboy ~]# echo ${tt_array2[@]} tom jack alice 访问数组中所有元数索引 [root@oldboy ~]# echo ${!tt_array2[@]} index1 index2 index3 4.遍历数组 通过数字元数的索引进行遍历(推荐) 注意:将统计的对象作为数组的索引,仅针对关联数组 实例1.统计/etc/passwd的shell数量 cat /etc/passwd | awk -F ‘.’ ‘{print $NF}’ |sort|uniq -c [root@oldboy ~]# cat array_passwd_count.sh #!/bin/bash declare -A array_passwd (1)对数组进行赋值 while read line do type=$(echo $line |awk -F ‘.’ ‘{print $NF}’) let array_passwd[$type]++ done </etc/passwd (2)对数组进行遍历 for i in ${!array_passwd[@]} do echo “shell:$i,eount: ${array_passwd[$i]}” done 实例2.统计Nginx日志IP访问次数 cat /etc/httpd/logs/access_log | awk ‘{print $1}‘| sort|uniq -c [root@oldboy ~]# cat array_nginx_count.sh #!/bin/bash # nginx log top 10 IP conut declare -A array_nginx #1.给关联数组的索引进行赋值 while read line do type=$(echo $line|awk ‘{print $1}‘) let array_nginx[$type]++ done </var/log/nginx/access.log
for i in ${!array_nginx[@]} do echo "IP是:$i 出现多少次${array_nginx[$i]}" done 实例3.统计TCP的状态信息 [root@oldboy ~]# cat array_tcp_state.sh #!/bin/bash declare -A array_tcp type=$(ss -an |grep :80|awk ‘{print $1}‘) #1.对数组进行的索引赋值 for i in $type do let array_tcp[$i]++ done #2.遍历数组 for j in ${!array_tcp[@]} do echo "当前的状态是:$j,当前状态出现了多少次:${array_tcp[$j]}" done
当前的状态是:ESTAB,当前状态出现了多少次:325 当前的状态是:CLOSE-WAIT,当前状态出现了多少次:35 当前的状态是:TIME-WAIT,当前状态出现了多少次:14017 当前的状态是:SYN-RECV,当前状态出现了多少次:21 当前的状态是:FIN-WAIT-1,当前状态出现了多少次:37 当前的状态是:LISTEN,当前状态出现了多少次:1 |
shell编程第八天
一.shell正则应用
正则表达式介绍: 正则表达式`regular expression`, RE是一种字符模式,用于在查找过程中匹配指定的字符。 在大多数程序里,正则表达式都被置于两个正斜杠之间;例如`/l[oO]ve/`就是由正斜杠界定的正则表达式,它将匹配被查找的行中任何位置出现的相同模式。在正则表达式中,元字符是最重要的概念。 正则表达式的作用
正则表达式注意事项
|
二. 基础正则表达式
元字符意义BRE,正则表达式时间就是一些特殊字符,赋予了它特定的含义 字符匹配: . :匹配任单个字符; [ ]:匹配指定范围内的任意当个字符; [^]:匹配指定范围外的任意单个字符; [a-z]:匹配所有小写自字母 [A-Z]:匹配所有大写字母 [0-9]:匹配所有数字 [a-z0-9]:匹配字母和数字 [abcd]:匹配括号里有的字母 匹配次数:用子啊要指定其出现的次数的字符的后面,用于现在其前面字符出现的次数; *:匹配其前面的字符任意次:0,1,多次: 例如:grep “x*y” abxy,aby,xxxxy,yad .*:匹配任意长度的任意字符; \?:匹配其前面的字符0次或1次,也就是说其前面的字符是可有可无的; \+:匹配其前面的字符1次或多次,也就是说其前面的字符至少出现1次; \{m\}:匹配其前面的字符m次; \{m,n\}:匹配其前面的字符至少m次,至多n次; \{0,n\}:至多n次; \{m,\}:至少m次; 位置锚定: ^:行首锚定;用于模式的最左侧; $:行尾锚定;用于模式的最右侧; ^PATTERN$:用PATTERN来匹配整行; ^$:空白行; ^[[:space:]]*$:空行或包含空白字符的行; 单词:非特殊字符组成的连续字符串都称为单词; \<或\b:词首锚定,用于单词的左侧; \>或\b:词尾锚定,用于单词的右侧; \<PATHERN\>:匹配完整单词; |
三. 扩展正则表达式
扩展正则表达式:ERE,egrep,grep -E 扩展正则表达式的元字符: 字符匹配: .:匹配任意单个字符; []:匹配指定范围内的任意单个字符; [^]:匹配指定范围外的任意单个字符; 次数匹配: *:匹配其前面的字符任意次:0,1,多次; .*:匹配任意长度的任意字符; ?:匹配其前面的字符0次或1次,也就是说其前面的字符是可有可无的; +:匹配其前面的字符1次或多次,也就是说其前面的字符至少出现1次 {m}:匹配其前面的字符m次; {m,n}:匹配其前面的字符至少m次,至多n次; {0,n}:至多n次; {m,}:至少m次; 位置锚定: ^:行首锚定;用于模式的最左侧; $:行尾锚定;用于模式的最右侧; ^PATTERN$:用PATTERN来匹配整行; ^$:空白行; ^[[:space:]]*$:空行或包含空白字符的行; \<PATTERN或\b:词首锚定,用于单词的左侧; PATTERN\>或\b:词尾锚定,用于单词的右侧; \<PATHERN\>:匹配完整单词; |
四. 正则表达式实战
I am oldboy teacher! I teach linux. test
I like badminton ball ,billiard ball and chinese chess! my blog is http://oldboy.blog.51cto.com our site is http://www.oldboy.com my qq num is 191868516. not 191886888516. //过滤以m开头的行 [root@Shell ~]# grep "^m" test.txt my blog is http://oldboy.blog.51cto.com my qq num is 191868516. [root@Shell ~]# grep "m$" test.txt my blog is http://oldboy.blog.51cto.com our site is http://www.oldboyedu.com //排除空行, 并打印行号 [root@student ~]# grep -vn "^$" oldboy.txt //匹配任意一个字符,不包括空行 [root@student ~]# grep "." oldboy.txt //.匹配所有 [root@student ~]# grep ".*" oldboy.txt //匹配单个任意字符 [root@node1 ~]# grep "oldboy.i" oldboy.txt //以点结尾的 [root@student ~]# grep "\.$" oldboy.txt //精确匹配到 [root@student ~]# grep -o "8*" oldboy.txt //匹配有abc的行 [root@student ~]# grep "[abc]" oldboy.txt //匹配数字所在的行"[^0-9]" [root@student ~]# grep "[0-9]" oldboy.txt //匹配所有小写字母[^a-z] [root@student ~]# grep "[a-z]" oldboy.txt //重复0三次 [root@student ~]# grep "8\{3\}" oldboy.txt //重复3个000不用转义符 [root@student ~]# grep -E "8{3}" oldboy.txt //重复数字8, 3-5次 [root@student ~]# grep -E "8{3,5}" test.txt //至少1次或1次以上 [root@student ~]# grep -E "8{1,}" oldboy.txt |
五. sed文本处理
sed是一个流编辑器, 非交互式的编辑器,它一次处理一行内容. 处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space) 接着用 sed 命令处理缓冲区中的内容,处理完成后, 把缓冲区的内容送往屏幕。 接着处理下一行,这样不断重复,直到文件末尾。 文件内容并没有改变,除非你 使用重定向存储输出。 Sed 要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。 1.sed命令格式 sed [options] ‘command‘ file(s) sed正则使用 与 grep一样,sed 在文件中查找模式时也可以使用正则表达式(RE)和各种元字符。 正则表达式是括在斜杠间的模式,用于查找和替换,以下是sed支持的元字符。 使用基本元字符集 , $, ., *, [], < >, (), {} 使用扩展元字符集 ?, +, { }, |, ( ) 使用扩展元字符的方式 + sed -r 2.sed命令示例 sed对指定行进行操作,包括打印、删除、修改、追加等。 sed选项参数 -e 允许多项编辑 -n 取消默认的输出 -i 直接修改对应文件 -r 支持扩展元字符 sed命令参数 a 在当前行后添加一行或多行 c 在当前行进行替换修改 d 在当前行进行删除操作 i 在当前行之前插入文本 p 打印匹配的行或指定行 n 读入下一输入行,从下一条命令进行处理 ! 对所选行以外的所有行应用命令 h 把模式空间里的内容重定向到暂存缓冲区 H 把模式空间里的内容追加到暂存缓冲区 g 取出暂存缓冲区的内容,将其复制到模式空间,覆盖该处原有内容 G 取出暂存缓冲区的内容,将其复制到模式空间,追加在原有内容后面 多重编辑选项e 例: //先删除行,然后管道给后面的sed进行替换 [root@Shell ~]# sed ‘1,9d‘ passwd |sed ‘s#root#alex#g‘ //使用-e进行多次编辑修改操作 [root@Shell ~]# sed -e ‘1,9d‘ -e ‘s#root#alex#g‘ passwd
打印命令p
//打印匹配halt的行 [root@Shell ~]# sed -n ‘/halt/p‘ passwd halt:x:7:0:halt:/sbin:/sbin/halt //打印第二行的内容 [root@Shell ~]# sed -n ‘2p‘ passwd bin:x:1:1:bin:/bin:/sbin/nologin //打印最后一行 [root@Shell ~]# sed -n ‘$p‘ passwd
追加命令a //给30行添加配置 \t tab键(需要转义) \n 换行符 [root@Shell ~]# sed -i ‘30a listen 80;‘ passwd 修改命令c //指定某行进行内容替换 [root@Shell ~]# sed -i ‘7c SELINUX=Disabled‘ /etc/selinux/config //正则匹配对应内容, 然后进行替换 sed -i ‘/^SELINUX=/cSELINUX=Disabled‘ /etc/selinux/config //非交互式修改指定的配置文件 [root@Shell ~]# sed -ri ‘/UseDNS/cUseDNS no‘ /etc/ssh/sshd_config [root@Shell ~]# sed -ri ‘/GSSAPIAuthentication/c#GSSAPIAuthentication no‘ /etc/ssh/sshd_config [root@Shell ~]# sed -ri ‘/^SELINUX=/cSELINUX=disabled‘ /etc/selinux/config 删除命令d //指定删除第三行, 但不会改变文件内容 [root@Shell ~]# sed ‘3d‘ passwd [root@Shell ~]# sed ‘3{d}‘ passwd //从第三行删除到最后一行 [root@Shell ~]# sed ‘3,$d‘ passwd //删除最后一行 [root@Shell ~]# sed ‘$d‘ passwd //删除所有的行 [root@Shell ~]# sed ‘1,$d‘ passwd //匹配正则进行该行删除 [root@Shell ~]# sed ‘/mail/d‘ passwd 插入命令i //在文件的某一行上面添加内容 [root@Shell ~]# sed -i ‘30i listen 80;‘ passwd
写文件命令w //将匹配到的行写入到新文件中 [root@Shell ~]# sed -n ‘/root/w newfile‘ passwd
//将passwd文件的第二行写入到newfile中 [root@Shell ~]# sed -n ‘2w newfile‘ passwd 获取下一行命令n //匹配root的行, 删除root行的下一列 [root@Shell ~]# sed ‘/root/{n;d}‘ passwd
//替换匹配root行的下一列 [root@Shell ~]# sed ‘/root/{n; s/bin/test/}‘ passwd
暂存和取用命令h H g G
//将第一行的写入到暂存区, 替换最后一行的内容 [root@Shell ~]# sed ‘1h;$g‘ /etc/hosts //将第一行的写入到暂存区, 替换最后一行的内容 [root@Shell ~]# sed ‘1h;$g‘ /etc/hosts
//将第一行的写入到暂存区, 在最后一行调用暂存区的内容 [root@Shell ~]# sed ‘1h;$G‘ /etc/hosts
//将第一行的内容删除但保留至暂存区, 在最后一行调用暂存区内容追加至于尾部 [root@Shell ~]# sed -r ‘1{h;d};$G‘ /etc/hosts //将第一行的写入到暂存区, 在最后一行调用暂存区的内容 [root@Shell ~]# sed ‘1h;$G‘ /etc/hosts
//将第一行的内容删除但保留至暂存区, 在最后一行调用暂存区内容追加至于尾部 [root@Shell ~]# sed -r ‘1{h;d};$G‘ /etc/hosts
//将第一行的内容写入至暂存区, 从第二行开始进行重定向替换 [root@Shell ~]# sed -r ‘1h;2,$g‘ /etc/hosts
//将第一行重定向至暂存区, 2-3行追加至暂存区, 最后追加调用暂存区的内容 [root@Shell ~]# sed -r ‘1h; 2,3H; $G‘ /etc/hosts
反向选择命令!
//除了第三行,其他全部删除 [root@Shell ~]# sed -r ‘3!d‘ /etc/hosts |
六. sed匹配替换
s 替换命令标志 g 行内全局替换 i 忽略替换大小写 替换命令s //替换每行出现的第一个root [root@Shell ~]# sed ‘s/root/alice/‘ passwd //替换以root开头的行 [root@Shell ~]# sed ‘s/^root/alice/‘ passwd //查找匹配到的行, 在匹配的行后面添加内容 [root@Shell ~]# sed -r ‘s/[0-9][0-9]$/& .5/‘ passwd
//匹配包含有root的行进行替换 [root@Shell ~]# sed -r ‘s/root/alice/g‘ passwd //匹配包含有root的行进行替换,忽略大小写 # sed -r ‘s/root/alice/gi‘ /etc/passwd
//后向引用 [root@Shell ~]# sed -r ‘s#(Roo)#\1-alice#g‘ /etc/passwd [root@Shell ~]# ifconfig eth0|sed -n ‘2p‘|sed -r ‘s#(^.*et) (.*) (net.*$)#\2#g‘
//示例 [root@bgx ~]# vim a.txt /etc/abc/456 etc //删除文本中的内容,需加转义 [root@Shell ~]# sed -r ‘\/etc\/abc\/456/d‘ a.txt //如果碰到/符号, 建议使用#符替换 [root@Shell ~]# sed -r ‘s#/etc/abc/456#/dev/null#g‘ a.txt [root@Shell ~]# sed -r ‘s@/etc/abc/456@/dev/null@‘ a.txt 删除文件 //删除配置文件中#号开头的注释行, 如果碰到tab或空格是无法删除 [root@Shell ~]# sed ‘/^#/d‘ file //删除配置文件中含有tab键的注释行 [root@Shell ~]# sed -r ‘/^[ \t]*#/d‘ file //删除无内容空行 [root@Shell ~]# sed -r ‘/^[ \t]*$/d‘ file
//删除注释行及空行 [root@Shell ~]# sed -r ‘/^[ \t]*#/d; /^[ \t]*$/d‘ /etc/vsftpd/vsftpd.conf [root@Shell ~]# sed -r ‘/^[ \t]*#|^[ \t]*$/d‘ /etc/vsftpd/vsftpd.conf [root@Shell ~]# sed -r ‘/^[ \t]*($|#)/d‘ /etc/vsftpd/vsftpd.conf 给文件行添加注释 //将第二行到第六行加上注释信息 [root@Shell ~]# sed ‘2,6s/^/#/‘ passwd
//将第二行到第六行最前面添加#注释符 [root@Shell ~]# sed -r ‘2,6s/.*/#&/‘ passwd
//添加#注释符 [root@Shell ~]# sed -r ‘3,$ s/^#*/#/‘ passwd # sed -r ‘30,50s/^[ \t]*#*/#/‘ /etc/nginx.conf # sed -r ‘2,8s/^[ \t#]*/#/‘ /etc/nginx.conf |
七. awk文本处理
awk是一种编程语言,用于在`linux/unix`下对文本和数据进行处理。 awk数据可以来自标准输入、一个或多个文件,或其它命令的输出。 awk通常是配合脚本进行使用, 是一个强大的文本处理工具。
awk 的处理文本和数据的方式如下:
1.进行逐行扫描文件, 从第一行到最后一行 2.寻找匹配的特定模式的行,在行上进行操作 3.如果没有指定处理动作,则把匹配的行显示到标准输出 4.如果没有指定模式,则所有被操作的行都被处理 awk 的两种形式语法格式
awk [options] ‘commands‘ filenames awk [options] -f awk-script-file filenames
options -F 定义输入字段分隔符,默认的分隔符是空格或tab键 command BEGIN{} {} END{} 行处理前 行处理 行处理后 [root@Shell ~]# awk ‘BEGIN{print 1/2} {print "ok"} END {print "Game Over"}‘ /etc/hosts 0.5 ok ok ok Game Over awk命令格式 //awk ‘pattern‘ filename 匹配文件 [root@Shell ~]# awk ‘/root/‘ /etc/passwd
//awk ‘{action}‘ filename 对文件行进行动作处理 [root@Shell ~]# awk -F: ‘{print $1}‘ /etc/passwd cut -d: -f1
//awk ‘pattern {action}‘ filename 匹配+处理动作 [root@Shell ~]# awk -F ‘:‘ ‘/root/ {print $1,$3}‘ /etc/passwd [root@Shell ~]# awk ‘BEGIN{FS=":"} /root/{print $1,$3}‘ /etc/passwd
//command |awk ‘pattern {action}‘ //判断大于多少则输出什么内容 [root@Shell ~]# df |awk ‘/\/$/ {if ($3>50000) print $4}‘ |
八. awk工作原理
# awk -F: ‘{print $1,$3}‘ /etc/passwd 1.awk使用一行作为输入,并将这一行赋给内部变量$0每一行也可称为一个记录,以换行符结束 2.awk进行字段分解,每个字段存储在已编号的变量中,从$1开始 3.awk默认情况下的分隔符是空格, 是由内部变量FS来确定字段分隔符。初始FS为空格 4.awk打印字段,将以设置的方法使用print函数打印 5.awk在打印的字段间加上空格,因为$1,$3 之间有一个逗号。逗号它映射为另一个内部变量,称为输出字段分隔符OFS默认为空格 6.awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕
### 4.2Awk内部变量 `$0`保存当前记录的内容 [root@Shell ~]# awk ‘{print $0}‘ /etc/passwd
`NR`控制输入的总行数 //打印整个文本的行号 [root@Shell ~]# awk ‘{print NR,$0}‘ /etc/passwd //打印文件的前三行 [root@Shell ~]# awk ‘NR<=3‘ /etc/passwd
`FNR`记录输入文件的编号 [root@Shell ~]# awk ‘{print FNR,$0}‘ /etc/passwd /etc/hosts NF保存行的最后一列内容 [root@Shell ~]# awk -F ":" ‘{print $1,$NF}‘ /etc/passwd
`FS`指定字段分割符,默认空格 //以冒号作为字段分隔符 [root@Shell ~]# awk -F: ‘/root/{print $1, $3}‘ /etc/passwd [root@Shell ~]# awk ‘BEGIN{FS=":"} {print $1,$3}‘ /etc/passwd //以空格冒号tab作为字段分割 [root@Shell ~]# awk -F‘[ :\t]‘ ‘{print $1,$2,$3}‘ /etc/passwd
`OFS`输出字段分隔符 //,映射为OFS,初始情况下OFS变量是空格 [root@Shell ~]# awk -F: ‘/root/{print $1,$2,$3,$4}‘ /etc/passwd [root@Shell ~]# awk ‘BEGIN{FS=":"; OFS="+++"} /^root/{print $1,$2,$3}‘ /etc/passwd
`RS`输入记录分隔符,默认为换行符 [root@Shell ~]# awk -F: ‘BEGIN{RS=" "} {print $0}‘ /etc/hosts
`ORS`将文件每一行合并为一行,以空格为分割 [root@Shell ~]# awk -F: ‘BEGIN{ORS=" "} {print $0}‘ /etc/hosts
//通常情况下让输出分隔符为换行符, 然后依次打印响应的字段 [root@Shell ~]# awk -F ":" ‘BEGIN{OFS="\n"}{print $1,$2,$3,$4,$5,$6,$7}‘ passwd //将RS记录值标记为冒号分割, 打印后相当于将每行的内容进行切割 [root@Shell ~]# awk ‘BEGIN{RS=":"}{print $0}‘ passwd
`print`格式化输出函数 [root@Shell ~]# date|awk ‘{print $2,"5月份""\n",$NF,"今年"}‘ [root@Shell ~]# awk -F: ‘{print "用户是:" $1 "\t 用户uid:" $3 "\t 用户gid:" $4}‘ /etc/passwd
printf 函数 [root@Shell ~]# awk -F: ‘{printf "%-15s %-10s %-15s\n", $1, $2, $3}‘ /etc/passwd %s 字符类型 %d 数值类型 占 15 字符 - 表示左对齐,默认是右对齐 printf 默认不会在行尾自动换行,加\n |
九. awk模式动作
awk语句都由模式和动作组成。 模式部分决定动作语句何时触发及触发事件。 如果省略模式部分,动作将时刻保持执行状态。模式可以是条件语句或复合语句或正则表达式。 1.awk正则表达式 //匹配记录(整行) [root@Shell ~]# awk ‘/^root/‘ /etc/passwd [root@Shell ~]# awk ‘$0 ~ /^root/‘ /etc/passwd
//匹配字段:匹配操作符(~ !~) [root@Shell ~]# awk ‘!/^root/‘ /etc/passwd [root@Shell ~]# awk ‘$0 ~ !/^root/‘ /etc/passwd 2.比较表达式 比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。 比较表达式使用关系运算符,用于比较数字与字符串。 关系运算符 |运算符 |含义 |示例 |:---|:----|:---- |< |小于 |x<y |<= | 小于或等于 | x<=y |= |等于 |x==y |!= |不等于 |x!=y |>= |大于等于 | x>=y |> | 大于 |x>y //uid为0的列出来 [root@Shell ~]# awk -F ":" ‘$3==0‘ /etc/passwd //uid小于10的全部列出来 [root@Shell ~]# awk -F: ‘$3 < 10‘ /etc/passwd //用户登陆的shell等于/bin/bash [root@Shell ~]# awk -F: ‘$7 == "/bin/bash" ‘ /etc/passwd //第一列为alice的列出来 [root@Shell ~]# awk -F: ‘$1 == "alice" ‘ /etc/passwd //为alice的用户列出来 [root@Shell ~]# awk -F: ‘$1 ~ /alice/ ‘ /etc/passwd [root@Shell ~]# awk -F: ‘$1 !~ /alice/ ‘ /etc/passwd //磁盘使用率大于多少则,则打印可用的值 [root@Shell ~]# df |awk ‘/\/$/‘|awk ‘$3>1000000 {print $4}‘
|
十. awk条件表达式
[root@Shell ~]# awk -F: ‘$3>300 {print $0}‘ /etc/passwd [root@Shell ~]# awk -F: ‘{if($3>300) print $0}‘ /etc/passwd [root@Shell ~]# awk -F: ‘{if($3>5555){print $3} else {print $1}}‘ /etc/passwd |
十一. 运算表达式
[root@Shell ~]# awk -F: ‘$3 * 10 > 500000‘ /etc/passwd [root@Shell ~]# awk -F: ‘BEGIN{OFS="--"} { if($3*10>50000) {print $1,$3} } END {print "打印ok"}‘ /etc/passwd [root@Shell ~]# awk ‘/southem/{print $5 + 10}‘ datafile [root@Shell ~]# awk ‘/southem/{print $5 + 10.56}‘ datafile [root@Shell ~]# awk ‘/southem/{print $8 - 10}‘ datafile [root@Shell ~]# awk ‘/southem/{print $8 / 2 }‘ datafile [root@Shell ~]# awk ‘/southem/{print $8 * 2 }‘ datafile [root@Shell ~]# awk ‘/southem/{print $8 % 2 }‘ datafile |
十二. 逻辑操作符和复合模式
&& 逻辑与 || 逻辑或 ! 逻辑非
//匹配用户名为root并且打印uid小于15的行 [root@Shell ~]# awk -F: ‘$1~/root/ && $3<=15‘ /etc/passwd //匹配用户名为root或uid大于5000 [root@Shell ~]# awk -F: ‘$1~/root/ || $3>=5000‘ /etc/passwd awk示例1 # awk ‘/west/‘ datafile # awk ‘/^north/‘ datafile # awk ‘$3 ~ /^north/‘ datafile # awk ‘/^(no|so)/‘ datafile # awk ‘{print $3,$2}‘ datafile # awk ‘{print $3 $2}‘ datafile # awk ‘{print $0}‘ datafile # awk ‘{print "Number of fields: "NF}‘ datafile # awk ‘/northeast/{print $3,$2}‘ datafile # awk ‘/^[ns]/{print $1}‘ datafile # awk ‘$5 ~ /\. [7-9]+/‘ datafile # awk ‘$2 !~ /E/{print $1,$2}‘ datafile # awk ‘$3 ~ /^Joel/{print $3 "is a nice boy."}‘ datafile # awk ‘$8 ~ /[0-9][0-9]$/{print $8}‘ datafile # awk ‘$4 ~ /Chin$/{print "The price is $" $8 "."}‘ datafile # awk ‘/Tj/{print $0}‘ datafile # awk -F: ‘{print "Number of fields: "NF}‘ /etc/passwd # awk -F"[ :]" ‘{print NF}‘ /etc/passwd awk示例2 [root@Shell ~]# cat b.txt bgx oldboy:is a:good boy!
[root@Shell ~]# awk ‘{print NF}‘ b.txt 4 [root@Shell ~]# awk -F ‘:‘ ‘{print NF}‘ b.txt 3 [root@Shell ~]# awk -F"[ :]" ‘{print NF}‘ b.txt 6
|
十三. Awk条件判断
`if`语句格式:
{ if(表达式){语句;语句;... }}
//打印当前管理员用户名称 [root@Shell ~]# awk -F: ‘{ if($3==0){print $1 "is adminisitrator"} }‘ /etc/passwd //统计系统用户数量 [root@Shell ~]# awk -F: ‘{ if($3>0 && $3<1000){i++}} END {print i}‘ /etc/passwd //统计普通用户数量 [root@Shell ~]# awk -F: ‘{ if($3>1000){i++}} END {print i}‘ /etc/passwd
`if...else` 语句格式: {if(表达式){语句;语句;... }else{语句;语句;...}} # awk -F: ‘{if($3==0){print $1} else {print $7}}‘ /etc/passwd # awk -F: ‘{if($3==0) {count++} else{i++} }‘ /etc/passwd # awk -F: ‘{if($3==0){count++} else{i++}} END{print " 管理员个数: "count ; print " 系统用户数: "i}‘ /etc/passwd
`if...else if...else` 语句格式: {if(表达式 1){语句;语句;... }else if(表达式 2){语句;语句;. .. }else{语句;语句;... }}
[root@Shell ~]# awk -F: ‘{ if($3==0){i++} else if($3>0 && $3<1000){j++} else if($3>1000) {k++}} END {print i;print j;print k}‘ /etc/passwd [root@Shell ~]# awk -F: ‘{ if($3==0){i++} else if($3>0 && $3<1000){j++} else if($3>1000) {k++}} END {print "管理员个数"i; print "系统用户个数" j; print "系统用户个 数" }‘ /etc/passwd 管理员个数1 系统用户个数29 系统用户个数69 |
十四. awk 循环语句
while循环 [root@Shell ~]# awk ‘BEGIN{ i=1; while(i<=10){print i; i++} }‘ [root@Shell ~]# awk -F: ‘{i=1; while(i<=NF){print $i; i++}}‘ /etc/passwd [root@Shell ~]# awk -F: ‘{i=1; while(i<=10) {print $0; i++}}‘ /etc/passwd [root@Shell ~]#cat b.txt 111 222 333 444 555 666 777 888 999 [root@Shell ~]# awk ‘{i=1; while(i<=NF){print $i; i++}}‘ b.txt
for循环 //C 风格 for [root@Shell ~]# awk ‘BEGIN{for(i=1;i<=5;i++){print i} }‘ //将每行打印 10 次 [root@Shell ~]# awk -F: ‘{ for(i=1;i<=10;i++) {print $0} }‘ passwd [root@Shell ~]# awk -F: ‘{ for(i=1;i<=10;i++) {print $0} }‘ passwd [root@Shell ~]# awk -F: ‘{ for(i=1;i<=NF;i++) {print $i} }‘ passwd |
十五. awk数组实战
[root@Shell ~]# awk -F: ‘{username[++i]=$1} END{print username[1]}‘ /etc/passwd [root@Shell ~]# awk -F: ‘{username[i++]=$1} END{print username[1]}‘ /etc/passwd [root@Shell ~]# awk -F: ‘{username[i++]=$1} END{print username[0]}‘ /etc/passwd >注意:将需要统计的某个字段作为数组的索引,最后对索引进行遍历 1.按索引遍历 [root@Shell ~]# awk -F: ‘{username[x++]=$1} END{for(i in username) {print i,username[i]} }‘ /etc/passwd [root@Shell ~]# awk -F: ‘{username[++x]=$1} END{for(i in username) {print i,username[i]} }‘ /etc/passwd 2.统计`/etc/passwd` 中各种类型 shell 的数量 # awk -F: ‘{shells[$NF]++} END{ for(i in shells){print i,shells[i]} }‘ /etc/passwd 3.网站访问状态统计<当前时实状态ss> [root@Shell ~]# ss -an|awk ‘/:80/{tcp[$2]++} END {for(i in tcp){print i,tcp[i]}}‘ 4.统计当前访问的每个IP的数量<当前时实状态 netstat,ss> [root@Shell ~]# ss -an|awk -F ‘:‘ ‘/:80/{ips[$(NF-1)]++} END {for(i in ips){print i,ips[i]}}‘ |
十六. Awk数组案例
Nginx日志分析,日志格式如下: log_format main ‘$remote_addr - $remote_user [$time_local] "$request" ‘ ‘$status $body_bytes_sent "$http_referer" ‘ ‘"$http_user_agent" "$http_x_forwarded_for"‘;
52.55.21.59 - - [25/Jan/2018:14:55:36 +0800] "GET /feed/ HTTP/1.1" 404 162 "https://www.google.com/" "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; de) Presto/2.9.168 Version/11.52" "-"
1.统计2018年01月25日,当天的PV量 [root@Shell ~]# grep "25/Jan/2018" log.bjstack.log |wc -l [root@Shell ~]# awk "/25\/Jan\/2018/" log.bjstack.log |wc -l [root@Shell ~]# awk ‘/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips) {sum+=ips[i]} {print sum}}‘ log.bjstack.log //统计15-19点的pv量 [root@Shell ~]# awk ‘$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00 {print $0}"‘ log.bjstack.log |wc -l
2.统计2018年01月25日,一天内访问最多的10个IP [root@Shell ~]# awk ‘/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips){ print ips[i],i}}‘ log.bjstack.log |sort -rn|head //统计15-19点访问次数最多的10个IP [root@Shell ~]# awk ‘$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00"‘ log.bjstack.log |awk ‘{ips[$1]++} END {for(i in ips){print ips[i],i}}‘|sort -rn|head
3.统计2018年01月25日,访问大于100次的IP [root@Shell ~]# awk ‘/25\/Jan\/2018/ {ips[$1]++} END {for(i in ips){if(ips[i]>10){print i,ips[i]}}}‘ log.bjstack.log
4.统计2018年01月25日,访问最多的10个页面($request top 10) [root@Shell ~]# awk ‘/25\/Jan\/2018/ {request[$7]++} END {for(i in request){print request[i],i}}‘ log.bjstack.log |sort -rn|head
5.统计2018年01月25日,每个URL访问内容总大小($body_bytes_sent) [root@Shell ~]# awk ‘/25\/Jan\/2018/ {request[$7]++;size[$7]+=$10} END {for(i in request){print request[i],i,size[i]}}‘ log.bjstack.log |sort -rn|head
6.统计2018年01月25日,每个IP访问状态码数量($status) [root@Shell ~]# awk ‘{ip_code[$1 " " $9]++} END {for(i in ip_code){print ip_code[i],i}}‘ log.bjstack.log|sort -rn|head
7.统计2018年01月25日,访问状态码为404及出现的次数($status) [root@Shell ~]# grep "404" log.bjstack.log |wc -l [root@Shell ~]# awk ‘{if($9=="404") code[$9]++} END {for(i in code){print i,code[i]}}‘ log.bjstack.log
8.统计2018年01月25日,8:30-9:00访问状态码是404 [root@Shell ~]# awk ‘$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00" && $9=="404" {code[$9]++} END {for(i in code){print i,code[i]}}‘ log.bjstack.log [root@Shell ~]# awk ‘$9=="404" {code[$9]++} END {for(i in code){print i,code[i]}}‘ log.bjstack.log
9.统计2018年01月25日,各种状态码数量 [root@Shell ~]# awk ‘{code[$9]++} END {for(i in code){print i,code[i]}}‘ log.bjstack.log [root@Shell ~]# awk ‘{if($9>=100 && $9<200) {i++} else if ($9>=200 && $9<300) {j++} else if ($9>=300 && $9<400) {k++} else if ($9>=400 && $9<500) {n++} else if($9>=500) {p++}} END{print i,j,k,n,p,i+j+k+n+p}‘ log.bjstack.log
[root@Shell ~]# awk ‘{if($9>=100 && $9<200) {i++} else if ($9>=200 && $9<300) {j++} else if ($9>=300 && $9<400) {k++} else if ($9>=400 && $9<500) {n++} else if($9>=500) {p++}} END{print i?i:0,j?j:0,k?k:0,n?n:0,p?p:0,i+j+k+n+p}‘ log.bjstack.log |
原文:https://www.cnblogs.com/yyhlss/p/9484200.html