zoukankan      html  css  js  c++  java
  • 第九章 expect 和grep命令

    一、expect介绍

    expect 是一个免费的编程工具,用来实现自动的交互式任务,而无需人为干预。说白了, expect
    就是一套用来实现自动交互功能的软件。需要安装
    
    yum install -y expect
    
    expect基础
    在使用 expect 时,基本上都是和以下四个命令打交道:
    
    命令 作用
    spawn 启动新的进程
    expect 从进程接收字符串
    send 用于向进程发送字符串
    interact 允许用户交互
    1.spawn 命令用来启动新的进程, spawn 后的 expect 和 send 命令都是和使用 spawn 启动的新进程进行交互。
    2.expect 通常用来等待一个进程的反馈,我们根据进程的反馈,再使用 send 命令发送对应的交互
    命令。
    3.send 命令接收一个字符串参数,并将该参数发送到进程。
    4.interact 命令用的其实不是很多,一般情况下使用 spawn 、 expect 和 send 和命令就可以很好的完成我们的任务;但在一些特殊场合下还是需要使用 interact 命令的, interact 命令主要用
    于退出自动化,进入人工交互。比如我们使用 spawn 、 send 和 expect 命令完成了ftp登陆主机,执行下载文件任务,但是我们希望在文件下载结束以后,仍然可以停留在ftp命令行状态,以便手
    动的执行后续命令,此时使用 interact 命令就可以很好的完成这个任务。
    

    1)expect自动应答的基本步骤

    第一步: 运行一个程序或命令=>  spawn 命令信息
    第二步: 识别产生信息关键字=>  expect 捕获关键字  {send  应答信息}
    第三步: 根据识别关键做处理=>  send  应答信息
    

    二、expect实例

    1)自动应答脚本

    #!/usr/bin/expect
    spawn ssh root@192.168.12.20 uptime
    expect "yes/no"
    send "yes
    "
    expect "*assword"
    send "1
    "
    expect eof
    

    2)解释

    #1、#!/usr/bin/expect -f:使用expect来解释该脚本
    #2、spwan:
    spawn是进入expect环境后才可以执行的expect内部命令,如果没有装expect或者直接在默认的SHELL下-执行是找不到spawn命令的。它主要的功能是给ssh运行进程加个壳,用来传递交互指令;
    #3、expect:
    expect "*assword":这里的expect也是expect的一个内部命令,这个命令的意思是判断上次输出结果里是否包含“password”的字符串,如果有则立即返回;否则就等待一段时间后返回,这里等待时长就是前面设置的30秒;
    #4、send:
    send "1
    ":当匹配到对应的输出结果时,就发送密码到打开的ssh进程,执行交互动作;
    
    首次登陆之后,再次登陆,就不会出现yes/no的提示了,所以上述脚本再次运行会出现spawn 命令出
    现交互式提问的expect 匹配不上的情况,此时脚本会阻塞在原地,我们可以set timeout 3设置超时时间,单位为秒,默认情况下是10秒,以保障脚本超时则结束,
    
    #!/usr/bin/expect -f
    spawn ssh root@192.168.12.20 uptime
    set timeout 3  # 某一条expect语句在原地匹配,超过了3秒,无论是否匹配成功都会继续执行下一条
    指令
    expect "yes/no"
    send "yes
    "
    expect "*assword"
    send "1
    "
    expect eof
    
    设置超时时间的目的仅仅只是为了让脚本不要一直卡在原地,要真正解决上述问题,需要改写成下述形
    式
    #!/usr/bin/expect -f
    spawn ssh root@192.168.12.20 hostname
    # 注意
    # 1、{}一定要换行
    # 2、下述语句就一个expect,代表匹配了一次,会匹配完一行就匹配下一行
    expect {
      "yes/no" {send "yes
    ";exp_continue}
      "*assword" {send "1
    "}
    }
    expect eof
    

    3)练习

    [root@aliyun ~]# cat 1.sh
    #!/usr/bin/expect -f
    spawn ssh egon@127.0.0.1
    set timeout -1  # 设置为-1代表永不超时,如果expect没有捕捉到就一直停在原地
    expect {
    "yes/no" {send "yes
    "}
    }
    expect {
    "password" {send "1
    "}
    }
    expect "*egon*"
    send "ls
    "
    expect "$"
    send "pwd
    "
    expect "$"
    send "exit
    "  # 注意一定要输入exit结束信号
    expect eof  # 最后关闭匹配
    [root@aliyun ~]#
    

    4)interact交互

    interact :执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有
    这一句登录完成后会退出,而不是留在远程终端上。
    
    [root@egon ~]# cat test.sh
    #!/usr/bin/expect -f
    spawn ssh root@192.168.12.20
    expect {
      "yes/no" {send "yes
    ";exp_continue}
      "*assword" {send "1
    "}
    }
    interact
    [root@egon ~]#
    [root@egon ~]# ./test.sh
    spawn ssh root@192.168.12.20
    root@192.168.12.20's password:
    Last login: Wed Aug 26 21:28:04 2020 from egon
    +--------------------------------------------+
    |                       |
    |   你当前登录的是支付业务后台数据库服务   |
    |   请不要删库                |
    |                       |
    +--------------------------------------------+
    [root@egon ~]# pwd
    /root
    [root@egon ~]# echo "hello"
    hello
    [root@egon ~]# exit
    登出
    Connection to 192.168.12.20 closed.
    [root@egon ~]#
    

    三、expect脚本传参

    shell脚本中的变量无法直接在expect中使用的,若expect需要使用变量一方面可以自己定义
    
    #!/usr/bin/expect -f
    set timeout -1
    set user "root"
    set ip "192.168.12.20"
    set cmd "hostname"
    set pass "1"
    spawn ssh $user@$ip $cmd
    expect {
      "yes/no" {send "yes
    ";exp_continue}
      "*assword" {send "$pass
    "}
    }
    expect eof
    
    另外一方面可以通过下述方式引入shell变量,注意此时解释器换成#!/bin/bash
    
    #!/bin/bash
    user="root"
    ip="192.168.12.20"
    cmd="hostname"
    pass="1"
    expect << EOF
    spawn ssh $user@$ip $cmd
    expect {
      "yes/no" {send "yes
    ";exp_continue}
      "*assword" {send "$pass
    "}
    }
    expect eof
    EOF
    
    此外,expect脚本还可以从命令行获取参数
    在expect中, $argc 表示参数个数,而参数值存放在 $argv 中,比如取第一个参数就是 [lindex
    $argv 0] ,以此类推。
    
    [root@egon ~]# cat test.sh
    #!/usr/bin/expect -f
    if {$argc != 4} {
      puts "Usage:./script.sh <ip> <username> <password> <cmd>"
      exit 1
    }
    set ip [lindex $argv 0]
    set user [lindex $argv 1]
    set pass [lindex $argv 2]
    set cmd [lindex $argv 3]
    set timeout -1
    spawn ssh $user@$ip $cmd
    expect {
      "yes/no" {send "yes
    ";exp_continue}
      "*assword" {send "$pass
    "}
    }
    expect eof
    [root@egon ~]# ./test.sh
    Usage:./script.sh <ip> <username> <password> <cmd>
    [root@egon ~]# ./test.sh 192.168.12.20 root 1 hostname
    spawn ssh root@192.168.12.20 hostname
    root@192.168.12.20's password:
    egon
    [root@egon ~]#
    

    四、grep介绍

    1)grep简介

    grep命令主要用于过滤文本,grep家族如下
    	1)grep: 在文件中全局查找指定的正则表达式,并打印所有包含该表达式的行
    	2)egrep:扩展的egrep,支持更多的正则表达式元字符
    	3)fgrep:固定grep(fixed grep),有时也被称作快速(fast grep),它按字面解释所有的字符
    

    2)grep命令格式

    grep [选项] PATTERN 文件1 文件2 ...
    [root@egon ~]# grep 'root' /etc/passwd
    [root@egon ~]# fgrep 'bash' /etc/passwd
    找到: grep返回的退出状态为0
    没找到: grep返回的退出状态为1
    找不到指定文件:  grep返回的退出状态为2
    
    grep 命令的输入可以来自标准输入或管道,而不仅仅是文件,例如:
    ps aux |grep 'nginx'
    

    五、grep选项

    -n, --line-number 在过滤出的每一行前面加上它在文件中的相对行号
    -o, --only-matching 只显示匹配的内容
    -q, --quiet, --silent 静默模式,没有任何输出,得用$?来判断执行成功没有,即有没有过滤
    到想要的内容
    --color 颜色
    -i, --ignore-case 忽略大小写
    -A, --after-context=NUM 如果匹配成功,则将匹配行及其后n行一起打印出来
    -B, --before-context=NUM 如果匹配成功,则将匹配行及其前n行一起打印出来
    -C, --context=NUM 如果匹配成功,则将匹配行及其前后n行一起打印出来
    -c, --count 如果匹配成功,则将匹配到的行数打印出来
    -v, --invert-match 反向查找,只显示不匹配的行
    -w 匹配单词
    -E 等于egrep,扩展
    -l, --files-with-matches 如果匹配成功,则只将文件名打印出来,失败则不打印
    通常-rl一起用,grep -rl 'root' /etc
    -R, -r, --recursive 递归
    

    六、grep示例

    # 1、-n
    [root@egon ~]# grep -n 'root' /etc/passwd
    1:root:x:0:0:root:/root:/bin/bash
    10:operator:x:11:0:operator:/root:/sbin/nologin
    [root@egon ~]#
    # 2、-o
    [root@egon ~]# grep -o 'root' /etc/passwd
    root
    root
    root
    root
    [root@egon ~]#
    # 3、-q
    [root@egon ~]# grep -q 'root' /etc/passwd
    [root@egon ~]# echo $?
    0
    # 4、--color
    [root@egon ~]# alias grep
    alias grep='grep --color=auto'
    [root@egon ~]#
    # 5、-i
    [root@egon ~]# echo "EGON" |grep -i egon
    EGON
    [root@egon ~]#
    # 6、-A-B-C
    [root@egon ~]# grep -A 2 'root' /etc/passwd
    [root@egon ~]# grep -B 2 'root' /etc/passwd
    [root@egon ~]# grep -C 2 'root' /etc/passwd
    # 7、-c
    [root@egon ~]# grep -c 'root' /etc/passwd
    2
    [root@egon ~]#
    # 8、-v
    [root@egon ~]# ps aux | grep nginx |grep -v grep
    [root@egon ~]#
    [root@egon ~]# ps aux | grep [n]ginx
    [root@egon ~]#
    # 9、-w
    [root@egon ~]# netstat -an |grep -w 80
    tcp6    0    0 :::80          :::*           LISTEN  
    [root@egon ~]# netstat -an |grep '<80>'
    tcp6    0    0 :::80          :::*           LISTEN  
    [root@egon ~]# netstat -an |grep '80'
    tcp6    0    0 :::80          :::*           LISTEN 
                         
    # 10、-rl
    [root@egon ~]# grep -rl 'root' /etc # 将/etc目录下所有包含'root'内容的文件都列出来
    

    七、正则表达式

    1)正则表达式介绍

    1.正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),是计算机科学的一个概念。正则表达式由元字符组成,通常被用来检索、替换那些符合某个模式(规则)的文本(许多程序设计语言都支持利用正则表达式进行字符串操作)。
    
    2.元字符:是一类可以表达出超越其字面本身含义的特殊字符
    shell元字符(也称为通配符): 由shell解释器来解析,如rm -rf *.pdf,元字符*Shell将其解析为任意多个字符
    正则表达式元字符 : 由各种执行模式匹配操作的程序来解析,比如vi、grep、sed、awk
    
    3.例如:vim示例:
    :1,$ s/tom/EGON/g # 如anatomy、tomatoes及tomorrow中的“tom”被替换了,而Tom确没
    被替换
    :1,$ s/<[Tt]om>/EGON/g
    

    2)正则表达式元字符

    元字符 功能  示例
    ^  行首 ^love
    $  行尾 love$
    .  除了换行符以外的任意单个字符 l..e
    *  前导字符的零个或多个   ab*love
    .*  所有字符 a.*love
    []  字符组内的任一字符 [lL]ove
    [^]  对字符组内的每个字符取反(不匹配字符组内的每个字符)  [^a-z0-9]ove
    ^[^]    非字符组内的字符开头的行
    [a-z]  小写字母
    [A-Z]  大写字母
    [a-Z]    小写和大写字母
    [0-9]    数字
     用来转义元字符  love.
    <   词首定位符 单词一般以空格或特殊字符做分隔、连续的字符组成  <love
    > 词尾定位符  love>
    (..)  匹配稍后将要使用的字符的标签         (love)able1er
    :1,$ s/						(192.168.11).66/1.50/g
    x{m} 字符x重复出现m次   e{3}
    x{m,} 字符x重复出现m次以上 e{3,}
    x{m,n} 字符x重复出现m到n次 e{3,6}
    

    3)正则表达式示例

    # 1、^ 行首
    [root@egon ~]# grep '^root' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    [root@egon ~]#
    # 2、$ 行尾
    [root@egon ~]# grep 'bash$' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    user1:x:1002:1003::/home/user1:/bin/bash
    egon1:x:198:1005::/home/egon1:/bin/bash
    gg:x:1004:1006::/home/gg:/bin/bash
    egon:x:1005:1007::/home/egon:/bin/bash
    tom:x:1006:1008::/home/tom:/bin/bash
    [root@egon ~]#
    # 3、. 除了换行符以外的任意单个字符
    [root@egon ~]# grep 'r..t' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    [root@egon ~]#
    # 4、* 前导字符的零个或多个
    [root@egon ~]# cat a.txt
    a
    ab
    abb
    abbb
    bbbbb
    [root@egon ~]# grep 'ab*' a.txt
    a
    ab
    abb
    abbb
    [root@egon ~]#
    # 5、.* 所有字符=贪婪
    [root@egon ~]# cat a.txt
    a123+-*/c11113333c
    a1c
    a77Ac
    a23333c
    ac
    111
    222
    333
    [root@egon ~]# grep 'a.*c' a.txt
    a123+-*/c11113333c
    a1c
    a77Ac
    a23333c
    ac
    [root@egon ~]#
    # 5.1 .*?=》非贪婪,默认情况下,grep不支持非贪婪修饰符,但您可以使用grep -P来使用Perl语法来
    支持.*?
    [root@egon ~]# cat a.txt
    <a href="http://www.baidu.com">"我他妈的是百度"</a>
    <a href="http://www.sina.com.cn">"我特么的是新浪"</a>
    [root@egon ~]#
    [root@egon ~]# grep -o 'href=".*"' a.txt # 贪婪
    href="http://www.baidu.com">"我他妈的是百度"
    href="http://www.sina.com.cn">"我特么的是新浪"
    [root@egon ~]#
    [root@egon ~]# grep -oP 'href=".*?"' a.txt # 非贪婪
    href="http://www.baidu.com"
    href="http://www.sina.com.cn"
    [root@egon ~]#
    # 6、[] 字符组内的任一字符
    # 7、[^] 对字符组内的每个字符取反(不匹配字符组内的每个字符)
    [root@egon ~]# cat a.txt
    a1c
    a2c
    a33c
    aAc
    aZc
    [root@egon ~]# grep 'a[0-9]c' a.txt
    a1c
    a2c
    [root@egon ~]# grep 'a[^0-9]c' a.txt
    aAc
    aZc
    [root@egon ~]#
    [root@egon ~]# grep 'a[0-9][0-9]c' a.txt
    a33c
    [root@egon ~]#
    # 8、^[^] 非字符组内的字符开头的行
    [root@egon ~]# cat a.txt
    a1c
    a2c
    a33c
    aAc
    aZc
    [root@egon ~]# grep '^[^0-9]..$' a.txt
    a1c
    a2c
    aAc
    aZc
    [root@egon ~]#
    # 9、[a-z] 小写字母
    # 10、[A-Z] 大写字母
    # 11、[a-Z] 小写和大写字母
    # 12、[0-9] 数字
    # 13、< 单词头 单词一般以空格或特殊字符做分隔,连续的字符串被当做单词
    # 14、> 单词尾
    [root@egon ~]# netstat -an |grep -w 80
    tcp6    0    0 :::80          :::*           LISTEN  
    [root@egon ~]# netstat -an |grep '<80>'
    tcp6    0    0 :::80          :::*           LISTEN  
    [root@egon ~]# netstat -an |grep '80'
    tcp6    0    0 :::80          :::*           LISTEN 
    
    Ps: grep匹配换行符和制表符
    [root@egon ~]# echo -e "a
    b" |grep $'a
    b'
    a
    b
    [root@egon ~]#
    [root@egon ~]# echo -e "a	b" |grep $'a	b'
    a b
    [root@egon ~]#
    

    4)扩展正则元字符

    # 扩展正则元字符
    + 匹配一个或多个前导字符  [a-z]+ove
    ? 匹配零个或一个前导字符  lo?ve
    a|b 匹配a或b love|hate
    () 组字符 love(able|rs) (egon)+
    (..)(..)12 标签匹配字符 (love)able1er
    x{n}   x出现n次   e{3}
    x{n,}   x出现n次至无穷次  e{3,}
    x{n,m}     x出现n次至m次  e{3,6}
    
    # 若想使用扩展正则
    grep加-E 或 egrep 或转义
    sed 加 -r 参数 或转义
    AWK 直接支持大多数扩展正则,更多支持需要加选项--posix选项
    

    5)扩展元字符示例

    # ======================grep扩展正则示例======================
    [root@egon ~]# cat a.txt
    a
    ab
    abb
    abbb
    abbbb
    abbbbb
    bbbbbbb
    [root@egon ~]# grep 'ab{2,4}' a.txt # 默认不支持扩展正则,所以没效果
    [root@egon ~]# egrep 'ab{2,4}' a.txt
    abb
    abbb
    abbbb
    abbbbb
    [root@egon ~]#
    # ======================sed扩展正则示例======================
    [root@egon ~]# sed -n '/roo?/p' /etc/passwd # 默认不支持扩展正则?
    [root@egon ~]# sed -n '/roo?/p' /etc/passwd # 可以用转义扩展正则符号?
    有结果,结果略...
    [root@egon ~]# sed -rn '/roo?/p' /etc/passwd # 也可以加-r选项
    有结果,结果略...
    [root@egon ~]#
    # ======================awk扩展正则示例======================
    [root@egon ~]# cat a.txt
    a
    ab
    abb
    abbb
    abbbb
    abbbbb
    bbbbbbb
    [root@egon ~]# awk '/ab{1,3}/{print}' a.txt
    ab
    abb
    abbb
    abbbb
    abbbbb
    [root@egon ~]# awk --posix '/ab{1,3}/{print}' a.txt
    ab
    abb
    abbb
    abbbb
    abbbbb
    [root@egon ~]#
    

    6)总结

    grep: 使用基本元字符集 ^, $, ., *, [], [^], < >,(),{}
    egrep(或grep -E): 使用扩展元字符集 ?, +, { }, |, ( )
    # 注:grep也可以使用扩展集中的元字符,仅需要对这些元字符前置一个反斜线
    w 所有字母与数字,称为字符[a-zA-Z0-9]  'l[a-zA-Z0-9]*ve'  'lw*ve'
    W 所有字母与数字之外的字符,称为非字符  'love[^a-zA-Z0-9]+'     'loveW+'
     词边界 'love'  '<love>'
    

    7)POSIX定义的字符分类

    # 表达式    功能               示例
    [:alnum:]   字母与数字字符            [[:alnum:]]+ 
    [:alpha:] 字母字符(包括大小写字母) [[:alpha:]]{4}
    [:blank:]   空格与制表符             [[:blank:]]*
    [:digit:]    数字字母              [[:digit:]]?
    [:lower:]   小写字母              [[:lower:]]{5,}
    [:upper:]   大写字母              [[:upper:]]+
    [:punct:]   标点符号              [[:punct:]]
    [:space:]   包括换行符,回车等在内的所有空白[[:space:]]+
    # 详解
    [:alnum:] Alphanumeric characters.
    匹配范围为 [a-zA-Z0-9]
    [:alpha:] Alphabetic characters.
    匹配范围为 [a-zA-Z]
    [:blank:] Space or tab characters.
    匹配范围为 空格和TAB键
    [:cntrl:] Control characters.
    匹配控制键 例如 ^M 要按 ctrl+v 再按回车 才能输出
    [:digit:] Numeric characters.
    匹配所有数字 [0-9]
    [:graph:] Characters that are both printable and visible. (A space is print-
    able, but not visible, while an a is both.)
    匹配所有可见字符 但不包含空格和TAB 就是你在文本文档中按键盘上能用眼睛观察到的所有符号
    [:lower:] Lower-case alphabetic characters.
    小写 [a-z]
    [:print:] Printable characters (characters that are not control characters.)
    匹配所有可见字符 包括空格和TAB
    能打印到纸上的所有符号
    [:punct:] Punctuation characters (characters that are not letter, digits, con-
    trol characters, or space characters).
    特殊输入符号 +-=)(*&^%$#@!~`|"'{}[]:;?/>.<,
    注意它不包含空格和TAB
    这个集合不等于^[a-zA-Z0-9]
    [:space:] Space characters (such as space, tab, and formfeed, to name a few).
    [:upper:] Upper-case alphabetic characters.
    大写 [A-Z]
    [:xdigit:] Characters that are hexadecimal digits.
    16进制数 [0-f]
    # 使用方法:
    [root@egon ~]# grep --color '[[:alnum:]]' /etc/passwd
    

    八、练习

    目标文件/etc/passwd,使用grep命令或egrep
    1.显示出所有含有root的行:
    2.输出任何包含bash的所有行,还要输出紧接着这行的上下各两行的内容:
    3.  显示出有多少行含有nologin。
    4.显示出那些行含有root,并将行号一块输出。
    5.显示出文件中
    6.新建用户
      abominable
      abominate
      anomie
      atomize
      编写正则表达式,将他们匹配出来
      egrep 'a.omi(nabl|nat|z|)e' /etc/passwd
    7.建四个用户
      Alex213sb
      Wpq2222b
      yH438PIG
      egon666
      egon
      过滤出用户名组成是字母+数字+字母的行
    [root@MiWiFi-R3-srv ~]# egrep '^[a-Z]+[0-9]+[a-Z]+' /etc/passwd
    8.显示出/etc目录下所有包含root的文件名
    9. 过滤掉/etc/ssh/sshd_config内所有注释和所有空行
    grep -v '^#' /etc/ssh/sshd_config |grep -v '^ *$'
    
  • 相关阅读:
    JS 面向对象
    堆 栈
    考试题
    HTML Meta标签
    Nodejs 安装
    CSS3 背景图片的大小位置
    JS Math函数
    CSS3 巧用before after选择器
    计算机网络原理_数据链路层
    Asp.net_验证控件
  • 原文地址:https://www.cnblogs.com/jhno1/p/14105381.html
Copyright © 2011-2022 走看看