Bootstrap

shell脚本编程实践(七)

1 sed命令

1.1 进阶实践

1.1.1 脚本实践

案例需求

需求

案例描述:
    搭建一个ftp服务器

属性要求
    1 不支持本地用户登录        
        local_enable=NO
    2 匿名用户可以上传 新建 删除     
        anon_upload_enable=YES  anon_mkdir_write_enable=YES    
    3 匿名用户限速500KBps  
        anon_max_rate=500000

准备工作

使用sed获取ip地址
ipaddr=$(ifconfig eth0 | sed -n '2p' | sed -e 's/.*inet \(.*\) net.*/\1/g')
iptail=$(echo $ipaddr|cut -d'.' -f4)
ipremote=10.0.0.13
修改主机名
hostname server$iptail.localhost.com
echo "HOSTNAME=server$iptail.localhost.com" >> /etc/sysconfig/network
echo "$ipaddr server$iptail.localhost.com" >> /etc/hosts

环境部署

安装软件
yum -y install vsftpd lftp

备份配置
cp /etc/vsftpd/vsftpd.conf{
   ,.default}

清理无效信息
sed -rn '/^(#|$)/!p' /etc/vsftpd/vsftpd.conf
sed -ri '/^#/d;/^$/d' /etc/vsftpd/vsftpd.conf

禁止本地登录
sed -i '/local_enable/c\local_enable=NO' /etc/vsftpd/vsftpd.conf

允许匿名操作
sed -i '$a anon_upload_enable=YES' /etc/vsftpd/vsftpd.conf
sed -i '$a anon_mkdir_write_enable=YES' /etc/vsftpd/vsftpd.conf
sed -i '$a anon_other_write_enable=YES' /etc/vsftpd/vsftpd.conf
sed -i '$a anon_max_rate=512000' /etc/vsftpd/vsftpd.conf

启动服务
service vsftpd restart

数据操作

测试验证
chmod 777 /var/ftp/pub
cp /etc/hosts /var/ftp/pub

测试下载
cd /tmp
lftp $ipaddr <<end
cd pub
get hosts
exit
end

检查下载后的文件
ls /tmp/hosts
    注意:文件存在则匿名用户下载成功


测试上传、创建目录、删除目录等
cd /tmp
lftp $ipaddr << end
cd pub
mkdir test1
mkdir test2
put /etc/group
rmdir test2
exit
end

测试效果
tree /var/ftp/pub/ 
    注意:文件存在则匿名用户操作成功

简单实践

脚本实践

查看脚本内容
[root@localhost ~]# cat vsftpd_install_manager.sh
#!/bin/bash
# 功能:定制vsftpd环境部署功能
# 版本:v0.1
# 作者:书记
# 联系:www.superopsmsb.com

# 定制普通变量
net_card="eth0"
vsftpd_conf='/etc/vsftpd/vsftpd.conf'

# 定制命令变量
ipaddr=$(ifconfig ${
   net_card} | sed -n '2p' | sed -e 's/.*inet \(.*\) net.*/\1/g')
iptail=$(echo $ipaddr|cut -d'.' -f4)

# 定制目标类型变量
target_type=(部署 下载 操作)

# 定制服务的操作提示功能函数
menu(){
   
    echo -e "\e[31m---------------管理平台登录界面---------------"
    echo -e " 1: 部署软件 2: 下载测试  3: 操作测试"
    echo -e "-------------------------------------------\033[0m"
}

# 设定主机名
hostname_set(){
   
    hostname server$iptail.localhost.com
    echo "HOSTNAME=server$iptail.localhost.com" >> /etc/sysconfig/network
    echo "$ipaddr server$iptail.localhost.com" >> /etc/hosts
}

# 软件安装
softs_install(){
   
    read -p "请输入需要安装的软件,多个用空格隔开:" soft
    yum -y install $soft &>/dev/null
}

# 修改配置
update_config(){
   
    cp ${
   vsftpd_conf}{
   ,.default}
    sed -ri '/^#/d;/^$/d' ${
   vsftpd_conf}
    sed -i '/local_enable/c\local_enable=NO' ${
   vsftpd_conf}
    sed -i '$a anon_upload_enable=YES' ${
   vsftpd_conf}
    sed -i '$a anon_mkdir_write_enable=YES' ${
   vsftpd_conf}
    sed -i '$a anon_other_write_enable=YES' ${
   vsftpd_conf}
    sed -i '$a anon_max_rate=512000' ${
   vsftpd_conf}
    service vsftpd restart &>/dev/null && echo "vsftpd服务启动成功"
}

# 定制部署流程
soft_deploy(){
   
    hostname_set
    softs_install
    update_config
}

