awk

awk 介绍

  • awk 是其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。

  • awk 是一个强大的文本分析工具。

  • awk 更像一门编程语言,他可以自定义变量,有条件语句,有循环,有数组,有正则,有函数等。

  • awk 按行读取数据,根据给出的条件进行查找,并在找出来的行中进行操作。

  • awk 有三种形势,awk,gawk,nawk,平时所说的awk其实就是gawk。

awk 命令

awk 命令格式

 awk [options] 'script' file(s) 
 awk [options] -f scriptfile file(s) 
  1. script,定义如何处理数据。

  2. file,是 awk 处理的数据来源,awk 也可以来自其它命令的输出。

  3. -f scriptfile 从脚本文件中读取awk命令,每行都是一个独立的script

script 格式如下:

 BEGIN { action }
 pattern { action }
 END { action }

脚本通常是被单引号或双引号包住,一个awk脚本通常由四部分组成:

  1. BEGIN { action } 语句块,awk 执行 pattern { action } 前要执行的脚本。

  2. pattern { action } 语句块,决定动作语句何时触发,可以是以下任意一种: - 正则表达式:使用通配符的扩展集。 - 关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试。 - 模式匹配表达式:使用运算符~(匹配)和 ~!(不匹配)。

  3. END { action } 语句块,awk 执行 pattern { action } 后要执行的脚本。

  4. action部分,决定对数据如何处理,由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大刮号内。常见的action包括:变量或数组赋值、输出命令、内置函数、控制流语句。

BEGIN { action }pattern { action }END { action }都是可选项目。

awk 工作流

  • 第一步执行 BEGIN { commands } 语句块中的语句。

在awk从输入输出流中读取行之前执行,通常在BEGIN语句块中执行如变量初始化,打印输出表头等操作。

  • 第二步从文件或标准输入中读取一行,然后执行 pattern { commands }语句块。它逐行读取数据,从第一行到最后一行重复这个过程,直到读取完所有行。

pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行。

{} 类似一个循环体,会对文件中的每一行进行迭代,通常将变量初始化语句放在BEGIN语句块中,将打印结果等语句放在END语句块中。

  • 第三步当读至输入流末尾时,执行 END { command }语句块。

在awk从输入流中读取完所有的行之后执行,比如打印所有行的分析结果,它也是一个可选语句块。

awk 示例

示例1:获取IP地址是10.1.8.10的网卡名

 [root@shell ~ 10:22:06]# ip addr | grep '10.1.8.10' 
     inet 10.1.8.10/24 brd 10.1.8.255 scope global noprefixroute ens33
 ​
 [root@shell ~ 10:22:18]# ip addr | grep '10.1.8.10' | awk '{print $NF}'
 ens33
 # 或者
 [root@shell ~ 10:22:24]# ip addr | awk '/10.1.8.10/ {print $NF}'
 ens33

示例2:查看使用率超过10的文件系统

 [root@shell ~ 10:24:04]# df -h
 Filesystem               Size  Used Avail Use% Mounted on
 devtmpfs                 2.0G     0  2.0G   0% /dev
 tmpfs                    2.0G     0  2.0G   0% /dev/shm
 tmpfs                    2.0G   12M  2.0G   1% /run
 tmpfs                    2.0G     0  2.0G   0% /sys/fs/cgroup
 /dev/mapper/centos-root   50G  1.6G   49G   4% /
 /dev/sda1               1014M  139M  876M  14% /boot
 /dev/mapper/centos-home  147G   33M  147G   1% /home
 tmpfs                    394M     0  394M   0% /run/user/0
 tmpfs                    394M     0  394M   0% /run/user/1000
 ​
 [root@shell ~ 10:24:06]# df -h | sed 's/%//' | awk '$5>10 {print $0}'
 Filesystem               Size  Used Avail Use Mounted on
 /dev/sda1               1014M  139M  876M  14 /boot
 # 或者
 [root@shell ~ 10:24:10]# df -h | awk '$5+1-1>10 {print $0}'
 /dev/sda1               1014M  139M  876M  14% /boot

示例3:提前系统运行数据。

