(一)for 语句:
循环定义变量,依次执行,批量处理;
有以下几种格式:
for NUM in 1 2 3
for NUM in {1..3}
for NUM in {a..f}
for NUM in `seq 1 3 `
for NUM in `seq 1 2 10` //可以设定步长;2就是步长,输出为 1 3 5
还可以是计算的方式(和C语言类似)
for((A=1;A<=10;A++))
do
done
1)脚本示例:
把所有的数据库备份成文件,执行脚本文件备份的数据库放在/mnt/mysql_dump/目录下,并且文件属性为.sql
vim /mnt/mysql-dump.sh
#!/bin/bash
DATABASE_MESSAGE=`mysql -uroot -EN -e "show databases;" | grep -E "^\*|schema$" -v`
mkdir -p /mnt/mysql_dump
for DATABASE in $DATABASE_MESSAGE
do
mysqldump -uroot $DATABASE > /mnt/mysql_dump/$(DATABASE).sql
[ "$?" -eq "0" ] && {
echo -e "\033[31m$DATABASE is backuped!\033[0m"
}
done
sh /mnt/mysql-dump.sh
测试:查看/mnt/mysql_dump目录下是否有以sql结尾的文件.
(二)while 语句
格式:
while 判断条件
do 动作
done
示例:1)刷新时间
vim /mnt/test.sh
2)如果分区使用率超过80%,系统提出报警;
vim /mnt/test.sh
#!/bin/bash
DATA=`df | awk -F " " '/\/$/{print $5}' | awk -F "%" '{print $1}'`
while ture
do
[ "$DATA" -ge "80" ]&&{
echo your / will full! | mail -s warning root
sleep 1
}
done
sh /mnt/test.sh
可以看到用户收到了邮件:
exit 、break 和 continue 的区别
exit | 退出当前执行的脚本 |
---|---|
break | 中断当前的循环,不会影响循环以外的语句 |
continue | 提前跳出循环,提前进入下一次 |
实验证明(exit、break和continue的区别):
[root@desktop mnt]# vim /mnt/test.sh
#!/bin/bash
for NUM in {1..5}
do
if
["$NUM" -eq 3]
then
$1
fi
echo $NUM
done
echo hello westos!!
[root@desktop mnt]# sh test1.sh break
1
2
hello westos!!
[root@desktop mnt]# sh test1.sh exit
1
2
[root@desktop mnt]# sh test1.sh continue
1
2
4
5
hello westos!!
(三) if 语句
基本格式
if
then
elif
then
else
fi
if 语句语句与 [ ] && | | 相似,都是条件判断,但是if语句是可以无限次循环,但那时这几个只能执行一次;
示例 1 :
编写脚本,输入一个文件名称,输出其类型; |
[root@desktop mnt]# vim check_file1.sh
#!/bin/bash
Check_file()
{
if
[ "$1" "$2" ]
then
echo -e "\033[31m$2 is \033[4m$3\033[0m"
fi
}
if
[ "$#" -ne "1" ]
then
echo -e "\033[31mplease input file name after script!\033[0m"
elif
[ ! -e "$1" ]
then
echo -e "\033[31m$1 do not exist!\033[0m"
exit 1
else
Check_file -L $1 link
Check_file -f $1 "common file"
Check_file -S $1 socket
Check_file -b $1 block
Check_file -c $1 character
Check_file -d $1 directory
fi
示例 2:
编写脚本,利用文件建立用户,并修改密码: 要求: 1)文件数量不对报错; 2)文件不存在,报错; 3)文件行数差异,报错; 4)用户存在显示用户存在,但是不改变此用户密码; 5)用户不存在建立用户,并修改密码; |
[root@desktop mnt]# vim user_create.sh
#!/bin/bash
#################### Check error ##############
if
[ "$#" -ne "2" ]
then
echo -e "\033[31m\033[4m1.ERROR:please input userfile and passfile !!\033[0m "
exit 1
elif
[ ! -e "$1" ]
then
echo -e "\033[31m\033[4m2.ERROR:the $1 doesn't exist!!\033[0m"
exit 1
elif
[ ! -e "$2" ]
then
echo -e "\033[31m\033[4m2.ERROR:the $2 doesn't exist!!\033[0m"
exit 1
elif
USERFILE_LINE=`awk 'BEGIN{N=0}{N++}END{print N}' $1`
PASSFILE_LINE=`awk 'BEGIN{N=0}{N++}END{print N}' $2`
[ "$USERFILE_LINE" -ne "$PASSFILE_LINE" ]
then
echo -e "\033[31m\033[4m3.ERROR:$1 is different from $2\033[0m"
exit 1
fi
########################## CREATE USER ##########################
for LINE_NUM in `seq 1 $USERFILE_LINE`
do
USERNAME=`sed -n "${LINE_NUM}p" $1`
PASSWORD=`sed -n "${LINE_NUM}p" $2`
useradd $USERNAME
[ "$?" -eq "0" ]&&{
echo $PASSWORD | passwd --stdin $USERNAME &> /dev/dull && echo -e "\033[31m$USERNAME created successfully!\033[0m"
}
done
示例 3:
运行 test.sh dog输出结果为cat ; cat 输出结果为 dog; 除此以外都输出结果为error; |
[root@desktop mnt]# vim test.sh
#!/bin/bash
if
[ "$1" == "cat" ]
then
echo dog
elif
[ "$1" == "dog" ]
then
echo cat
else
echo erro
fi
( 四 ) case 语句
字符匹配进行同步对比;
示例 1:
运行 test.sh dog输出结果为cat ; cat 输出结果为 dog; 除此以外都输出结果为error; |
[root@desktop mnt]# vim test1.sh
#!/bin/bash
case $1 in
dog)
echo cat
;;
cat)
echo dog
;;
*) //*可以不写
echo error
esac
示例 2:
选择动作,执行相应操作; 执行脚本user_ctrl.sh create userfile passfile ==》建立用户; 执行脚本user_ctrl.sh delete userfile passfile ==》删除用户; 其中,userfile中有linux1 linux2 linux3 3个用户,对应passfile有其相应的密码; |
#!/bin/bash
MAX_LINE=`awk 'BEGIN{N=0}{N++}END{print N}' $2`
case $1 in
create)
for LINE_NUM in `seq 1 $MAX_LINE`
do
USERNAME=`sed -n "${LINE_NUM}p" $2`
PASSWORD=`sed -n "${LINE_NUM}p" $3`
useradd $USERNAME
[ "$?" -eq "0" ]&&{
echo $PASSWORD | passwd --stdin $USERNAME &> /dev/null && echo -e "\033[31mthe $USERNAME create successful!\033[0m"
}
done
;;
delete)
for LINE_NUM in `seq 1 $MAX_LINE`
do
USERNAME=`sed -n "${LINE_NUM}p" $2`
userdel -r $USERNAME
echo -e "\033[31mthe $USERNAME has deleted!\033[0m"
done
esac
示例 3:
非交互式建立分区 |
#!/bin/bash
fdisk /dev/vdb <<FOF
n
p
+$1
wq
FOF
非交互式删除分区 |
#!/bin/bash
fdisk /dev/vdb <<EOF
d
2
wq
EOF
partprobe
解决扩展分区的问题; |
#!/bin/bash
DESK_MESSAGE=`fdisk -l | awk '/Extended/'`
if
[ -z "$DESK_MESSAGE" ]
then
fdisk /dev/vdb <<EOF
n
e
wq
EOF
partprobe
fi
(五)expect 语句
- expect是自动应答命令用于交互式命令的自动执行;注意它不是shell,/usr/bin/expect是他的解释器;
- spawn是expect中的监控程序,其运行后监控命令提出的交互问题;
- send 发送问题答案给交互命令;
- “\r” 表示回车
- expect eof 表示当问题不存在时继续回答下面的问题
- exp_continue 表示问题不存在时继续回答下面问题
- interact 表示问题回答完毕后留在交互界面
set NAME [ lindex $argv n ] 定义变量
例如:set PASS [ lindex $argv 1] //将lindex后的第一串字符给NAME
实验:
在shell环境下编写.sh文件:
在expect环境下,编写.exp文件:
可以看到两者的效果是一样的;
示例 1:
利用expect语句编写自动登陆脚本 执行auto_connect.sh 172.25.254.74 westos 172.25.254.74为ip,westos为密码; 执行脚本后自动登陆172.25.254.74并保持登陆; |
[root@desktop mnt]# vim auto_connect.exp
#!/usr/bin/expect
set timeout 5
set IP [ lindex $argv 0 ]
set PASS [ lindex $argv 1 ]
spawn ssh root@$IP
expect {
"yes/no" { send "yes\r";exp_continue }
"password" {send "$PASS\r"}
}
interact
EOF
示例 2:
批处理脚本: 检测教室中开启的所有主机,并将所有主机的主机名和ip的对应列表,把列表保存在/mnt/hostname |
#!/bin/bash
Auto_Connect()
{
/usr/bin/expect << EOF
spawn ssh root@172.25.254.$IP_NUM hostname
expect {
"yes/no" { send "yes\r";exp_continue }
"password" {send "westos\r"}
}
expect eof
EOF
}
for IP_NUM in 74
do
ping -c1 -w1 172.25.254.$IP_NUM &> /dev/null && {
HOST_NAME=`Auto_Connect| grep -E "password|spawn" -v`
echo $HOST_NAME 172.25.254.$IP_NUM | sed 's/\r//g' >> /mnt/hostname
}
done
[root@desktop mnt]# sh hostname.sh
[root@desktop mnt]# cat hostname
foundation74.ilt.example.com 172.25.254.74