一、if语句:

单分支:

if CONDITION-TRUE; then

分支

fi

双分支:

if CONDITION-TRUE; then

分支1

else

分支2

fi

多分支:

if CONDITION1-TRUE; then

分支1

elif CONDITION2-TRUE; then

分支2

...

else

分支n

fi


二、条件测试:

test EXPRESSION

[ EXPRESSION ]

` EXPRESSION `

COMMAND


2.1 测试表达式:

(1) 整数测试; 

(2) 字符串测试;

(3) 文件测试


2.2 整数测试:A, B

A -gt B: 大于

A -ge B: 大于等于

A -eq B: 等于

A -lt B: 小于

A -le B: 小于等于

A -ne B: 不等于  not equal to


2.3 字符串测试:A, B

A > B

A < B

A >= B

A <= B

A == B或A = B:等值比较

A != B: 不等于

-z A: 判断A是否为空;空则为真,不空则假;

-n A:判断A是否不空;不空则为真,空则为假;

=~

"$A" =~ PATTERN

如果变量A中保存的字符串能被PATTERN所匹配;即为真;否则为假;

2.4 文件测试:$file

-e $file: 是否存在;存在则为真;

-a $file: 同上;弃用;

-f $file: 文件是否存在,且为普通文件;

-d $file: 是否存在且为目录;

-h $file: 是否存在且为符号链接文件;

-L $file:同上

-b $file: 是否存在且为块设备文件;

-c $file: 是否存在且为字符设备文件;

-S $file: 是否存在且为套接字文件:

-p $file: 是否存在且为管道文件;


-r $file: 当前用户对此文件是否拥有读权限;

-w $file:                         写

-x $file:                         执行权限;


-u $file: 文件是否拥有suid权限;

-g $file:文件是否拥有sgid权限;

-k $file: 文件是否拥有sticky权限;


-O $file: 当前用户是否为文件的属主;

-G $file: 当前用户是否属于文件的属组;


-N $file: 文件自从上一次被读取之后,是否被修改过;

例如:

# cp /etc/fstab  /tmp/

# cat /tmp/fstab

# [ -N /tmp/fstab ]

# echo $?

1

# echo "hell world" >> /tmp/fstab

# [ -N /tmp/fstab ]

# echo $?

0

                  -s 测试文件是否不空,不空则为真,空则为假


$f1 -nt $f2: 文件f1是否比文件f2新;

$f1 -ot $f2: 文件f1是否比文件f2旧;

$f1 -ef $f2: f1和f2是否为同一个文件的硬链接;


2.5 COMMAND用作条件:

(1) 使用命令执行结果;

(a) 使用命令引用

(b) 使用比较操作符


例如:

[ `id -u $username` -lt 500 ]
userid=`id -u $username`
[ $userid -lt 500 ]


(2) 使用命令的退出状态码

(a) 先运行命令;

(b) 退出状态码


引用方式两种:

(a) if COMMAND; then

注意:COMMAND不能被命令引用;COMMAND的执行结果通常没有意义,所以其结果通常(&>)被定向至/dev/null

(b) 先执行命令,后判断退出状态码是否为0

COMMAND

if [ $? -eq 0 ]


三、条件测试语法:

3.1 单分支:

             3.1.1 

if CONDITION; then

CMD1

CMD2

...

fi


例如:求100以内所有偶数之和;遍历100以内所有正整数;

    #!/bin/bash
declare -i sum=0
for i in {1..100}; do
    if [[ $[$i%2] -eq 0 ]]; then
       let sum+=$i
    fi
done
echo "the sum of even is $sum"


练习1:传递一个参数给脚本,而后以此参数为用户名,添加此用户;

方法一:

