Linux--RH254---unit 11 bash 2

一、test条件判断
    test命令可用于评估bash脚本中的表达式。它评估其参数所指定的表达式,如果表达式为true,返回零退出状态,如果表达式为false,则返回非零退出状态。test具有替代语法,使用方括号"[]"将表达式括起来,这样更易于阅读。

语法:test EXPRESSION 或 [EXPRESSION]

1.非零或零长度字符串运算符:test -{n|z} STRING
[[email protected] ~]# test -n "$a";echo $?    ##判断a字符是否为非零长度字符串
0                        ##表达式为true,返回零退出状态
[[email protected] ~]# test -z "$a";echo $?    ##判断a字符是否为零长度字符串

1                        ##表达式为false,返回非零退出状态

Linux--RH254---unit 11 bash 2


2.字符串比较运算符:=、!=

[[email protected] mnt]# [ $a = $b ] && echo yes || echo no    ##判定$a是否等于$b,相等则为ture
no
[[email protected] mnt]# [ $a != $b ] && echo yes || echo no    ##判定$a是否不等于$b,不相等则为ture

yes

Linux--RH254---unit 11 bash 2


3.数字比较运算符:-eq、-ne、-lt、-le、-gt、-ge
[[email protected] mnt]# [ "$a" -eq "$b" ]&& echo yes || echo no    ##-eq判断是否等于
no
[[email protected] mnt]# [ "$a" -le "$b" ]&& echo yes || echo no    ##-le判断是否小于等于
yes
[[email protected] mnt]# [ "$a" -lt "$b" ]&& echo yes || echo no    ##-lt判断是否小于
yes
[[email protected] mnt]# [ "$a" -gt "$b" ]&& echo yes || echo no    ##-gt判断是否大于
no
[[email protected] mnt]# [ "$a" -ge "$b" ]&& echo yes || echo no    ##-ge判断是否大于等于
no
[[email protected] mnt]# [ "$a" -ne "$b" ]&& echo yes || echo no    ##-ne判断是否不等于
yes

Linux--RH254---unit 11 bash 2


4.文件状态运算符:test -{b|c|e|f|d|x|s|S|L} FILE/DIRECTORY
[[email protected] mnt]# [ -e "/mnt" ]&& echo yes || echo no    ##检测该档名是否存在
yes
[[email protected] mnt]# [ -d "/mnt" ]&& echo yes || echo no    ##检测该档名是否存在且为目录(directory)
yes
[[email protected] mnt]# [ -f "/mnt" ]&& echo yes || echo no    ##检测该档名是否存在且为档案(file)
no
[[email protected] mnt]# [ -x "/mnt" ]&& echo yes || echo no    ##检测该档名是否存在且具有可执行权限
yes
[[email protected] mnt]# [ -b "/dev/vdb" ]&& echo yes || echo no    ##检测该档名是否存在且为一个块设备
yes
[[email protected] mnt]# [ -c "/dev/pts/0" ]&& echo yes || echo no    ##检测该档名是否存在且为一个字符设备
yes
[[email protected] mnt]# [ -S "/var/lib/mysql/mysql.sock" ]&& echo yes || echo no    ##检测该档名是否存在且为一个套接字档案
yes
[[email protected] mnt]# [ -s "/mnt/check_ip.sh" ]&& echo yes || echo no    ##检测该档名是否存在且为非空白档案
yes
[[email protected] mnt]# ln -s /mnt/file /mnt/file1
[[email protected] mnt]# [ -L "/mnt/file1" ]&& echo yes || echo no        ##检测该档名是否存在且为一个链接档
yes

Linux--RH254---unit 11 bash 2