# 匿名用户测试下载动作
download_test(){
   
    # 准备数据目录及配套文件
    chmod 777 /var/ftp/pub
    cp /etc/hosts /var/ftp/pub

    # 测试演示
    cd /tmp
    lftp $ipaddr <<-end
    cd pub
    get hosts
    exit
        end
}

# 匿名用户测试操作权限
operator_test(){
   
    #测试上传、创建目录、删除目录等
    cd /tmp
    lftp $ipaddr <<-end
    cd pub
    mkdir test1 test2
    put /etc/group
    rmdir test2
    exit
        end
}

# 定制业务逻辑
while true
do
    menu
    read -p "> 请输入要操作的目标类型: " target_id
    if [ ${
   target_type[$target_id-1]} == "部署" ];then
        echo "开始登录管理平台..."
        soft_deploy

    elif [ ${
   target_type[$target_id-1]} == "下载" ];then
        download_test
        # 测试结果
        if [ -f /tmp/hosts ];then
            echo "匿名用户下载成功"
            rm -f /tmp/hosts
        else
            echo "匿名用户下载失败"
        fi
    elif [ ${
   target_type[$target_id-1]} == "操作" ];then
        operator_test
        if [ -d /var/ftp/pub/test1 ];then
            if [ ! -d /var/ftp/pub/test2 ];then
                if [ -f /var/ftp/pub/group ];then
                    echo "匿名操作权限正常"
                    rm -rf /var/ftp/pub
                fi
            fi
        fi
    else
        Usage
    fi
done
脚本执行效果
[root@localhost ~]# /bin/bash vsftpd_install_manager.sh
---------------管理平台登录界面---------------
 1: 部署软件 2: 下载测试  3: 操作测试
-------------------------------------------
> 请输入要操作的目标类型: 1
开始登录管理平台...
请输入需要安装的软件,多个用空格隔开:vsftpd lftp
vsftpd服务启动成功
---------------管理平台登录界面---------------
 1: 部署软件 2: 下载测试  3: 操作测试
-------------------------------------------
> 请输入要操作的目标类型: 2
匿名用户下载成功
---------------管理平台登录界面---------------
 1: 部署软件 2: 下载测试  3: 操作测试
-------------------------------------------
> 请输入要操作的目标类型: 3
匿名操作权限正常
---------------管理平台登录界面---------------
 1: 部署软件 2: 下载测试  3: 操作测试
-------------------------------------------
> 请输入要操作的目标类型:

2 awk实践

2.1 基础实践

2.1.1 基础知识

基础知识

简介

    在日常计算机管理中,总会有很多数据输出到屏幕或者文件,这些输出包含了标准输出、标准错误输出。默认情况下,这些信息全部输出到默认输出设备---屏幕。然而,大量的数据输出中,只有一小部分是我们需要重点关注的,我们需要把我们需要的或者关注的这些信息过滤或者提取以备后续需要时调用。早先的学习中,我们学过使用grep来过滤这些数据,使用cut、tr命令提出某些字段,但是他们都不具备提取并处理数据的能力,都必须先过滤,再提取转存到变量,然后在通过变量提取去处理,比如:
内存使用率的统计步骤
    1) 通过free -m提取出内存总量,赋值给变量 memory_totle
    2)通过free -m提取出n内存使用量,赋值给变量memory_use
    3)通过数学运算计算内存使用率

    需要执行多步才能得到内存使用率,那么有没有一个命令能够集过滤、提取、运算为一体呢?当然,就是今天我要给大家介绍的命令:awk

awk简介

    awk全称 Aho Weinberger Kernighan报告生成器,awk的三个字母是来自于三个作者的首字母。它是一个功能非常强大的文档编辑工具,它不仅能以行为单位还能以列为单位处理文件,并且还具有格式化文本输出功能。目前它受自由软件基金会(FSF)进行开发和维护,通常也称它为 GNU AWK,AWK有多种版本:
    AWK:原先来源于 AT & T 实验室的的AWK
    NAWK:New awk,AT & T 实验室的AWK的升级版
    GAWK:即GNU AWK。所有的GNU/Linux发布版都自带GAWK,它与AWK和NAWK完全兼容    
原理解读
    awk 认为文件中的每一行是一条记录,记录与记录的分隔符为换行符,每一列是一个字段 字段与字段的分隔符默认是一个或多个空格或tab制表符.

    awk的工作方式是逐行读取文本数据,将每一行数据视为一条记录(record)每条记录以字段分隔符分成若干字段,然后输出各个字段的值.然后以查找匹配某个特定模式的文本行,并对这些文本执行制定动作。

语法解读

基本格式

格式:
    awk [参数] '[动作]' [文件名]
    awk [参数] –f 动作文件 var=value [文件名]
    awk [参数] 'BEGIN段 [动作] END段' [文件名]
注意:
    动作的格式  '匹配条件{打印动作}'