#!/bin/bash
#
if [ $# -ge 1 ]; then
        if ! id $1 &>/dev/null;then
        useradd $1
        fi
fi


方法二:

#!/bin/bash
     if !id $1 & >> null;then
         useradd $1
               else
               echo "the user exists"
               fiif可以嵌套:
if CONDITION1; then
if CONDITION2; then
CMD
fi
fi


    3.1.2 条件取反:

! CONDITION


练习2:写一个脚本

(1) 添加用户testuser1-tuser10;

(2) 用户不存在时才添加;

(3) 统计真正添加的用户数;

#!/bin/bash
#
declare -i newusers=0
for i in {1..10}; do
    if ! id testuser$i &> /dev/null; then
        useradd testuser$i
        let newusers++
    fi
done
echo "New users: $newusers."


练习3: 写一个脚本

(1) 用ping命令测试172.16.100.X内的所有主机;

(2) 将在线的主机输出出来;

#!/bin/bash
#
for i in {1..254}; do
    if ping -c1 -w1 172.16.100.$i &> /dev/null; then
        echo "172.16.100.$i is up."
    fi
done


3.2 双分支:

if CONDITION-TRUE; then

分支1

else

分支2

fi


练习4: 写一个脚本

  (1) 用ping命令测试172.16.100.X内的所有主机;

(2) 将所有主机的在线状态输出出来; 

#!/bin/bash
#!/f [ $# -ge 1 ]; then
        if ! id $1 &>/dev/null;then
        useradd $1
        fi
fibin/bash
#
for i in {1..255};do
        if  ping -c1 -w1 172.16.100.$i &>/dev/null;then
        echo the host: 172.16.100.$i is online
        else
        echo the host: 172.16.100.$i is offline
fi
done


练习5:写一个脚本

(1) 传递两个整数参数给脚本;

(2) 返回其较大一个;

#!/bin/bash
if [ $1 -lt $2 ]; then
       echo $2
   else
       echo $1
fi


练习6:写一个脚本

(1) 传递两个以上的整数给脚本;

(2) 返回其较大者;

#!/bin/bash
#
declare -i max=0
for i in $*; do
    if [ $i -gt $max ]; then
        max=$i
    fi
done
echo "max: $max."


练习7: 写一个脚本

(1) 取得当前的主机名;

(2) 如果当前的主机名为localhost,则将其修改为www.magedu.com;否则,显示其名称;

#!/bin/bash
              source /etc/sysconfig/network       (读取HOSTNAME配置文件,让变量$HOSTNAME可以直接引用)
#echo $HOSTNAME
[ "$HOSTNAME" == "localhost"  ] && HOSTNAME="www.mage.com"
#/bin/hostname $HOSTNAME             (修改主机名,若在配置文件修改,可永久生效,但需要重启;而hostname加newname可临时修改;为避免重启,所以做临时修改;而hostname前加/bin/;是因为/bin/为二进制程序配置文件库;怕在脚本中直接用hostname修改不了)
hostname $HOSTNAME
echo $HOSTNAME
或者:
#!/bin/bash
source /etc/sysconfig/network
if [ $HOSTNAME == localhost ] ; then
    HOSTNAME="www.mage.com"
else
   echo $HOSTNAME
fi
hostname $HOSTNAME
echo $HOSTNAME


练习8:写一个脚本

(1) 传递两个文本文件路径给脚本;

(2) 显示两个文件中空白行数较多的文件及其空白行数;

(3) 显示两个文件中总行数较多的文件及其行数;

#!/bin/bash
i=`grep "^$" $1 | wc -l`
j=`grep "^$" $2 | wc -l`
if [[ $i -gt $j ]]; then
    echo " the spaceline: $i"
else
    echo "the  spaceline: $j"
fi
k=`cat $1 | wc -l`
L=`cat $2 | wc -l`
if [[ $k -gt $L ]]; then
   echo "the file is $1 & the totalline is $k"
else
   echo "the file is $L & the totalline is $L"
fi


练习9:写一个脚本

(1) 传递一个参数给脚本,此参数为用户名;

(2) 如果用户存在,则执行如下任务

(a) 如果用户的id号小于500,显示其为管理员或系统用户;

(b) 否则,显示其为普通用户;

(3) 如果用户不存在,则添加之;

#!/bin/bash
#
if id $1 &> /dev/null; then
     userid=`id -u $1`
    if [ $userid -lt 500 ]; then
        echo "$1 is sysadmin or sysuser."
    else
        echo "A common user."
    fi
else
    useradd $1
    if [ $? -eq 0 ];then
        echo "Add user $1."
    else
        echo "Cannot add $1."
    fi
fi


3.3 多分支的if语句:

if CONDITION1-TRUE; then

分支1

elif CONDITION2-TRUE; then

分支2

elif CONDITION3-TRUE; then

分支3

...

else

分支n

fi


练习10:传递一个参数给脚本

如果参数为quit,则显示说要退出脚本;

如果参数为yes,则显示说继续;

否则,则显示为无法识别;

#!/bin/bash
if [ "$1" == "quit" ];then         或者[ $1 == quit ]
       echo "exit"
elif [ "$1" == "yes" ];then
               echo "continue"
else
               echo "Not recognized"
fi


练习11:传递一个用户名参数给脚本

(1) 如果用户的id号为0,则显示为管理员;

(2) 如果用户的id号大于6000,则显示为guest; 

(3) 如果用户的id号大于500,则显示为普通用户;

(4) 如果用户的id号大于0, 则显示为系统用户;

(5) 否则,无法识别;

#!/bin/bash
#
if [ -z $1 ]; then 
        #echo "Usage: $(basen"
        echo "Not recognized"
        exit 1  
elif ! id $1 &> /dev/null; then
        #echo "Unknown....This isn't a user."
        echo "Not recognized"
        exit 2  
else
       userid=$(id -u $1)
       if [ $userid -eq 0 ]; then 
               echo "Admin user"
       elif [ $userid -gt 6000 ]; then 
               echo "Guest user"
       elif [ $userid -gt 500 ] && [ $userid -le 6000 ]; then 
               echo "Comon user"
       elif [ $userid -gt 0 ] && [ $userid -le 500 ]; then 
               echo "System user"
       fi      
fi

或者

#!/bin/bash
if [ $# -lt 1 ] ;then
echo "please input a user name"
exit 1
fi
if id $1 &> /dev/null ; then
uid=`id -u $1`
else
echo "no such user"
exit 2
fi
if [ "$uid" -eq 0 ] ;then
echo "The user is administrator"
elif [ "$uid" -gt 6000 ] ; then
echo "The user is guest"
elif [ "$uid" -gt 500 ] ; then
echo "The user is common"
elif [ "$uid" -gt 0 ] ; then
echo "The user is system "
else
echo "Cannot found"
fi


    3.4 文件测试练习    

练习12:写一个脚本,传递一个文件路径参数给脚本

(1) 存在,则显示有此文件;

(2) 否则,则显示无此文件

      #!/bin/bash
if [ -z $1 ];then
   echo "you entered nothing"
      exit 1
else
   if [ -e $1 ]; then
      echo "the file exists"
   else
      echo "the file doesn't exist"
  fi
fi


练习13:写一个脚本,传递一个文件路径参数给脚本

(1) 如果脚本无参数,则显示必须给至少一个参数,退出脚本;退出码5;

(2) 路径指向的文件如果不存在,则直接退出脚本;退出码为6;

(3) 判断文件类型:

(a) 如果是普通文件,则显示为"common file";

(b) 如果是目录,则显示为"directory";

(c) 如果是符号链接,则显示为"symbolic link file";

(d) 如果是块设备,则显示为“block device file";

(e) 如果是字符设备,则显示为"character device file";

(f) 否则,则显示为“unkown”;

#!/bin/bash
#
if [ $# -lt 1 ]; then
    echo "At least one argument."
    exit 5
fi
if [ ! -e $1 ]; then
    echo "No such file."
    exit 6
fi
if [ -f $1 ]; then
    echo "common file."
elif [ -d $1 ]; then
    echo "directory."
elif [ -L $1 ]; then
    echo "Symbolic link."
elif [ -b $1 ]; then
    echo "block device."
elif [ -c $1 ]; then
    echo "character device."
else
    echo "unkown type."
fi


练习14:写一个脚本,其使用格式如下所示(其中所有的script.sh均为用户给定的脚本名称,其要跟随脚本名称变化):

script.sh {start|stop|restart|status} 

(1) 调用时至少传递一个参数;否则,则显示帮助信息,并退出脚本;

(2) 如果参数为“start”, 则创建空文件/var/lock/subsys/script.sh,并显示“starting script.sh successfully.”;

(3) 如果参数为“stop”,则删除空文件/var/lock/subsys/script.sh,并显示“stopping script.sh successfully.”;

(4) 如果参数为“restart”,则删除空文件/var/lock/subsys/script.sh,并显示“stopping script.sh successfully.”;而后重新创建之,并显示“restarting script.sh successfully.”;

(5) 如果参数为“status”,则

(a) 如果文件/var/lock/subsys/script.sh文件存在,则显示“running”;

(b) 否则,则显示为"stopped"

(6) 其它任意参数,均显示帮助信息后退出;帮助信息格式为命令使用格式;

 
#!/bin/bash
#
# chkconfig: 2345 95 5                    
# description: test service script        此两行为开机启动脚本格式;可以cp到脚本配置文件 /etc/init.d 里面;但需要先给其权限;然后再拷贝;然后在命令行键入chkfig -add script.sh 运行;则可生效
#
prog=`basename $0`                       $0是从当下目录到其有$0脚本的完全路径
lockfile=/var/lock/subsys/$prog
if [ $# -lt 1 ]; then
    echo "Usage: $prog {start|stop|restart|status}"
    exit 1
fi
if [ "$1" == 'start' ]; then
    if [ -e $lockfile ]; then
echo "$prog is aleady running."
exit 1
    else
touch $lockfile
echo "Starting $prog succefully."
    fi
elif [ "$1" == 'stop' ]; then
    if [ -e $lockfile ]; then
rm -f $lockfile
echo "Stopping $prog succefully."
    else
echo "$prog is not running."
exit 1
    fi

elif [ "$1" == 'restart' ]; then
    if [ -e $lockfile ]; then
rm -f $lockfile
echo "Stopping $prog succefully."
touch $lockfile
echo "Starting $prog succefully."
    else
touch $lockfile
echo "Starting $prog succefully."
    fi
elif [ "$1" == 'status' ];then
    if [ -e $lockfile ];then
echo "$prog is running."
    else
echo "$prog is stopped."
    fi
else
    echo "Usage: $prog {start|restart|status|stop}"
    exit 1
fi


四、组合测试条件:

4.1 给条件添加逻辑操作符;

或, -o: [ -z "$hostname" -o "$hostname" == 'localhost' ]

与, -a: [ $uid -gt 0 -a $uid -lt 500 ]

非:[ ! EXPRESSION ]


练习15:写一个脚本,取得当前的主机名,判断      答案参照552练习4题;

(1) 如果主机名为空或为"localhost",则将其命名为stuX.magedu.com;

(2) 否则,则显示主机名即可;

#!/bin/bash
#
hostname=`hostname`
if [ "$hostname" == 'localhost' -o -z "$hostname" ]; then
    hostname stu100.magedu.com
    #echo "stu100.magedu.com" > /proc/sys/kernel/hostname
else
    echo "The hostname is: $hostname."
fi


练习16:写一个脚本,传递一个参数给脚本;此参数为用户名

(1) 如果用户不存在,则直接退出脚本;

(2) 如果用户存在,

id=0,则显示为“system admin”

0<id<500,则显示为“system user”

id>=500,则显示为“Common user.”

#!/bin/bash
#
if ! id $1 &> /dev/null; then
    echo "No such user."
    exit 1
fi
uid=$(id -u $1)   注意:大写UID在此处用可能有会冲突,也可找其他字母代替
if [ $uid -eq 0 ]; then
    echo "Sys Admin."
elif [ $uid -gt 0 -a $uid -lt 500 ];then
    echo "Sys User."
else
    echo "Common User."
fi


练习17:写一个脚本,传递一个参数给脚本;此参数为用户名

(1) 如果用户不存在,则直接退出脚本;

(2) 如果用户的id号大于等于500,且其shell为“以sh结尾的”类型,则显示“a user can log system.”;否则,显示用户无法登录;

#!/bin/bash
#
if ! id $1 &> /dev/null; then
    echo "No such user."
    exit 1
fi
if [[ `id -u $1` -ge 500 ]] && [[ `grep "^$1\>" /etc/passwd | cut -d: -f7` =~ /bin/.*sh$ ]]; then
    echo "a user can log system."
else
    echo "a user cannot log."
fi

或者

#!/bin/bash
if [ $# -lt 1 ];then
echo "At least one argument"
        exit 1
fi
if ! id $1 &>/dev/null;then
echo "the user does not exist"
        exit 2
fi
if id $1 &>/dev/null;then
if [[ `id -u $1` -ge 500 ]] && [[ `grep 'bash$' /etc/passwd | cut -d: -f7` ]];then
echo "a user can log system"
else
echo "can not login"
fi
fi


4.2 组合测试条件:短路操作符

与:COMMAND1 && COMMAND2

COMMAND1的退出状态如果为假,则COMMAND2不用运行,即可有最终结果;

或:COMMAND1 || COMMAND2

COMMAND1的退出状态如果为真,则COMMAND2不用运行,即可有最终结果;

非:! COMMAND


[ ! -d /tmp/test ] && mkdir /tmp/test

   [ -d /tmp/test ] || mkdir /tmp/test


练习18:写一个脚本,完成如下任务:

(1) 如果httpd进程或nginx进程处于运行中,则显示“web server started.”,并显示其监听的端口;

(2) 否则显示“no web server.”;

         (if pidof httpd &> /dev/null && pidof nginx &> /dev/null;) 


#!/bin/bash
h=`netstat -lntp | grep 'httpd' | cut -d':' -f4`
n=`ss -tnlp | grep 'nginx' | cut -d":" -f2 | cut -d" " -f1`
if pidof httpd &>/dev/null;then
  #   netstat -tnlp | grep 'httpd' | cut -d':' -f4    
       echo "the httpd web server started"
    echo "the httpd listenning port is $h"
  elif pidof nginx &>/dev/null;then
   #         ss -tnlp | grep 'nginx' | cut -d":" -f2 | cut -d" " -f1
   #  netstat -ntpl | grep 'nginx' | cut -d: -f2 | cut -d" " -f1   
   echo "the nginx web server started"
echo "the nginx listenning port is $n"
else
echo "No web server"
fi

         上面是各种方法的组合,可以灵活转换


五、交互式脚本:

read [OPTIONS] [name ...]

用法示例:

[root@node3 ~]# read A
hello
[root@node3 ~]# echo $A
hello
[root@node3 ~]# read A B C
how old are you?
[root@node3 ~]# echo $A
how
[root@node3 ~]# echo $C
are you?


-p "PROMPT"  提示信息

-t #: 超时时长


给变量以默认值:

[ -z "$VAR" ] && VAR=VALUE


练习19:显示如下菜单给用户

cpu) show cpu infomation;

mem) show memory infomation;

disk) show disk infomation;

*) quit

提示用户键入选项:

(1) cpu: 显示CPU相关的信息

(2) mem: 显示内存相关的信息

(3) disk: 列出磁盘设备

(4) 其它任何信息,即为退出脚本

#!/bin/bash
#
cat << EOF
cpu) show cpu infomation;
mem) show memory infomation;
disk) show disk infomation;
*) quit
=================================================================
EOF
read -p "Your  choice: " choice
if [[ "$choice" == 'cpu' ]]; then
    lscpu
elif [[ "$choice" == 'mem' ]]; then
    free -m
elif [[ "$choice" == 'disk' ]]; then
    fdisk -l /dev/sd[a-z]
else
    echo "quit"
    exit 0
fi