5.二进制文件运算符:-ef、-nt、-ot
[[email protected] mnt]# [ "/mnt/file1" -ef "/mnt/file2" ] && echo yes || echo no        ##判断file1与file2是否为同一档案,可用在判断 hard link 的判定上,主要意义在判定两个档案是否均指向同一个inode
yes
[[email protected] mnt]# [ "/mnt/file" -ot "/mnt/check_ip.sh" ] && echo yes || echo no    ##判断file是否比check_ip.sh旧
no
[[email protected] mnt]# [ "/mnt/file" -nt "/mnt/check_ip.sh" ] && echo yes || echo no    ##判断file是否比check_ip.sh新

yes

Linux--RH254---unit 11 bash 2


6.逻辑运算符:-o、-a、!
[[email protected] mnt]# [ -e "/mnt/file" -a -e "/mnt/check_ip.sh" ] && echo yes || echo no    ##两状况同时成立才为ture
yes
[[email protected] mnt]# [ -e "/mnt/file" -o -e "/mnt/hh" ] && echo yes || echo no            ##两状况任何一个成立即为ture
yes
[[email protected] mnt]# [ ! -e "/mnt/hh" ] && echo yes || echo no                    ##反向状态,当/mnt/hh不存在时返回值为ture

yes

Linux--RH254---unit 11 bash 2


### 脚本示例 ###
1)检测网络
#!/bin/bash
[ -n "$*" ] &&(                        ##判断$*是否为非零长度字符串,true则执行&&后的语句
        ping -c1 -w1 $* &> /dev/null && echo $* is up || echo $* is down    ##检测ip地址是否可以ping通
)||(                            ##false则执行||后的语句
        echo "please give me a ipaddress!"

)

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2


2)两个数字相加,判定是否在10以内
#!/bin/bash
while
[ -z "$1" -o -z "$2" ]                    ##检测$1或$2中是否有一个为零长度字符串
do
        echo "please give two number !"
        exit 1                        ##错误退出
done
((NUM=$1+$2))                        ##计算$1+$2的值
[ "$NUM" -lt "10" ] && echo "$1+$2=$NUM is smaller than 10" || echo "$1+$2=$NUM is bigger than 10"        ##$NUM小于10时执行&&后的语句,否则执行||后的语句

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2


3)检测文件/目录,并判定类型
#!/bin/bash
while
[ -z "$1" ]                                ##判断$1是否为空
do
        echo "please input a filename !"
        exit 1                                ##错误退出
done
[ -e $1 ] || echo "$1 is not exist !"
[ -d $1 ] && echo "$1 exists and is a directory !"
[ -b $1 ] && echo "$1 exists and is block special !"
[ -c $1 ] && echo "$1 exists and is character special !"
[ -S $1 ] && echo "$1 exists and is a socket !"
[ -L $1 ] && echo "$1 exists and is a symbolic link !"
[ -f $1 -a ! -L $1 ] && echo "$1 exists and is a regular file !"    ##$1是类型f并且不是类型L
Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2


二、if语句
    if命令检查if后面的命令或列表的退出值。如果第一个命令评估为true/零,则运行then之后的命令列表,直至任一else。如果第一个命令评估为false/非零,则运行else与fi之间的命令列表(反向平写if,标记if块的结束)。

语法:if command; then command; command2; else command3; fi

Linux--RH254---unit 11 bash 2


### 脚本示例 ###
1)编写脚本添加/mnt/userfile中的用户,并将用户密码设定为westos
#!/bin/bash
if
[ -z "$1" ]                                ##当输入的$1为空时
then
        echo "please input a userfile"
elif
[ ! -e "$1" ]                                ##当输入的$1不存在时
then
        echo "$1 is not exist"
else
        for NAME in `cat $1`                        ##for循环,按顺序将$1中数据取出
        do
                USER=`getent passwd $NAME`                ##检测用户是否存在
                if
                [ -z "$USER" ]                        ##当用户不存在
                then
                        useradd $NAME                    ##建立用户
                        echo westos | passwd --stdin $NAME &>/dev/null    ##设定密码
                        echo "$NAME created successfully !"        ##建立成功
                else
                        echo "$NAME is exist !"                ##当用户已存在
                fi
        done

fi

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2