包括:

  • CPU 使用率

  • 内存 使用率

  • 当前用户登录数

  • 当前系统负载

  • 系统运行进程数量

 [root@shell bin 10:43:30]# pwd
 /root/bin
 [root@shell bin 10:43:33]# vim monitor_os.sh
 #!/bin/bash
 os_info_file=/tmp/os_info.txt
 top -b -n 1 | head -n 5 > ${os_info_file}
 ​
 cpu_usage=$(awk '/^%Cpu/ {print $2+$4}' ${os_info_file})
 echo "CPU 使用率:${cpu_usage}"
 ​
 memory_usage=$(awk '/^KiB Mem/ {print ($4-$6)/$4}' ${os_info_file})
 echo "内存使用率:${memory_usage}"
 ​
 user_count=$(awk '/^top/ {print $6}' ${os_info_file})
 echo "在线用户数量:${user_count}"
 ​
 load_usage=$(awk '/^top/ {print $(NF-2),$(NF-1),$NF}' ${os_info_file})
 echo "当前系统负载:${load_usage}"
 ​
 running_process_count=$(awk '/^Tasks/ {print $4}' ${os_info_file})
 echo "系统运行进程数量:${running_process_count}"
 ​
 rm -f ${os_info_file}

思考题

统计一篇文章中出现频率最高的10个单词,并按照数量降序排序。

ansible 环境准备

ansible 架构

  • 控制节点:下发指令或文件到受控制节点。

  • 受控制节点:接受控制节点发过来的指令,并执行。

ansible 环境准备

实验环境

 10.1.8.10 controller.laoma.cloud controller
 10.1.8.11 server1.laoma.cloud server1
 10.1.8.12 server2.laoma.cloud server2
 10.1.8.13 server3.laoma.cloud server3
 10.1.8.14 server4.laoma.cloud server4

准备虚拟机模版

准备1台干净的centos 7 虚拟机。

注意:模版虚拟机的CPU和内存的配置,建议设置为1CPU和2G内存。

开发脚本sethost:

  • 不加参数执行sethost,则提示命令使用方法。

  • 加参数执行sethost,则第一个参数范围是10-14。超出范围也提示命令使用方法。

  • 正常执行示例:sethost 10,这设置正确的主机名和IP地址。

 [root@shell ~ 13:34:31]# vim /usr/local/bin/sethost
 #!/bin/bash
 ​
 # test root user
 (( UID!=0 )) && echo 'Please run as root.' && exit 1
 ​
 usage="Usage: $0 10-14"
 ​
 # test args number
 (($# !=1 )) && echo $usage && exit 2
 ​
 con_name=ens33
 domain_name=laoma.cloud
 ​
 host_id=$1
 ​
 if ((host_id==10));then
   HOSTNAME=controller.${domain_name}
 elif ((11<=host_id && host_id<=14)) ;then
   HOSTNAME=server$[host_id-10].${domain_name}
 else
   echo $usage
   exit 3
 fi
 ​
 hostnamectl set-hostname $HOSTNAME
 nmcli connection modify ${con_name} ipv4.addresses 10.1.8.${host_id}/24
 nmcli connection up ${con_name}
 ​
 hostname
 ip -br address
 [root@shell ~ 13:34:31]# chmod +x /usr/local/bin/sethost

关机打快照,快照名为ansible。

克隆虚拟机

基于模版虚拟机快照ansible,克隆出其他虚拟机,并使用sethost脚本设置主机名和IP地址。

以server1为例:

 [root@shell ~ 13:34:31]# sethost 11

配置 ansible 基础环境

在模版虚拟机上配置/etc/hosts,添加ansible主机清单

 [root@deploy ~ 14:51:11]# vim /etc/hosts
 127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
 ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
 ​
 ################# ansible ####################
 10.1.8.10 controller.laoma.cloud controller
 10.1.8.11 server1.laoma.cloud server1
 10.1.8.12 server2.laoma.cloud server2
 10.1.8.13 server3.laoma.cloud server3
 10.1.8.14 server4.laoma.cloud server4
 ################# ansible ####################

配置免密登录ansible节点:

 [root@deploy ~ 14:52:58]# ssh-keygen
 ​
 [root@deploy ~ 14:54:39]# \
 for host in controller server1 server2 server3 server4
 do
   sshpass -p123 ssh-copy-id root@$host
 done
 ​
 [root@deploy ~ 14:56:02]# for host in controller server1 server2 server3 server4; do ssh $host 'hostname;ip -br a show ens33;echo'; done
 controller.laoma.cloud
 ens33            UP             10.1.8.10/24 fe80::20c:29ff:fe14:2f8b/64 
 ​
 server1.laoma.cloud
 ens33            UP             10.1.8.11/24 fe80::20c:29ff:fe6a:559b/64 
 ​
 server2.laoma.cloud
 ens33            UP             10.1.8.12/24 fe80::20c:29ff:feec:ac41/64 
 ​
 server3.laoma.cloud
 ens33            UP             10.1.8.13/24 fe80::20c:29ff:fe19:59c1/64 
 ​
 server4.laoma.cloud
 ens33            UP             10.1.8.14/24 fe80::20c:29ff:feaa:4763/64 

在模版虚拟机上开发脚本weihu,用来集中管理其他机器。

  • weihu cmd command,将会在ansible 5台设备上执行command。

  • weihu copy src dest,将模版虚拟机上的src文件复制到ansible 5台设备dest位置。

 [root@deploy ~ 14:49:42]# vim /usr/local/bin/weihu
 #!/bin/bash
 ​
 function usage () {
   echo "Usage: weihu cmd COMMAND, 在集群中所有的机器上执行对应COMMAND命令"
   echo "Usage: weihu copy source target,将本地source文件,推送到集群中所有的机器上"
   exit
 }
 ​
 action=$1
 ​
 HOSTLIST='controller server1 server2 server3 server4'
 ​
 (( $#<=1 )) && usage
 ​
 case "$action" in
   "cmd")
     # 删除参数1
     shift
     COMMAND="$*"
     for host in $HOSTLIST
     do 
       ssh root@$host "$COMMAND"
     done
     ;;
   "copy")
     # 删除参数1
     shift
     for host in $HOSTLIST
     do 
       num=$#
       case $num in
         2)
           scp -r $1 root@$host:$2
           ;;
         #[3-9]|[1-9][0-9])
         [3-9])
       last=$(echo $* | awk '{print $NF}')
           args_exclude_last=$(echo $* | sed "s#$last##")
           scp -r ${args_exclude_last} root@$host:${last}
           ;;
         *)
           usage
       esac
     done
     ;;
   *)
     usage
     ;;
 esac
 [root@deploy ~ 14:50:49]# chmod +x /usr/local/bin/weihu

