脚本开发与自动化运维----shell脚本开发及其在DevOps中的应用

发布于:2024-04-19 ⋅ 阅读:(22) ⋅ 点赞:(0)

一.正则表达式

  1. 正则表达式(Regular Expression、regex 或 regexp, 缩写为RE), 又称规则表达式,是计算机科学中的一个概念。正则表通常被用来检索、替换那些符合某个模式(规则)的文本。正则表达式是对字符串(包括普通字符(例如, a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式, 就是用事先定义好的一些特定字符、及这些特定字符的组合, 组成一个“规则字符串”, 这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,模式描述在搜索文本时要匹配的一个或多个字符串。
  2. 正则表达式这个概念最初是由 Unix中的工具软件(例如 sed 和grep)普及开的。支持正则表达式的指令如: locate|find|vim|grep|sed|awk, 我们将详细讲解grep|sed|awk。
  3. 正则表达式由元字符组成,元字符是在正则表达式中具有“特殊意义的专用字符”。不同的字符有不同的含义,有的元字符可以表示一类字符,因此由元字符组成的正则表达式可以表示一类字符,当构建好一个规则, 并设计好能准确表达这个规则的正则表达式, 那么就可以使用这个正则表达式从指定内容中获取符合这个规则的内容, 或者判断某个内容是否符合这个规则。
元字符 说明 实例 匹配的字符串示例
一般字符 匹配自身 haha haha
匹配除换行'\n'以为的任意一个字符,在DOTALL模式中也能匹配换行符。 a.c abc,adc.....
\ 转义字符串,改变后一个字符的意思 a\.c a.c
[...] 字符集,对应位置可以是其中的任意一个字符 a[bcd]e abe,ace,ade
\d 数字,等价于[0-9]

a\dc

a[0-9]/c

a1c,a2c....

[:lower:] 小写字母
[:upper:] 大写字母
[:punct:] 标点符号
[:space:] 换行符、回车等空白字符

二.grep

  1. grep命令是一种强大的文本搜索工具, 它能使用正则表达式搜索文本, 并把匹配的行打印出来(匹配到的标红)。grep全称是 Global Regular Expression Print, 表示全局正则表达式打印。
  2.  grep的工作方式是, 在一个或多个文件中搜索字符串模板, 模板后的所有字符串被看作文件名。搜索的结果被送到标准输出, 不影响原文件内容。
  3.  grep可用于 shell脚本, 因为 grep通过返回一个状态值来说明搜索的状态, 如果模板搜索成功, 则返回0, 如果搜索不成功,则返回1, 如果搜索的文件不存在, 则返回2。我们利用这些返回值就可进行一些自动化的文本处理工作。

egrep= grep-E: 扩展的正则表达式(除了\<,\>,\b 使用其他正则都可以去掉\)。

  • 【命令格式】gre p [option] pattern file
  • 【功能】用于过滤、搜索特定的字符。

【命令参数】

  •  -A<显示行数>: -A NUM,--after-context = NUM, 除了显示符合范本样式的那一行之外, 并显示该行之后的内容。
  •  -B<显示行数>: --before-context=NUM, 除了显示符合样式的那一行之外, 并显示该行之前的内容。
  •  -C<显示行数>: -NUM,--context=NUM, 除了显示符合样式的那一行之外, 并显示该行之前后的内容。
  • -c: 统计匹配的行数
  • -e : 实现多个选项间的逻辑 or 关系 
  • -E: 扩展的正则表达式,grep-E等同于 egrep
  • -fFUE:从 FILE 获取 PATTERN 匹配
  • -F: 相当于 fgrep
  • -i-ignore-case#忽略字符大小写的差别。
  • -n: 显示匹配的行号
  • -o: 仅显示匹配到的字符串
  • -q: 静默模式,不输出任何信息
  • -s: 不显示错误信息.
  • -v: 显示不被 pattern 匹配到的行, 相当于[^] 反向匹配
  • -w: 匹配 整个单词

1.案例(匹配字符)

本例主要练习匹配字符。root用户家目录下的 test01. prel文件为匹配规则、test01 文件为普通文本文件。使用grep按照test01. prel中指定规则匹配文件test01中的字符。

 1.显示含有字符A的行,及后一行

2.显示含有字符A的行,及前一行:

3.显示含有字符A的行,及前后各一行

4.统计含有aaa的行数

5.显示含有AAA或bbb的行:

6.从文件test01.prel获取匹配规则:创建test01.prel

7.显示含有b的行,忽略·大小写并显示所在行号:

8.匹配字符串Aa:

9.静默模式匹配字符aa:

10.显示没有匹配到aa的行:

11.精确匹配单词aa:

2.案例(匹配次数相关正则使用)

【例 2-2】本例主要练习匹配次数相关正则的使用。在 root用户家目录下有文件test_grep_02, 使用正则, 匹配字符。注意, 第三行为 Tab缩进后换行、第四行为四个空格后回车、第五第六行为回车空行。

1.匹配除了换行外,任意单个字符:

2.匹配字符a、/:

3.匹配abc之外的字符:

4.匹配字母和数字:

5.匹配字母:

6.匹配数字:

7.匹配字母a-z:

8.匹配空格:

9.匹配标点符号:

3.案例(位置锚点)

【例2-3】本例主要练习位置锚定, 即定位出现的位置相关正则的使用。在 root用户家目录下有文件test_grep_03, 使用正则, 匹配字符。

1.匹配"o"0次或任意多次:

2.匹配"o"任意多次,不包括0次

3.匹配"o"0次或者1次:

4.匹配“o”至少1次

5.匹配"o"1-2次:

6.匹配“o”至少10次:

7.匹配"o"至多10次:

4.使用正则,匹配字符

【例2-4】在 root用户家目录下有文件test_grep_04,使用正则, 匹配字符。注意, 第二行为Tab空格, 第三、第四为空行。

1.行首锚定,匹配出行首为a的行:

2.行尾锚定,匹配出行尾为b的行:

3.匹配出空行:

4.匹配出以空格开头的行:

5.词首、词尾锚定,匹配出词首为a、词尾为b的词

5.分组

通过\(\)将一个或多个字符捆绑在一起,当作一个整体进行处理。分组括号中的模式匹配到的内容,会被正则表达式引擎记录在内部变量中, 这些变量的命名方式是\1,\2,\3……

6.后向引用

引用前面的分组中的模式所匹配的字符。\1 表示从左侧起第一个括号以及与之匹配右括号之间的模式所匹配到的字符;\2 表示从左侧其第二个括号以及与之匹配右括号之间的模式所匹配的字符;\&表示前面的分组中匹配的所有字符。如图2-1为后向引用示意图。

7.案例(分组和后向引用相关正则表达式) 

【例2-5】本例主要练习分组和后向引用相关正则的使用。在用户家目录下有test_grep_05文件, 使用正则, 匹配满足条件的字符。

1.匹配以He开头的分组:

2.匹配以He开头、He结尾的分组:

3.匹配He.*wo开头、wo结尾的分组

三.sed

 sed 是 stream editor 的缩写, 中文称之为“流编辑器”。sed 命令是一个面向行处理的工具, 它以“行”为处理单位,针对每一行进行处理, 处理后的结果会输出到标准输出(STDOUT)。sed 命令不会对读取的文件做任何贸然的修改,而是首先将内容都输出到标准输出中。

1.sed 工作流

首先, sed把当前正在处理的行, 保存在一个临时缓存区中(也成为模式空间),然后处理临时缓冲区中的行, 完成后, 把该行回显到屏幕上;
sed把每一行都存在临时缓冲区,对这个副本进行编辑, 所以不会修改源文件;
sed 主要用来自动编辑一个或多个文件;简化对文件的反复操作,编写转换程序等。

2.sed使用方法

 sed 常见的使用方法有两种, 一种为“命令行”模式; 另一种为“脚本”模式。可类比Python语言学习时, 两种编程方式。
【命令格式】sed [参数]'[地址定界] command'file
【功能】用于过滤、搜索特定的字符。
【参数】:

-i -- -i-place 直接将处理的结果写入文件

【command】常用的有如下几种:

  • d: 表示删除行。
  • p: 打印该行。
  • a:在当前行之后插入新行新内容, 每行末尾需要使用‘\’续行。
  • i: 在当前行之前插入新行新内容, 每行末尾需要使用‘\’续行。
  • c: c符号后的新行新内容, 替换当前行中的文本, 每行末尾需要使用‘\’续行, 整行替换。
  • r:读取指定文件的内容。
  • w:写入指定文件。
  • s: 替换指定字符。 

3.参数-n

  • -n:静默模式。不能出模式空间内容到屏幕
案例

在root用户家目录下有文件test01,对文件进行处理:

使用静态模式和非静态模式,输出含有"4"的行。

       注意观察, 在非静默模式下, 由于打印输出到4时, 符合“模板”匹配规则, 故将结果直接回显打印在了屏幕上;而静默模式下, 仅仅输出了符合“模板”匹配规则的结果,文本本身没有被输出, 相当于输出静默。
      -n常常和p命令一起使用, 仅输出那些匹配的行, 无关行不做输出。

4.命令p、命令d

  • d:表示删除行
  • p:打印该行 

续test06案例

1.分别输出第1行、第2行、第3~4行、最后一行

2.删除第1行,并查看原文件是否发生变化

通过观察输出和查看源文件, 发现, sed 执行结果并不影响原文件。执行删除行的指令后,原文件内容不变。

5.命令a、命令i和命令c

  • a: 在当前行之后插入新行新内容, 每行末尾需要使用‘\’续行;
  • is:在当前行之前插入新行新内容, 每行末尾需要使用‘\’续行;
  • c: c符号后的新行新内容,替换当前行中的文本, 每行末尾需要使用“\’续行,整行替换。

续案例test06

1.向最后一行之后添加9999:

2.向当前行之后插入文本9999

3.向当前行之前插入文本6666:

4.向末行之前插入文本6666

5.用文本Hello world替换第5行:

6.用文本hello world替换每一行:

7.向末行插入多行文本yyyy换行8888:

注意:为了实现多行文本插入,在每一行需要加续行符“\”

6.命令r、命令w

  • r: 读取指定文件的内容。
  • w: 写入指定文件。

将/etc/hosts拷贝到用户家目录下, 重命名为 cp_hosts。对文件执行以下操作:

1.将cp_hosts的内容append到test06的第三行后

2.将cp_hosts的内容append到test06的末行后:

将/etc/passwd拷贝到用户家目录下,重命名为cp_passwd

1.将test06的内容覆盖写到cp_passwd文件中

2.将test06的末尾行内容,覆盖写到cp_passwd文件中

7.命令s与参数-i

  • s:替换指定字符
  • -i:直接将处理结果写到文件中。

在root用户家目录下有文件test07,对该文件进行处理

1.替换test07中的"This"为"Doudou",原文件内容不变

2.修改test07,将其中的"This"替换为"Doubu"

8.运维实例

为ubuntu安装ssh服务,并修改配置文件,使得ssh服务root用户允许远程

创建test01.sh文件,在文件中添加相应得配置

#!/bin/bash 
# 查询是否安装了 ssh 服务,结果重定向到临时文件 temp_text 中 
dpkg -l | grep ssh > temp_text
if [ $? -ne 0 ]
then
        # 安装 ssh 服务 
        sudo apt-get install openssh-server -y
        # 修改配置,允许 root 远程登录 
                cat /etc/ssh/sshd_config | grep ^#PermitRootLogin |sed -i 's/prohibitpassword/yes/' /etc/ssh/sshd_config |sed -i 's/#//' /etc/ssh/sshd_config 
 fi
# 查询是否开启了 ssh 服务,结果重定向到临时文件 temp_text 中 
ps -e | grep ssh > temp_text
if [ $? -ne 0 ]
then
sudo /etc/init.d/ssh start
fi

使用bush test01.sh启动文件,使用cat temp_test查看临时文件

使用以上安装ubuntu脚背作为模版,安装nginx
创建test02.sh文件,在文件中添加相应得配置

#!/bin/bash
# 查询是否安装了 ssh 服务,结果重定向到临时文件 temp_text 中
dpkg -l | grep nginx > temp_text
if [ $? -ne 0 ]
then
# 安装 ssh 服务
sudo apt-get install nginx -y
# 修改配置,允许 root 远程登录
fi
# 查询是否开启了 ssh 服务,结果重定向到临时文件 temp_text 中
ps -e | grep nginx > temp_text
if [ $? -ne 0 ]
then
sudo systemctl start nginx
fi
  • 第1行: 指定 shell解释器;
  • 第3行判断是否已经安装ssh, 并将结果覆盖重定向到文件temp_text中;
  • 第4~10行: if分支结构, 如果第3行指令执行失败, 即未安装 ssh, 则通过 apt-get包管理工具,安装 openssh-server服务(第7行); 然后获取ssh服务的配置文件, 从中筛选出配置允许 root用户远程登录所在行, 并将该行内容中 prohibit-password修改为yes, 并取消注释, 使用参数’-i’将结果直接写入文件中;
  • 第12行: 查看当前所有动态进程中, 是否有 ssh;
  • 第13~16行: 如果当前 ssh为非动态进程, 重启ssh服务。 

在使用bash test02.sh, 生成临时文件temp_text

查看临时文件

四.awk

  1. awk是一个强大的文本分析工具(awk源于三位创始人 Alfred Aho,Peter Weinberger,和 Brian Kernighan 的 Family Name 的首字符), 相对于 grep的查找, sed的编辑, awk在其对数据分析并生成报告时, 显得尤为强大。
  2. 简单来说 awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。awk可以非常方便、高效地操作文档以及字符,从而实现想要的格式。
  3. awk 有3个不同版本:awk、nawk和gawk,未作特别说明, 一般指gawk, gawk 是AWK 的 GNU 版本。实际上, awk 的确拥有自己的语言——awk 程序设计语言,三位创建者已将它正式定义为“样式扫描和处理语言”。允许用户创建简短的程序, 这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

1.awk基本语法

【使用方法】awk'{pattern+ action}'{filenames}

  •  awk 是由 pattern 和action组成, pattern为模式, 表示 awk 在数据中查找的内容, 而 action是在找到匹配内容时所执行的一系列命令。{}花括号用于根据特定的模式对一系列指令进行分组, 可不出现。
  • 模式可以是/正则表达式/、关系表达式、模式匹配表达式、BEGIN 语句块、pattern语句块、END 语句块种或者什么都没有(全部匹配)。具体的, 将在后面的内容详细说明。

 action由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开, 并位于大括号内, 可以是如下几种, 或者什么都没有(print):

  • 变量或数组赋值;
  • 输出命令;
  • 内置函数;
  • 控制流语句。

【命令格式】

  • awk[选项参数]'script' var= value file(s)
  • awk [选项参数]-f scriptfile var= value file(s)

【参数】:

参数 完整参数 说明
-F fs fs 指定输入分隔符,fs 可以是字符串或正则表达式
-v 赋值一个用户定义变量,将外部变量传递给 awk
-f 从脚本文件中读取 awk 命令

【内置变量】

参数 含义
ARGC 命令行参数个数
ARCV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk 浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行 -F 选项
NF 浏览记录的域的个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符

 2.记录、域、域分隔符

记录
  • awk 把每一个以换行符\n 结束的行成为一个记录。
  • 记录分隔符:默认的输入输出分隔符为回车,保存在内建变量 ORS 和 RS 中。 $0 变量:指的是整条记录。如 awk ‘{print $0}’ test 将输出 test 文件中的所有记录。
  • 变量 NR:一个计数器,处理完一条记录,NR 的值就增加 1。
 域

记录中每个单词称作“域”,默认情况下,以空格或 tab 分隔。awk 可跟踪域的个数, 并在内建变量 NF 中保存该值。

域分隔符

内建变量 FS 保存输入域分隔符的值,默认为空格或 tab。可以通过-F 命令行选项修 改 FS 的值。如 tail -n 5 /etc/passwd |awk -F : '{print $1,$5}',将以冒号为分隔符,打印出/etc/passwd 文件后 5 行的第一、第五列的内容

案例:获取 test,并在记录前显示记录号。(先执行 last -n 5 >> test, 将最近的系统登录记录重定向到文件 test中)

awk '{print $0}' test
awk '{print NR,$0}' test
awk '{print NR,NF}' test
awk '{print NR,NF,$0}' test
awk '{print NR,NF,$0,FS}' test
awk -F , '{print NR,NF,$1,FS}' test
awk -F , '{print NR,NF,$2,FS}' test

awk 工作流程是:读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符 划分域,填充域。$0 则表示所有域,$1 表示第一个域,$n 表示第 n 个域。默认域分隔 符是"空白键" 或 "[tab]键"。所以,在例 2-7 中,$1 表示登录用户,$3 表示登录用户 ip, 以此类推。

  • print 进行信息的输出。
  • {}用来分组,增加语句的可读性。

3.模式

模式表示 awk 在数据中查找的内容,可以是以下几种或者什么都没有(全部匹配):

/正则表达式/

使用通配符的扩展集。

搜索test 中第一行所有内容。

awk -F , '/a/' test

搜索test 中第一行中的开头的内容。

awk -F , '/a/{print $1}' test

关系表达式

使用运算符进行操作,可以是字符串或数字的比较。常用的运算符有:

案例:统计test文件中的行数

wk -F , '{count++}END{print count}' test

统计当前目录下文件占用的字节数

ls -l | awk '{print $5}'
ls -l | awk 'BEGIN{size=0;}{size = size+$5} END{print $5}'
ls -l | awk 'BEGIN{size=0;}{size = size+$5} END{print size}'

统计test中f出现的个数

awk '{count+=gsub('/f/', 'q')}END{print count}' test

统计test中a出现的个数

awk '{count+=gsub('/a/', 'q')}END{print count}' test

注意,统计不包括文件夹的子目录。ls 无法获取文件夹真实的大小。如果希望查看 文件夹真实的大小,可以借助 du 指令获取,如 du -ah --max-depth = 1 将包括隐藏文件 在内的所有文件大写列出来,仅显示到第一层。

模式匹配表达式

用运算符~(匹配)和!~(不匹配)。~表示表达式结果为真,!~表示表达式结果为假。 如 awk 'BEGIN{info="Hello world!";if( info ~ /Hello/){print "yes"}}' , awk 'BEGIN{info="Hello world!";if( info !~ /Hello/){print "no"}}'。

BEGIN 模块

用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。

BEGIN 模块后紧跟着动作块,该动作块在 awk 处理任何输入文件之前执行。所以它 可以在没有任何输入的情况下进行测试。它通常用来改变内建变量的值,如 OFS,RS 和FS 等,以及打印标题。如:$ awk 'BEGIN{FS = ":"; OFS = "\t"; ORS = "\n\n"}{print $1,$2,$3} test,表示在处理输入文件以前,域分隔符(FS)被设为冒号,输出文件分隔符(OFS)被设 置为制表符,输出记录分隔符(ORS)被设置为两个换行符。再如$ awk 'BEGIN{print "TITLE TEST"},只打印标题。

END 模块

用户在最后一条输入记录被读取之后发生的动作。 END 不匹配任何的输入文件,但是执行动作块中的所有动作,它在整个输入文件处 理完成后被执行。如$ awk 'END{print "The number of records is" NR}' test,表示将打印所 有被处理的记录数。  

案例:从/etc/passwd 中获取后 5 行的用户和相应的 shell,在第一行添加行“name,shell”,最后一行添加“blue,/bin/nosh”用户和 shell 之间用“,”分割。

cat /etc/passwd
tail -n 5 /etc/passwd
tail -n 5 /etc/passwd | awk -F ':' 'BEGIN{print "name,shell"} {print $1","$7} END{print "blue,/bin/nosh"}'

awk 工作流程是:先执行 BEGIN,然后读取文件,读入有\n 换行符分割的一条记录, 然后将记录按指定的域分隔符划分域,填充域,$0 则表示所有域,$1 表示第一个域,$n 表示第 n 个域,随后开始执行模式所对应的动作 action。接着开始读入第二条记 录······直到所有的记录都读完,最后执行 END 操作。

4.实训案例

获取本机网络地址

本案例主要实现对 ubuntu 系统 IP 信息的获取。文件为 root 用户家目录下 get_ip.sh脚本。

#!/bin/bash 
ip -a addr | grep inet | grep -v inet6 | awk '{print $2}'| grep -v '192.168.200.101' |awk -F / '{print $1}'
 提取有效行

提取/etc/hosts 文件中的有效行(即注释行以及空行之外的行)

cat /etc/hosts
cat /etc/hosts |grep -v '^#' |grep -v '^$'

操作系统信息获取与状态分析

本案例主要实现对操作系统信息获取与系统运行状态分析。root 用户家目录下,sys_monitor.sh 脚本,实现以下功能:

功能一:提取操作系统信息(内核、系统版本、网络地址等);