2)在上一示例基础上,编写脚本可以添加/mnt/userfile中的用户,也可以删除/mnt/userfile中的用户
#!/bin/bash
ACTION () {        ##函数块
if
[ -z "$4" ]        ##调用函数时的$4就是脚本执行时的$2
then
        echo "please input a userfile"        ##若使用脚本时$2为空提出警告
elif
[ ! -e "$4" ]        ##若使用脚本时$2不存在提出警告
then
        echo "$4 is not exist"
else
        for NAME in `cat $4`
        do
                USER=`getent passwd $NAME`
                if
                [ $1 "$USER" ]
                then
                        $2 $NAME
                        [ "$2" = "useradd" ]&& (
                                echo westos|passwd --stdin $NAME &>/dev/null
                                echo "$NAME created successfully !"
                                ) || echo "$NAME delete successfully !"
                else
                        echo $NAME $3
                fi
        done
fi
}
if            ##脚本主内容
[ "$1" = "create" ]    ##建立用户
then
        ACTION -z 'useradd' 'exist !' $2        ##调用函数ACTION
elif
[ "$1" = "delete" ]    ##删除用户
then
        ACTION -n 'userdel -r' 'not exist !' $2        ##调用函数ACTION
else
        echo "Useage:ctl_user.sh  <create|delete>  <userfile> !!"    ##若使用脚本时$1为空提出警告

fi

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2



三、case语句
    case语句 :它能够把变量的内容与多个模板进行匹配,再根据成功匹配的模板去决定应该执行哪部分代码。
#!/bin/bash
case "$1" in
start)                    ##当$1为start时
        echo "正在开启。。。"
        ;;
stop)                    ##当$1为stop时
        echo "正在关闭。。。"
        ;;
restart)                ##当$1为restart时
        echo "正在重启请稍等。。。"
        ;;
*)                    ##当以上情况都不符时
        echo "please input start|stop|restart !!"
        ;;

esac

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2


四、expect语句
    在shell中利用expect实现自动应答脚本。
1.当不使用自动应答脚本,需要手动一条一条输入答案
[[email protected]esktop31 mnt]# vim ask.sh
#!/bin/bash
read -p "Who are you: " USER
read -p "How old are you: " AGE
read -p "What's your class: " CLASS
read -p "Where are you from: " ADDRESS

echo $USER is $AGE\'s old and study at $CLASS and from $ADDRESS

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2


2.当使用自动应答脚本,执行命令时答案自动输入

yum install expect -y        ##安装expect

Linux--RH254---unit 11 bash 2

[[email protected] mnt]# vim answer.exp
#!/usr/bin/expect        ##这一行告诉操作系统脚本里的代码使用那一个shell来执行
spawn /mnt/ask.sh        ##spawn是expect的内部命令,作用是给后面的shell指令加个壳,用来传递交互指令
expect "Who"            ##判断输出结果里是否包含“Who”的字符串
send "wy\r"            ##执行交互动作,相当于手动输入"wy"
expect "How"
send "18\r"
expect "What"
send "linux\r"
expect "Where"
send "xi'an\r"

expect eof            ##作用是在输出中搜索文件结束符,如果没有这一行,脚本会立即退出,得不到正确结果

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2


3.改进answer.exp,使输入值不唯一
  $argv 参数数组:
    expect脚本可以接受从bash传递过来的参数.可以使用[lindex $argv n]获得,n从0开始,分别表示第一个,第二个,第三个....参数
[[email protected] mnt]# vim answer.exp
#!/usr/bin/expect
set NAME    [ lindex $argv 0 ]
set AGE     [ lindex $argv 1 ]
set CLASS   [ lindex $argv 2 ]
set ADDRESS [ lindex $argv 3 ]
spawn /mnt/ask.sh
expect "Who"
send "$NAME\r"
expect "How"
send "$AGE\r"
expect "What"
send "$CLASS\r"
expect "Where"
send "$ADDRESS\r"

expect eof

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2