常见参数:
    -F                指定列的分隔符,默认一行数据的列分隔符是空格
    -f file         指定读取程序的文件名
    -v var=value    自定义变量
awk程序运行优先级是:
    1 BEGIN: 在开始处理数据流之前执行,可选项
    2 动作: 如何处理数据流,必选项
    3 END: 处理完数据流后执行,可选项
常见动作
    print    显示内容
    $0        显示当前行所有内容
    $n        显示当前行的第n列内容,如果存在多个$n,它们之间使用逗号(,)隔开
注意:
    如果打印的内容是变量,则无需在变量两侧加上双引号,其他的都应该加双引号

其他功能

printf 格式化显示内容
    printf [-v var] format [item1,item2,...]
    注意:
        printf输出需要指定换行符号,format的格式必须与后面item对应
        常见格式:
            %c        显示字符的ASCII码        %d|i     显示十进制整数        %e|E    显示科学计数法数值
            %f        显示浮点数             %s         显示字符串            %u      显示无符号整数
            %%        显示%本身                
        修饰符:
            %#[.#]    第一个#控制显示宽度,第二个#表示小数点后的精度,例如%3.1f
            %-        左对齐,%-15s
            %+        显示数值的正负符号,%+d
常见内置变量
    FILENAME     当前输入文件的文件名,该变量是只读的
    NR             指定显示行的行号
    FNR            多文件时候,分别计数
    NF             表示字段数量
    OFS         输出格式的列分隔符,缺省是空格
    FS             输入文件的列分隔符,缺省是连续的空格和Tab
    RS            输入记录分隔符,指定输入时的换行符,原换行符($)仍有效
    ORS            输出记录分隔符,输出时用指定符号代替换行符
    ARGC|ARGV[n] 获取命令的参数个数|参数内容

准备工作

[root@localhost ~]# cat awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9

2.1.2 基础语法

信息查看

字段提取

字段提取:提取一个文本中的一列数据并打印输出,它提供了相关的内置变量。
    $0 表示整行文本
    $1 表示文本行中的第一个数据字段
    $2 表示文本行中的第二个数据字段
    $N 表示文本行中的第N个数据字段
    $NF 表示文本行中的最后一个数据字段
    NR 代表行的行号,在动作外部表示特定行
注意:
   如果打印多列信息,需要使用逗号隔开,否则是内容合并

实践1-打印列信息

打印第1列的内容
[root@localhost ~]# awk '{print $1}' awk.txt
nihao
nihao
nihao

打印第3列内容
[root@localhost ~]# awk '{print $3}' awk.txt
awk2
awk5
awk8

打印最后一列信息
[root@localhost ~]# awk '{print $NF}' awk.txt
awk3
awk6
awk9

打印所有内容
[root@localhost ~]# awk '{print $0}' awk.txt
nihao awk1 awk2 awk3
nihao awk4 awk5 awk6
nihao awk7 awk8 awk9

实践2-打印多列信息

打印第3,8列内容
[root@localhost ~]# awk '{print $1,$3}' awk.txt
nihao awk2
nihao awk5
nihao awk8

打印信息时候,合并信息
[root@localhost ~]# awk '{print $1$3}' awk.txt
nihaoawk2
nihaoawk5
nihaoawk8

使用\t实现内容的分割,需要用""扩住
[root@localhost ~]# awk '{print $1"\t"$3}' awk.txt
nihao   awk2
nihao   awk5
nihao   awk8

打印列外普通信息
[root@localhost ~]# awk '{print "hello awk"}' awk.txt
hello awk
hello awk
hello awk
注意:
    如果没有$n的话,表示 print动作执行的次数与文件行数一致

打印fstab的关键信息
[root@localhost ~]# grep "^UUID" /etc/fstab |awk {'print $1,$3'}
UUID=5583bd7c-cc9f-4e19-b453-c224102f3ed5 xfs
UUID=cbd246cd-1df8-4fe7-9040-823cd0978837 xfs

实践3-行号信息输出

打印每列的行号信息
[root@localhost ~]# awk '{print NR,$0}' awk.txt
1 nihao awk1 awk2 awk3
2 nihao awk4 awk5 awk6
3 nihao awk7 awk8 awk9

按照行号打印对应列的内容
[root@localhost ~]# awk '{print NR, $NR}' awk.txt
1 nihao
2 awk4
3 awk8

实践4-打印特定行内容

制定行号打印信息
[root@localhost ~]# awk  'NR==1 {print NR,$1,$3}' awk.txt
1 nihao awk2
[root@localhost ~]# awk  'NR==2 {print NR,$1,$3}' awk.txt
2 nihao awk5

定制查看

简介

    awk默认的信息查看是以空格作为列分隔符的,而对于非空格作为分隔符的内容,我们需要借助于专门的语法实现信息的分割,这里主要用到以下知识:
常见参数:
    -F            指定列的分隔符,默认一行数据的列分隔符是空格
常见内置变量
    FS             输入文件的列分隔符,缺省是连续的空格和Tab
    RS            输入记录分隔符,指定输入时的换行符,原换行符($)仍有效
    注意:
        一般情况下,在输出信息之前进行格式的调整,需要在BEGIN{
   }部分设定

实践1-简单演示

准备文件内容
[root@localhost ~]# head -n1 /etc/passwd > passwd.txt
[root@localhost ~]# cat passwd.txt
root:x:0:0:root:/root:/bin/bash

使用普通awk命令展示
[root@localhost ~]# awk '{print $1}' passwd.txt
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# awk '{print $2}' passwd.txt

[root@localhost ~]# awk '{print $0}' passwd.txt
root:x:0:0:root:/root:/bin/bash
结果显示:
    文件中只有一列,无法被awk默认分离

实践2-定制分隔符

设定分隔符实现信息的分隔效果
[root@localhost ~]# awk -F ':' '{print $0}' passwd.txt
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# awk -F ':' '{print $1}' passwd.txt
root
[root@localhost ~]# awk -F ':' '{print $1,$2}' passwd.txt
root x
[root@localhost ~]# awk -F ':' '{print $1,$7}' passwd.txt
root /bin/bash

基于-v方式设定输入分隔符的环境变量FS
[root@localhost ~]# awk -v FS=":" '{print $1FS$7}' passwd.txt
root:/bin/bash
虽然-v FS 和 -F 都可以设定入口数据的列分隔符,如果混用的话,-F的优先级高一点
[root@localhost ~]# awk -v FS=":" -F":" '{print $1FS$7}' passwd.txt
root:/bin/bash
[root@localhost ~]# awk -F":" -v FS=":"  '{print $1FS$7}' passwd.txt
root:/bin/bash

实践3-统计案例

获取网址域名信息
[root@localhost ~]# cat domain.txt
http://www.example.org/index.html
http://www.example.org/1.html
http://api.example.org/index.html
http://upload.example.org/index.html
http://img.example.org/3.html
http://search.example.org/2.html

对相关信息进行统计
[root@localhost ~]# awk -F[/]+ '{print $2}' domain.txt  | uniq -c
      2 www.sswang.org
      1 api.sswang.org
      1 upload.sswang.org
      1 img.sswang.org
      1 search.sswang.org
[root@localhost ~]# awk -F[/]+ '{print $(NF-1)}' domain.txt  | uniq -c 
      2 www.sswang.org
      1 api.sswang.org
      1 upload.sswang.org
      1 img.sswang.org
      1 search.sswang.org

2.1.3 显示语法

基础知识

简介

    awk支持格式化输出相关信息。它主要依赖两种方法:
属性方法
    OFS         输出格式的列分隔符,缺省是空格
    ORS            输出记录分隔符,输出时用指定符号代替换行符
print方法
    printf [-v var] format [item1,item2,...]
    注意:
        printf输出需要指定换行符号,format的格式必须与后面item对应
        常见格式:
            %c        显示字符的ASCII码        %d|i     显示十进制整数        
            %e|E    显示科学计数法数值      %u      显示无符号整数
            %f        显示浮点数             %s         显示字符串            
            %%        显示%本身                
        修饰符:
            %#[.#]    第一个#控制显示宽度,第二个#表示小数点后的精度,例如%3.1f
            %-        左对齐,%-15s
            %+        显示数值的正负符号,%+d

简单实践

实践1-列输出分隔符实践

借助于-v方式为命令行输出相关信息
[root@localhost ~]# awk -F ':' -v OFS="~~~" '{print $1,$7}' passwd.txt
root~~~/bin/bash

借助于BEGIN语句设定环境变量
[root@localhost ~]# awk -F":" 'BEGIN{OFS="~"} {print NR,$1,$7}' passwd.txt
1~root~/bin/bash

在BEGIN内部同时实现多个环境变量
[root@localhost ~]# awk 'BEGIN{FS=":";OFS="-"}NR==1{print $1,$3,$NF}' passwd.txt
root-0-/bin/bash

实践2-行输入输出分隔符实践

定制输入分隔符
[root@server12 ~]# seq 7 | awk 'BEGIN{RS=""}{print $1,$2,$3,$4,$5,$6,$7}'
1 2 3 4 5 6 7

借助于-v方式为行分隔符输出相关信息
[root@localhost ~]# awk -F ':' -v ORS="|" '{print $NR,$0}' awk.txt
nihao awk1 awk2 awk3 nihao awk1 awk2 awk3| nihao awk4 awk5 awk6| nihao awk7 awk8 awk9|[root@localhost ~]#

借助于
;