一、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/bashdeclare -i sum=0for i in {1..100}; do if [[ $[$i%2] -eq 0 ]]; then let sum+=$i fidoneecho "the sum of even is $sum"
练习1:传递一个参数给脚本,而后以此参数为用户名,添加此用户;
方法一:
#!/bin/bash#if [ $# -ge 1 ]; then if ! id $1 &>/dev/null;then useradd $1 fifi
方法二:
#!/bin/bash if !id $1 & >> null;then useradd $1 else echo "the user exists" fiif可以嵌套:if CONDITION1; thenif CONDITION2; thenCMDfifi
3.1.2 条件取反:
! CONDITION
练习2:写一个脚本
(1) 添加用户testuser1-tuser10;
(2) 用户不存在时才添加;
(3) 统计真正添加的用户数;
#!/bin/bash#declare -i newusers=0for i in {1..10}; do if ! id testuser$i &> /dev/null; then useradd testuser$i let newusers++ fidoneecho "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." fidone
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 fifibin/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 offlinefidone
练习5:写一个脚本
(1) 传递两个整数参数给脚本;
(2) 返回其较大一个;
#!/bin/bashif [ $1 -lt $2 ]; then echo $2 else echo $1fi
练习6:写一个脚本
(1) 传递两个以上的整数给脚本;
(2) 返回其较大者;
#!/bin/bash#declare -i max=0for i in $*; do if [ $i -gt $max ]; then max=$i fidoneecho "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 $HOSTNAMEecho $HOSTNAME或者:#!/bin/bashsource /etc/sysconfig/networkif [ $HOSTNAME == localhost ] ; then HOSTNAME="www.mage.com"else echo $HOSTNAMEfihostname $HOSTNAMEecho $HOSTNAME
练习8:写一个脚本
(1) 传递两个文本文件路径给脚本;
(2) 显示两个文件中空白行数较多的文件及其空白行数;
(3) 显示两个文件中总行数较多的文件及其行数;
#!/bin/bashi=`grep "^$" $1 | wc -l`j=`grep "^$" $2 | wc -l`if [[ $i -gt $j ]]; then echo " the spaceline: $i"else echo "the spaceline: $j"fik=`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." fielse useradd $1 if [ $? -eq 0 ];then echo "Add user $1." else echo "Cannot add $1." fifi
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/bashif [ "$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/bashif [ $# -lt 1 ] ;thenecho "please input a user name"exit 1fiif id $1 &> /dev/null ; thenuid=`id -u $1`elseecho "no such user"exit 2fiif [ "$uid" -eq 0 ] ;thenecho "The user is administrator"elif [ "$uid" -gt 6000 ] ; thenecho "The user is guest"elif [ "$uid" -gt 500 ] ; thenecho "The user is common"elif [ "$uid" -gt 0 ] ; thenecho "The user is system "elseecho "Cannot found"fi
3.4 文件测试练习
练习12:写一个脚本,传递一个文件路径参数给脚本
(1) 存在,则显示有此文件;
(2) 否则,则显示无此文件
#!/bin/bashif [ -z $1 ];then echo "you entered nothing" exit 1else if [ -e $1 ]; then echo "the file exists" else echo "the file doesn't exist" fifi
练习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 5fiif [ ! -e $1 ]; then echo "No such file." exit 6fiif [ -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/$progif [ $# -lt 1 ]; then echo "Usage: $prog {start|stop|restart|status}" exit 1fi
if [ "$1" == 'start' ]; then if [ -e $lockfile ]; thenecho "$prog is aleady running."exit 1 elsetouch $lockfileecho "Starting $prog succefully." fielif [ "$1" == 'stop' ]; then if [ -e $lockfile ]; thenrm -f $lockfileecho "Stopping $prog succefully." elseecho "$prog is not running."exit 1 fi
elif [ "$1" == 'restart' ]; then if [ -e $lockfile ]; thenrm -f $lockfileecho "Stopping $prog succefully."touch $lockfileecho "Starting $prog succefully." elsetouch $lockfileecho "Starting $prog succefully." fielif [ "$1" == 'status' ];then if [ -e $lockfile ];thenecho "$prog is running." elseecho "$prog is stopped." fielse echo "Usage: $prog {start|restart|status|stop}" exit 1fi
四、组合测试条件:
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/hostnameelse 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 1fiuid=$(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 1fiif [[ `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/bashif [ $# -lt 1 ];thenecho "At least one argument" exit 1fiif ! id $1 &>/dev/null;thenecho "the user does not exist" exit 2fiif id $1 &>/dev/null;thenif [[ `id -u $1` -ge 500 ]] && [[ `grep 'bash$' /etc/passwd | cut -d: -f7` ]];thenecho "a user can log system"elseecho "can not login"fifi
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/bashh=`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"elseecho "No web server"fi
上面是各种方法的组合,可以灵活转换
五、交互式脚本:
read [OPTIONS] [name ...]
用法示例:
[root@node3 ~]# read Ahello[root@node3 ~]# echo $Ahello[root@node3 ~]# read A B Chow old are you?[root@node3 ~]# echo $Ahow[root@node3 ~]# echo $Care 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 << EOFcpu) show cpu infomation;mem) show memory infomation;disk) show disk infomation;*) quit=================================================================EOFread -p "Your choice: " choiceif [[ "$choice" == 'cpu' ]]; then lscpuelif [[ "$choice" == 'mem' ]]; then free -melif [[ "$choice" == 'disk' ]]; then fdisk -l /dev/sd[a-z]else echo "quit" exit 0fi