### 脚本示例 ###
1)使用ssh命令时,自动输入信息,并且保持登陆状态
[[email protected] mnt]# vim ssh.exp
#!/usr/bin/expect
set IP   [ lindex $argv 0 ]
set PASS [ lindex $argv 1 ]
spawn ssh [email protected]$IP
expect {
        "yes/no" {send "yes\r";exp_continue}    ##exp_continue意思是如果遇到这个问题就正常执行,如果没有遇到这个问题,就跳过执行下一条
        "password:" {send "$PASS\r"}
}

interact                ##执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。否则退出登录。

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2


2)编写脚本/mnt/check_hostname.sh,并且在/mnt/autosh.exp中实现自动应答,查看/mnt/host里面ip主机的hostname
[[email protected] mnt]# vim host
172.25.254.231 redhat

172.25.254.131 westos

Linux--RH254---unit 11 bash 2

[[email protected] mnt]# vim autosh.exp
#!/usr/bin/expect
set IP   [ lindex $argv 0 ]
set PASS [ lindex $argv 1 ]
set COMMAND [ lindex $argv 2 ]
spawn ssh [email protected]$IP $COMMAND
expect {
        "yes/no" {send "yes\r";exp_continue}
        "password:" {send "$PASS\r"}
}

interact

Linux--RH254---unit 11 bash 2

[[email protected] mnt]# vim check_hostname.sh
#!/bin/bash
if
[ -n "$*" ]
then
        MAX_LINE=`wc -l $* | awk '{print $1}'`
        for NUM in `seq 1 $MAX_LINE`
        do
                IP=`sed -n ${NUM}p $* | awk '{print $1}'`
                PASS=`sed -n ${NUM}p $* | awk '{print $2}'`
                /mnt/autosh.exp $IP $PASS hostname | tail -n 1
        done
else
        echo "Useage:check_host.sh <filename>"

fi

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2



五、环境变量
    shell和脚本使用变量来存储数据 ,有些变量可以连同它们的内容传递给子进程,这些变量我们称之为环境变量。
使用env命令显示所有环境变量

使用set命令现实所有本地定义的shell变量

Linux--RH254---unit 11 bash 2

1.环境级环境变量:只能在当前环境使用
[[email protected] ~]# cd /mnt
[[email protected] mnt]# a=1
[[email protected] mnt]# echo $a
1
[[email protected] mnt]# bash
[[email protected] mnt]# echo $a

[[email protected] mnt]# exit
exit
[[email protected] mnt]# export a=1
[[email protected] mnt]# bash
[[email protected] mnt]# echo $a
1
[[email protected] mnt]# exit

exit

Linux--RH254---unit 11 bash 2


2.用户级环境变量
[[email protected] mnt]# su - student
[[email protected] ~]$ vim .bash_profile
export a=1
[[email protected] ~]$ source .bash_profile
[[email protected] ~]$ echo $a

1

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2


3.全局变量
[[email protected] mnt]# vim /etc/profile
exprot a=2
[[email protected] mnt]# source /etc/profile
[[email protected] mnt]# echo $a
2
[[email protected] mnt]# su - student
Last login: Wed Jun 21 10:43:49 EDT 2017 on pts/0
[[email protected] ~]$ echo $a
1
[[email protected] ~]$ source /etc/profile
[[email protected] ~]$ echo $a

2

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2


4.别名
(1)使用别名:
alias命令可以用来自定义属于自己的系统命令,写入~/.bashrc文件永久生效。
(2)查看别名:
[[email protected] ~]# alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'

alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

Linux--RH254---unit 11 bash 2


3)永久设置别名:
[[email protected] ~]# vim /etc/bashrc
alias write='vim'
[[email protected] ~]# source /etc/bashrc
[[email protected] ~]# alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'
alias write='vim'

[[email protected] ~]# write

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2

Linux--RH254---unit 11 bash 2


4)删除别名:

unalias write

Linux--RH254---unit 11 bash 2