3unit12

Red Hat System Administration III

####################################单元 十二Bash脚本条件判断和控制流结构

 

###################Bash位置参数

有两种简单的方法可以将用户输入读入bash中的变量。

第一个方法是使用read提示用户输入(使用-p选项)并将其直接存储到一个或多个变量:

交互式输入

# read -p 'Enter your first and last name: ' FIRST LAST

 

另一个方法是使用位置参数来读取传递给脚本的命令行参数或选项输入。各种特殊变量存储传递的选项编号

Bash解析的个别参数或整个原始命令行。

指定的位置参数总数:$#

位置参数自身:$0、$1、$2、$3....

所有位置参数: $@、$*

 

eg:

[root@mail-eastos mnt]# vim test.sh

1 #!/bin/bash

  2 echo $1

  3 echo $2

  4 echo $3

  5 echo $*

  6 echo $#

  7 echo $@

[root@mail-eastos mnt]# chmod +x test.sh

[root@mail-eastos mnt]# ./test.sh hello linux redhat

hello

linux

redhat

hello linux redhat

3

hello linux redhat

 

 

###################退出状态

Linux命令完成时,将返回退出状态。成功完成程序时,将返回0的推出状态。这被bash当作逻辑True值。非零退出状态通常表示发生了错误,并且被bash当作逻辑False值。

 

例如:grep的退出状态的含义:

0 – 在指定的文件中找到了模式

1 – 在指定的文件中未找到模式

>1 – 一些其他错误(无法打开文件、错误的搜索表达式等)

 

推出状态的值被存储在"?"中,可以使用以下命令查看:

# echo $?

 

#####################test条件判断

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

 

语法:test EXPRESSION 或 [EXPRESSION]    【】man test

 非零或零长度字符串运算符:test -{n|z} STRING

[root@server0 ~]# [ -n westos ]; echo $?

0

[root@server0 ~]# [ -z westos ]; echo $?

1

 

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

[root@server0 ~]# [ abc = abc ]; echo $?

0

[root@server0 ~]# [ abc = ABC ]; echo $?

1

[root@server0 ~]# [ abc != ABC ]; echo $?

0

数字比较运算符:-eq、-ne、-lt、-le、-gt、-ge

[root@server0 ~]# [ 1 -eq 1 ]; echo $?

0

[root@server0 ~]# [ 1 -ne 1 ]; echo $?

1

[root@server0 ~]# [ 1 -gt 2 ]; echo $?

1

 

文件状态运算符:test -{b|c|e|f|d|r|w|x|s|L} FILE/DIRECTORY

[root@server0 ~]# [ -b /dev/sda ]; echo $?

1

[root@server0 ~]# [ -c /dev/zero ]; echo $?

0

[root@server0 ~]# [ -e /etc/passwd ]; echo $?

0

[root@server0 ~]# [ -f /etc/passwd ]; echo $?

0

[root@server0 ~]# [ -d /etc/passwd ]; echo $?

1

[root@server0 ~]# [ -L /etc/passwd ]; echo $?

1

eg:检查文件状态脚本

[root@mail-eastos mnt]# vim check_file.sh

#!/bin/bash

  2 CHECK () {

  3         if

  4           [ $1 $2 ]

  5         then

  6         echo $2 is a $3

  7         else

  8         echo $2 is not a $3

  9         fi

 10 }

 11 case "$1" in

 12         -f)

 13         CHECK -f $2 file

 14           ;;

 15         -b)

 16         CHECK -b $2 block

 17           ;;

 18         -d)

 19         CHECK -d $2 directory

 20                      ;;

 21                      *)

 22         echo "ERROR:please input a argment and file after command"

 23 esac

 

 

二进制文件运算符:-ef、-nt、-ot

[root@server0 bin]# [ /bin/mount -ef /usr/bin/mount ]; echo $?

0

[root@server0 bin]# [ /bin/mount -nt /usr/bin/mount ]; echo $?

1

[root@server0 bin]# [ /bin/mount -ot /usr/bin/mount ]; echo $?

1

逻辑运算符:-o、-a、!、&&、||

[root@server0 bin]# [ 2 -gt 1 -a 1 -gt 2 ]; echo $?

1

[root@server0 bin]# [ 2 -gt 1 -o 1 -gt 2 ]; echo $?

0

[root@server0 bin]# [ ! 2 -gt 1 ]; echo $?

1

[root@mail-eastos mnt]# sh check_file.sh -f /etc/passwd

/etc/passwd is a file

[root@mail-eastos mnt]# sh check_file.sh -f /etc/

/etc/ is not a file

[root@mail-eastos mnt]# sh check_file.sh -d /etc/

/etc/ is a directory

 

eg:

[root@mail-eastos mnt]# a=1

[root@mail-eastos mnt]# b=1

[root@mail-eastos mnt]# test "$a" = "$b" &&echo yes

yes

[root@mail-eastos mnt]# [ "$a" = "$b" ]&&echo yes

yes

[root@mail-eastos mnt]# sdAD

bash: sdAD: 未找到命令...

[root@mail-eastos mnt]# echo $?

127

