编写Shell管理脚本(二)
一、if语句
1,条件测试
test  测试表达式是否成立,成立结果为0
测试文件状态:
 -d 是否为目录
 -e 目录或文件是否存在
 -f 是否为文件
 -r 当前用户是否有权限读取
 -w 当前用户是否有权限写入
 -x 当前用户是否可执行该文件
 -L 是否为符号连接文件
数值比较:
 -eq 等于   Equal 
 -ne 不等于   Not Equal
 -gt 大于     Greater Than
 -lt 小于      Lesser Than 
 -le 小于或等于    Lesser or Equal 
 -ge 大于或等于    Greater or Equal 
字符串比较:
  = 内容相同
 != 内容不同,! 号表示相反的意思
 -z 内容为空
条件判断:
-a或&& 逻辑与
 前后表达式都成立时整个测试结果才为真,否则为假 
-o或|| 逻辑或
 操作符两边至少一个为真时,结果为真,否则结果为假
! 逻辑否
 当指定的条件不成立时,返回结果为真  

先测试“/etc/vsftpd”、“/etc/hosts”是否为目录,并通过“$?”变量查看返回状态值,据此判断测试结果。
[root@localhost ~]# [ -d /etc/vsftpd ]
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ -d /etc/hosts ]
[root@localhost ~]# echo $?
1
[root@localhost ~]# ls -ld /etc/vsftpd /etc/hosts
-rw-r--r-- 2 root root  187 10-17 13:53 /etc/hosts
drwxr-xr-x 2 root root 4096 10-18 13:31 /etc/vsftpd
 
测试“/media/cdrom/Server”及其父目录是否存在,如果存在则显示“YES”,否则不输出任何信息。
[root@localhost ~]# [ -e /media/cdrom/Server ] && echo "YES"
                                              //无输出表示该目录不存在
[root@localhost ~]# [ -e /media/cdrom ] && echo "YES"
YES                                           //显示YES表示该目录存在

使用普通用户teacher登录,并测试是否对“/etc/passwd”文件有读、写权限,如果是则显示“YES”。
[teacher@localhost ~]$ [ -w /etc/passwd ] && echo "YES"
[teacher@localhost ~]$ [ -r /etc/passwd ] && echo "YES"
YES

测试当前登录到系统中的用户数量是否小于或等于10,是则输出“YES”。
[root@localhost ~]$ who | wc -l
2
[root@localhost ~]$ [ `who | wc -l` -le 10 ] && echo "YES"
YES

提取出“/boot”分区的磁盘使用率,并判断是否超过95%(为了便于理解,操作步骤以适当进行分解)。
[root@localhost ~]# df -hT | grep "/boot" | awk '{print $6}'
[root@localhost ~]# read -p "Localtion: " FilePath 
Localtion: /etc/inittab   
[root@localhost ~]# [ $FilePath = "/etc/inittab" ] && echo "YES"
YES

若当前环境变量LANG的内容不是“en.US”,则输出LANG变量的值,否则无输出。
[root@localhost ~]# [ $LANG != "en.US" ] && echo $LANG
zh_CN.UTF-8

使用touch命令建立一个新文件,测试其内容是否为空,向文件中写入内容后,再次进行测试。
[root@localhost ~]# touch zero.file
[root@localhost ~]# [ -z 'cat zero.file' ] && echo "YES"
YES                                      //表示该文件为空文件
[root@localhost ~]# [ -z 'cat zero.file' ] && echo "YES"
[root@localhost ~]# echo "something" > zero.file
[root@localhost ~]# [ -z 'cat zero.file' ] && echo "YES"
                                         //无输出表示文件不为空

测试当前的用户是否是teacher,若不是则提示“Not teacher”。
[root@localhost ~]# echo $USER
root
[root@localhost ~]# [ $USER = "teacher" ] || echo "Not teacher"
Not teacher

只要“/etc/rc.d/rc.local”或者“/etc/init.d/rc.local”中有一个是文件,则显示“YES”,否则无任何输出。
[root@localhost ~]# [ -f /etc/rc.d/rc.local ] || [ -f /etc/init.d/rc.local ] && echo "YES"
YES

测试“/etc/profile” 文件是否有可执行权限,若确实没有可执行权限,则提示“No x mode.”的信息。
[root@localhost ~]# [ ! -x "/etc/profile" ] && echo "No x mode."
No x mode.

若当前的用户是root且使用的shell程序是“/bin/bash”, 则显示“YES”,否则无任何输出。
[root@localhost ~]# echo $USER $SHELL
root /bin/bash
[root@localhost ~]# [ $USER = "root" ] && [ $SHELL = '/bin/bash' ] && echo "YES" 
YES
 
2,if语句格式
单分支:
if  条件测试命令 
    then   命令序列
fi
双分支:
if  条件测试命令
    then   命令序列1
    else   命令序列2
fi
多分支:
if  条件测试命令1  ;  then
    命令序列1
elif  条件测试命令2  ;  then
    命令序列2
elif  ...
else
    命令序列n
fi 


检查“/var/log/messages”文件是否存在,若存在则统计文件内容的行数并输出,否则不做任何操作(合理使用变量,可以提高编写效率)。
[root@localhost ~]# vi chklog.sh
#!/bin/bash
LogFile="/var/log/messages"
if [ -f $LogFile ] ;  then
    wc -l $LogFile
fi
[root@localhost ~]# sh chklog.sh 
1005 /var/log/messages

提示用户指定备份目录的路径,若目录已存在则显示提示信息后跳过,否则显示相应提示信息后创建该目录。
[root@localhost ~]# vi mkbak.sh
#!/bin/bash
read -p "What is your backup directory: " BakDir
if [ -d $BakDir ] ; then
echo "$BakDir already exist. "
else
    echo "$BakDir is not exist, will make it. "
    mkdir $BakDir