测试维护脚本

 root@deploy ~ 14:56:09]# weihu cmd hostname
 controller.laoma.cloud
 server1.laoma.cloud
 server2.laoma.cloud
 server3.laoma.cloud
 server4.laoma.cloud
 ​
 [root@deploy ~ 14:56:47]# weihu copy /etc/hosts /etc/hosts
 hosts                                                    100%  449   222.1KB/s   00:00    
 hosts                                                    100%  449   245.5KB/s   00:00    
 hosts                                                    100%  449   275.8KB/s   00:00    
 hosts                                                    100%  449   351.0KB/s   00:00    
 hosts                                                    100%  449   317.4KB/s   00:00
 ​
 ​
 [root@deploy ~ 14:57:33]# weihu cmd cat /etc/hosts
 127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
 ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
 ​
 ################# ansible ####################
 10.1.8.10 controller.laoma.cloud controller
 10.1.8.11 server1.laoma.cloud server1
 10.1.8.12 server2.laoma.cloud server2
 10.1.8.13 server3.laoma.cloud server3
 10.1.8.14 server4.laoma.cloud server4
 ......

准备一个专用的账户devops,用于控制节点远程登录其他节点。

 [root@deploy ~ 15:21:59]# weihu cmd useradd devops
 [root@deploy ~ 15:36:17]# weihu cmd id devops
 uid=1001(devops) gid=1001(devops) groups=1001(devops)
 uid=1001(devops) gid=1001(devops) groups=1001(devops)
 uid=1001(devops) gid=1001(devops) groups=1001(devops)
 uid=1001(devops) gid=1001(devops) groups=1001(devops)
 uid=1001(devops) gid=1001(devops) groups=1001(devops)
 ​
 [root@deploy ~ 15:36:22]# weihu cmd 'echo 123 | passwd --stdin devops'
 [root@deploy ~ 15:37:41]# sshpass -p 123 ssh devops@server1 id
 uid=1001(devops) gid=1001(devops) groups=1001(devops)
 ​
 # 配置devops账户,免密提权为root
 [root@deploy ~ 15:39:17]# weihu cmd "echo 'devops ALL=(ALL)NOPASSWD: ALL' > /etc/sudoers.d/devops"