[root@mail-eastos mnt]# ls

check_ip.sh   create_user.sh   db.sh     test.sh

check_num.sh  create_users.sh  passfile  userfile

[root@mail-eastos mnt]# echo $?

0

[root@mail-eastos mnt]# [ 1 -ge 1 ];echo $?

0

 

 

#############################if语句

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

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

示例:

if test “$USER” != 'root' ; then

echo you are not logged in as root

fi

if [ $(id -u) -lt 9 ] ; then

echo “The number $(id -u) is less than 9!”

fi

 

if grep “^${USER}:” /etc/passwd &> /dev/null ; then

echo “${USER} is a local user on the system.”

else

echo “${USER} is not a local user.”

fi

 

systemctl is-active mariadb > /dev/null 2>&1 ; MARIADB_ACTIVE=$?

systemctl is-active postgresql > /dev/null 2>&1 ; POSTGRESQL_ACTIVE=$?

if [ $MARIADB_ACTIVE -eq 0 ];then

mysql

elif [ $POSTGRESQL_ACTIVE -eq 0 ];then

psql

else

sqlite3

fi

 

###########################################case语句

case语句 :它能够把变量的内容与多个模板进行匹配,再根据成功匹配的模板去决定应该执行哪部分代码。

case "$1" in

start)

systemctl start $2

;;

stop)

systemctl stop $2

;;

reload|restart)

systemctl stop $2

systemctl start $2

;;

*)

echo "Usage: $0 (start|stop|restart|reload)"

;;

esac

 

#########################################################expect语句

[root@localhost mnt]# yum install expect

shell中利用expect实现自动应答脚本。

# cat talk # cat auto

echo "who are you?" #!/usr/bin/expect

read who #set timeout 10

echo "hello, $who" spawn ./talk

echo "are you expect "who"

happy?" send "firefly\n"

read answer expect "happy?"

echo "why?" send "Yes,I am happy.\n"

read answer expect "why?"

send "任性!\n"

expect eof

 

exit

[root@localhost mnt]# which expect

/usr/bin/expect

 

eg:

[root@localhost mnt]# vim ask.sh

 #!/bin/bash

  2 read -p "input your name :" NAME

  3 read -p "input your age :" AGE

  4 read -p "input your class :" CLASS

  5 read -p "input your feel :" FELL

  6 echo $NAME is $AGE\'s old and $NAME is $CLASS student fell $FELL

[root@localhost mnt]# vim answer.exp

#!/usr/bin/expect

  2 spawn /mnt/ask.sh

  3 expect {

  4         "name :" {send "yy\r";exp_continue};

  5         "age :" {send "12\r";exp_continue};

  6         "class :" {send "linux\r";exp_continue};

  7         "feel :" {send "happy\r"};

  8 }

  9 expect eof  ##退出会话

 

这一行告诉操作系统脚本里的代码使用那一个shell来执行。

set timeout 10

设置后面所有的expect命令的等待响应的超时时间,单位为秒。

spawn talk

spawn是expect的内部命令,作用是给后面的shell指令加个壳,用来传递交互指令。

expect "who"

判断上次输出结果里是否包含“who”的字符串,如果有则立即返回,否则等待超时时间后返回。

send "westos\n"

执行交互动作,相当于手工输入"westos"。

expect eof

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

interact

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

$argv 参数数组

expect脚本可以接受从bash传递过来的参数.可以使用[lindex $argv n]获得,n从0开始,分别表示第

一个,第二个,第三个....参数。

 

eg:自动连接

[root@localhost mnt]# vim auto_ssh.exp

#!/usr/bin/expect

  2 spawn ssh root@172.25.254.241

  3 expect {

  4         "(yes/no)?" {send "yes\r";exp_continue};

  5         "password:" {send "redhat\r"};

  6 }

  7 interact  ##停留在会话中

[root@localhost mnt]# /mnt/auto_ssh.exp | grep -E "spawn|password" -v

localhost

##########################################环境变量

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

[root@server0 ~]# LINUX=redhat

[root@server0 ~]# echo $LINUX

redhat

[root@server0 ~]# bash

[root@server0 ~]# echo $LINUX

 

[root@server0 ~]# exit

exit

[root@server0 ~]# export LINUX

[root@server0 ~]# bash

[root@server0 ~]# echo $LINUX

redhat

[root@server0 ~]# exit

exit

 

使用env命令显示所有环境变量

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

 

Bash启动脚本

在用户登录的时候,会运行全局变量文件/etc/profile,和用户自定义变量文件

~/.bash_profile去初始化它们的环境变量。

/etc/profile