fi
[root@localhost ~]# sh mkbak.sh 
What is your backup directory: /opt/bakroot
/opt/bakroot is not exist, will make it. 
[root@localhost ~]# ls -ld /opt/bakroot/
drwxr-xr-x. 2 root root 4096 11?.17 19:30 /opt/bakroot/

统计当前登录到系统中的用户数量,并判断是否超过三个,若是则显示实际数量并给出警告信息,否则列出登录的用户账号名称及所在终端。
[root@localhost ~]# vi chkuser.sh
#!/bin/bash
UserNum=`who | wc -l`
if [ $UserNum -gt 3 ] ; then
    echo "Alert, too many login users ( Total: $UserNum ). "
else
    echo "Login users: "
    who | awk '{print $1,$2}'
fi
[root@localhost ~]# sh chkuser.sh 
Login users: 
root tty1
root pts/0

检查portmap进程是否已经存在,若已经存在则输出“portmap service if running.” ;否则检查是否存在“/etc/rc.d/init.d/portmap” 可执行脚本,存在则启动portmap服务,否则提示“no portmap script file.”。
[root@localhost ~]# vi chkportmap.sh
#!/bin/bash
pgrep portmap &> /dev/null
if [ $? -eq 0 ] ; then
    echo "portmap service is running. "
elif [ -x "/etc/rc.d/init.d/portmap" ] ; then
     service portmap start
else
    echo "no portmap script file. "
fi
[root@localhost ~]# sh chkportmap.sh 
no portmap script file.

每隔五分钟监测一次mysqld服务进程的运行状态,若发现mysqld进程已终止,则在“/var/log/messages”文件中追加写入日志信息(包括当时时间),并重启mysqld服务;否则不进行任何操作。
[root@localhost ~]# vi chkportmap.sh
#!/bin/bash
service mysqld status &> /dev/null
if [ $? -ne 0 ] ; then
   echo "At time: `date`: MySQL server is down. " >> /var/log/messages
   service mysqld restart
fi
[root@localhost ~]# sh chkportmap.sh
[root@localhost ~]# tail -1 /var/log/messages
At time: 2011 年 11 月 18 日 星期五 20:16:31 CST : MySQL server is down.
[root@localhost ~]# crontab –e     //需确认crond服务已运行
*/5 * * * * /root/chkdbsvr.sh

二、for语句
根据变量的不同取值,重复执行一组命令操作

语法:
for  变量名  in  取值列表
do
     命令序列
done  


依次输出三条文字信息,包括一天中的“Moring”、“Noon”、“Evening”字串。
[root@localhost ~]# vi showday.sh
#!/bin/bash
for TM in "Morning" "Noon" "Evening"
do
    echo "The $TM of the day. "
done
[root@localhost ~]# sh showday.sh 
The Morning of the day. 
The Noon of the day. 
The Evening of the day.

对于使用“/bin/bash”作为登录shell的系统用户,检查他们在“/opt”目录中拥有的子目录或文件数量,如果超过100个,则列出具体数值及对应的用户账号。
[root@localhost ~]# vi chkfileown.sh
 
#!/bin/bash
DIR="/opt"
LMT=100
ValidUsers=`grep "/bin/bash" /etc/passwd | cut -d ":" -f 1`
for UserName in $ValidUsers
do
   Num=`find $DIR -user $UserName | wc -l`
   if [ $Num -gt $LMT ] ; then
         echo "$UserName have $Num files. "
   fi
done
[root@localhost ~]# sh chkfileown.sh 
[root@localhost ~]# find -user root | wc -l
40

计算“/etc”目录中所有“*.conf”形式的配置文件所占用的总空间大小。
[root@localhost ~]# vi confsize.sh
#!/bin/bash
SizeNums=$(ls -l $(find /etc -type f -a -name *.conf) | awk '{print $5}')
Total=0
for i in $SizeNums
do
    Total=`expr $Total + $i`
done
echo "Total size of conf files: $Total bytes. "
[root@localhost ~]# sh confsize.sh 
Total size of conf files: 813 bytes.
三、while语句
重复测试指定的条件,只要条件成立则反复执行对应的命令操作

语法:
 while  命令或表达式
 do
            命令列表
 done 


由用户从键盘输入一个大于1的整数(如50),并计算从1到该数之间各整数的和。
[root@localhost ~]# vi sumint.sh
#!/bin/bash
read -p "Input a number (>1): "  UP
i=1
sum=0
while [ $i -le $UP ]
do
    sum=`expr $sum + $i`
    i=`expr $i + 1`
done
echo "The sum of 1-$UP is : $sum"
[root@localhost ~]# sh sumint.sh 
Input a number (>1): 50
The sum of 1-50 is : 1275

批量添加20个系统用户账号,用户名称依次为“stu1”、“stu2”、“stu3”、……“stu20”,各用户的初始密码均设置为“123456”。
[root@localhost ~]# vi add20users.sh
#!/bin/bash
i=1
while [ $i -le 20 ]
do
useradd stu$i
echo "123456" | passwd --stdin stu$i &> /dev/null
     i=`expr $i + 1`
done
[root@localhost ~]# sh add20users.sh
[root@localhost ~]# tail -2 /etc/passwd
stu19:541:541::/home/stu19:/bin/bash
stu20:542:542::/home/stu20:/bin/bash

编写一个批量删除用户的脚本程序,将上例中添加的20个用户删除。
[root@localhost ~]# vi del20users.sh
 
#!/bin/bash
i=1
while [ $i -le 20 ]
do
      userdel -r stu$i
      i=`expr $i + 1`
done
[root@localhost ~]# sh del20users.sh
[root@localhost ~]# grep "stu" /etc/passwd     //无输出则表示上述用户已删除