配置控制节点使用devops账户免密登录所有ansible节点。

 [root@deploy ~ 00:06:40]# sshpass -p123 ssh devops@controller 'ls .ssh'
 ls: cannot access .ssh: No such file or directory
 [root@deploy ~ 00:08:28]# sshpass -p123 ssh devops@controller 'mkdir -m 700 .ssh'
 ​
 [root@deploy ~ 15:47:55]# sshpass -p123 ssh devops@controller 'ssh-keygen -t rsa -N "" -f .ssh/id_rsa'
 [root@deploy ~ 15:48:30]# sshpass -p123 ssh devops@controller 'for host in controller server1 server2 server3 server4;do sshpass -p123 ssh-copy-id devops@$host;done'
 ​
 # 验证控制节点免密登录其他节点
 [devops@controller ~ 15:50:01]$ for host in controller server1 server2 server3 server4;do ssh devops@$host id;done
 uid=1001(devops) gid=1001(devops) groups=1001(devops)
 uid=1001(devops) gid=1001(devops) groups=1001(devops)
 uid=1001(devops) gid=1001(devops) groups=1001(devops)
 uid=1001(devops) gid=1001(devops) groups=1001(devops)
 uid=1001(devops) gid=1001(devops) groups=1001(devops)
 ​
 [devops@controller ~ 15:50:12]$ for host in controller server1 server2 server3 server4;do ssh devops@$host sudo id;done
 uid=0(root) gid=0(root) groups=0(root)
 uid=0(root) gid=0(root) groups=0(root)
 uid=0(root) gid=0(root) groups=0(root)
 uid=0(root) gid=0(root) groups=0(root)
 uid=0(root) gid=0(root) groups=0(root)

ansible 配置

部署 ansible软件

控制节点

 [devops@controller ~ 16:31:42]$ sudo yum install -y ansible

受管理节点

 [root@deploy ~ 16:36:44]# weihu cmd yum install -y python

配置主机清单

ansible管理的主机信息要保存到一个文件中,这个文件称之为主机清单(inventory)。

 [devops@controller ~ 16:33:11]$ mkdir ansible
 [devops@controller ~ 16:38:45]$ cd ansible/
 [devops@controller ansible 16:38:47]$ vim inventory
 controller
 server1
 server2
 server3
 server4
 ​
 [devops@controller ansible 16:43:15]$ ansible -i inventory -m command -a 'id' server1
 server1 | CHANGED | rc=0 >>
 uid=1001(devops) gid=1001(devops) groups=1001(devops)
 # 参数说明:
 # -i inventory,主机清单位置
 # -m command,使用命令模块
 # -a 'hostname',模块对应的具体参数
 # server1,针对哪个机器操作
 ​
 [devops@controller ansible 16:43:41]$ ansible -i inventory -m command -a 'id' -b server1
 server1 | CHANGED | rc=0 >>
 uid=0(root) gid=0(root) groups=0(root)
 # -b 提权为root操作
 ​
 # 使用user模块管理用户
 [devops@controller ansible 16:43:00]$ ansible -i inventory -m user -a 'name=zhangsan state=present' -b server1
 server1 | CHANGED => {
     "ansible_facts": {
         "discovered_interpreter_python": "/usr/bin/python"
     }, 
     "changed": true, 
     "comment": "", 
     "create_home": true, 
     "group": 1002, 
     "home": "/home/zhangsan", 
     "name": "zhangsan", 
     "shell": "/bin/bash", 
     "state": "present", 
     "system": false, 
     "uid": 1002
 }
 [devops@controller ansible 16:43:46]$ ansible -i inventory -m command -a 'id zhangsan' server1
 server1 | CHANGED | rc=0 >>
 uid=1002(zhangsan) gid=1002(zhangsan) groups=1002(zhangsan)
 ​
 # 删除用户
 [devops@controller ansible 16:44:33]$ ansible -i inventory -m user -a 'name=zhangsan state=absent remove=yes' -b server1
 server1 | CHANGED => {
     "ansible_facts": {
         "discovered_interpreter_python": "/usr/bin/python"
     }, 
     "changed": true, 
     "force": false, 
     "name": "zhangsan", 
     "remove": true, 
     "state": "absent"
 }
 [devops@controller ansible 16:45:49]$ ansible -i inventory -m command -a 'id zhangsan' server1
 server1 | FAILED | rc=1 >>
 id: zhangsan: no such usernon-zero return code

分组主机清单

 [devops@controller ansible 16:45:53]$ vim inventory 
 [controllers]
 controller
 ​
 [webs]
 server1
 server2
 ​
 [dbs]
 server3
 server4