\_ /etc/profile.d/*.sh

~/.bash_profile

\_ ~/.bashrc

\_ /etc/bashrc

 

使用别名

alias命令可以用来自定义属于自己的系统命令,写入~/.bashrc 文件永久生效。

查看别名:

# alias

alias ls='ls --color=auto'

alias mv='mv -i'

alias rm='rm -i'

...

设置别名:

# alias mycom='echo hello;hostname'

# mycomm

hello

server0.example.com

删除别名: unalias mycomm

eg:

[root@localhost ~]# vim .bashrc  ##局部

[root@localhost ~]# source .bashrc

 

[root@localhost ~]# vim /etc/bashrc ##全局

[root@localhost ~]# source /etc/bashrc

使用函数

pathmunge () {

if [ "$2" = "after" ] ; then

PATH=$PATH:$1

else

PATH=$1:$PATH

fi

}

...

if [ "$EUID" = "0" ]; then

pathmunge /usr/sbin

pathmunge /usr/local/sbin

else

pathmunge /usr/local/sbin after

pathmunge /usr/sbin after

fi

 

eg:

[root@localhost mnt]# echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

[root@localhost mnt]# which ls

alias ls='ls --color=auto'

/usr/bin/ls

[root@localhost mnt]# PATH=$PATH:/mnt

[root@localhost mnt]# echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/mnt

[root@localhost mnt]# ask.sh

[root@localhost mnt]# logout

Connection to 172.25.254.141 closed.

[root@foundation60 ~]# ssh root@172.25.254.141

root@172.25.254.141's password:

Last login: Mon May  1 06:57:21 2017 from 172.25.254.60

[root@localhost ~]# echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

[root@localhost ~]# a=1

[root@localhost ~]# echo $a

1

[root@localhost ~]# bash

[root@localhost ~]# echo $a

 

[root@localhost ~]# export a=1

[root@localhost ~]# bash

[root@localhost ~]# echo $a

1

Connection to 172.25.254.141 closed.

[root@foundation60 ~]# ssh root@172.25.254.141

root@172.25.254.141's password:

Last login: Mon May  1 07:12:51 2017 from 172.25.254.60

[root@localhost ~]# echo $a

 

[root@localhost ~]# su - student

[student@localhost ~]$ echo $a

 

[student@localhost ~]$ vim .bash_profile  ##局部变量

[student@localhost ~]$ echo $PATH

/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/student/.local/bin:/home/student/bin

[student@localhost ~]$ source .bash_profile

[student@localhost ~]$ echo $PATH

/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/student/.local/bin:/home/student/bin:/home/student/.local/bin:/home/student/bin:/mnt

[student@localhost ~]$ exit

logout

[root@localhost ~]# echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

[root@localhost ~]# vim /etc/profile   ##全局变量

[root@localhost ~]# source /etc/profile

 

 

 

eg:

#!/bin/bash

  2 read -p "Give me a world :" HELLO

  3 echo $HELLO

eg:检查指定ip的主机是否开机

[root@mail-eastos mnt]# vim check_ip.sh

1 #!/bin/bash

  2 read -p "please input your ip :" A

3 ping $A -c1 -w1 &>/dev/null && echo $A is up ||echo $A is  down

 

eg:自动创建用户脚本  ##文本行不一样,文件所加个数缺少,用户存在报错

[root@mail-eastos mnt]# vim userfile

[root@mail-eastos mnt]# vim passfile

[root@mail-eastos mnt]# vim create_user.sh

#!/bin/bash

  2 MAX=`wc -l $1|cut -d " " -f 1`

  3 MAX1=`wc -l $2|cut -d " " -f 1`

  4 CHECK=`getent passwd $1`

  5 if

  6         [ "$MAX" -ne "$MAX1" ]

  7 then

  8         echo error

  9 elif

 10         [ -n "$CHECK"]

 11 then

 12         echo error

 13 elif

 14 else

 15 for NUM in $(seq 1 $MAX)

 16 do

 17         NAME=`sed -n ${NUM}p $1`

 18          PASSWORD=`sed -n ${NUM}p $2`

 19          useradd $NAME

 20          echo $PASSWORD |passwd --stdin $NAME

 21 done

 22 fi

  

eg:检测10以内的数字脚本

[root@mail-eastos mnt]# vim check_num.sh

#!/bin/bash

  2 if

  3 [ -n "$1" ]

  4 then

  5         if

  6         [ "$1" -lt "10" -a "$1" -gt "0" ]

  7         then

  8         echo "属于0-10"

  9         else

 10         echo "不属于0-10"

 11         fi

 12 else

 13 echo "please give me a num:"

 14 fi

 

eg:数据库备份脚本

[root@mail-eastos mnt]# vim db.sh

 #!/bin/bash

  2 for DB in $(mysql -e "show databases;" -E -N | grep -v '^*' |gre    p -v 'schema$')

  3 do

  4         echo "Backing up $DB"

  5         mysqldump $DB >/dbbackup/$DB.dump

  6 done

  7 echo ""

  8 for DBDUMP in /dbbackup/*

  9 do

 10 SIZE=$(stat--printf"%s\n"$DBDUMP)

 11 echo "$DBDUMP $SIZE"

 12 done

eg:自动添加分区脚本

[root@localhost mnt]# vim fdisk_add.sh

1 #!/bin/bash

  2 fdisk $1 <<end

  3 n

  4

  5

  6

  7 +100M

  8 wq

  9 end

[root@localhost mnt]# sh fdisk_add.sh /dev/vdb

 

posted @ 2017-05-01 19:41  yangying  阅读(140)  评论(0编辑  收藏  举报