测试

 # 针对webs主机组操作
 [devops@controller ansible 16:48:55]$ ansible -i inventory -m command -a 'hostname' -o webs
 server2 | CHANGED | rc=0 | (stdout) server2.laoma.cloud
 server1 | CHANGED | rc=0 | (stdout) server1.laoma.cloud
 # -o 输出内容合并为一行
 ​
 # all代表所有机器
 [devops@controller ansible 16:49:03]$ ansible -i inventory -m command -a 'hostname' -o all
 server2 | CHANGED | rc=0 | (stdout) server2.laoma.cloud
 server1 | CHANGED | rc=0 | (stdout) server1.laoma.cloud
 controller | CHANGED | rc=0 | (stdout) controller.laoma.cloud
 server3 | CHANGED | rc=0 | (stdout) server3.laoma.cloud
 server4 | CHANGED | rc=0 | (stdout) server4.laoma.cloud
 ​
 # web主机组安装nginx
 [devops@controller ansible 16:51:41]$ ansible -i inventory -m yum -a 'name=nginx state=present' -b webs
 ​
 # web主机组卸载nginx
 [devops@controller ansible 16:51:41]$ ansible -i inventory -m yum -a 'name=nginx state=absent' -b webs

查看模块帮助

 # 查看模块清单,并过滤出yum相关信息
 [devops@controller ansible 16:53:41]$ ansible-doc -l | grep yum
 yum                                                           Manages packages with the `yum' package manager  
 yum_repository                                                Add or remove YUM repositories  
 # 查看yum模块帮助信息
 [devops@controller ansible 16:53:47]$ ansible-doc yum
 # 直接搜索EXAMPLE
 # 部分内容如下:
 EXAMPLES:
 ​
 - name: install the latest version of Apache
   yum:
     name: httpd
     state: latest
 ​
 - name: ensure a list of packages installed
   yum:
     name: "{{ packages }}"
   vars:
     packages:
     - httpd
     - httpd-tools
 ​
 - name: remove the Apache package
   yum:
     name: httpd
     state: absent
 ​
 - name: install the latest version of Apache from the testing repo
   yum:
     name: httpd
     enablerepo: testing
     state: present
 ...

ansible最大的特点:

  1. 简单:只要能看懂English就行。

  2. 幂等性:多次执行,结果一致。假设第一次执行软件包未安装,则执行安装。第二次执行,则不需要做任何事情。

playbook 编写和执行

通过编写playbook,完成重复、复杂的任务。

  • ansible 命令类似于 shell 中单个命令。

  • playbook 类似于 shell 脚本。

 [devops@controller ansible 16:55:36]$ vim deploy_web.yaml
 ​
 #粘贴不乱码
 :set paste
 # yaml格式起始行,一般不省略
 ---
 ​
 # Playbook中第一个play
 # play具有属性:name,hosts,become,tasks,缩进一致
 # name属性,用于简要描述play
 - name: debploy WebSite
 ​
   # hosts属性,用于定义要在哪个受管理节点执行
   hosts: webs
 ​
   # tasks属性,用于描述play中任务,属性是列表格式
   tasks:
 ​
     # 第一个任务
     # 任务具有属性:涵name和模块名等。
     # name属性,用于简要描述任务
     - name: latest version of httpd and firewalld installed
       # 指明模块名,也就是要执行的任务
       yum:
         # 指定要操作的rpm包名称
         name:
           # rpm包名称是-开头的列表格式,或者逗号分隔的列表格式
           - httpd
           - firewalld
 ​
         # 定义软件包的状态,lastet代表升级为最新版本
         state: latest
 ​
     # 第二个任务
     - name: prepare index.html
       # copy 模块,用于将content属性值写入到目标文件
       copy:
         content: "Welcome to {{ ansible_fqdn }} WebSite!\n"
         dest: /var/www/html/index.html
 ​
     # 第三个任务
     - name: enable and start httpd
       # service模块,用于启用并启动httpd服务
       service:
         name: httpd
         enabled: true
         state: started
 ​
     # 第四个任务
     - name: enable and start firewalld
       # service模块,用于启用并启动firewalld服务
       service:
         name: firewalld
         enabled: true
         state: started
 ​
     # 第五个任务
     - name: firewalld permits access to httpd service
       # firewalld,用于放行http服务
       firewalld:
         service: http
         permanent: true
         state: enabled
         immediate: yes
 ​
 # Playbook中第二个play,-开头表示列表
 - name: Test WebSite
   hosts: localhost
   become: no
   tasks:
     - name: connect to intranet web server
       # uri模块,用于测试网站是否可以访问
       uri:
         url: http://{{item}}
       loop:
         - server1
         - server2
 ​
 # yaml格式结束行,一般省略
 ...
 # 执行剧本
 [devops@controller ansible 17:01:40]$ ansible-playbook -i inventory -b deploy_web.yaml
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