Linux下的shell(三):普通脚本的编写
文章目录
- Linux下的shell(三):普通脚本的编写
- 1.脚本中的语句控制器
- 2.if判断语句
- 3.case判断语句
- 4.expect语句
- 【4】使用expect语句编写脚本实现功能:输入ip和密码,实现自动ssh连接
- 【5】使用expect语句编写脚本实现功能:自动测试十台主机是否可以ping,可以则显示主机名
- 【6】编辑脚本实现功能:执行命令后建立名单中的用户,并设定密码为指定文件中的密码。当执行脚本时没有输入用户名单以及密码文件时、当用户名单与密码文件的行数不同时、当有文件不存在时、当新建的用户已存在时均报错。
- 【7】编辑脚本实现功能:执行脚本并输入密码后会备份数据库中的所有库到/mnt/db/musqldump目录中。并且备份文件名称为“库名称.sql”,当此文件存在时报错并询问动作:输入“S”跳过备份,输入“B”时备份“库名词.sql”文件为“库名称_backup.sql”,输入“O”则覆盖源文件。
- 5.shell中常用的运算命令
1.脚本中的语句控制器
exit n 脚本退出,退出值为n
break 退出当前循环
continue 提前结束循环内部的命令,但不终止循环
2.if判断语句
使用if语句可以对条件进行依次判断。
格式:
if 如果(判断条件1)
then 那么
(满足条件1要执行的动作)
elif 又如果(判断条件2)
then 那么
(满足条件1要执行的动作)
... ...
else 否则(以上所有条件都不满足)
(都不满足时要执行的动作)
fi 结尾
【1】编写脚本实现功能:使用if语句编写脚本,实现输入命令调用相应功能
vim filectrl.sh
#!/bin/bash
[ -z "$1" ]&&{ 判断是否输入命令
echo -e "\033[31mPlease input scrip first[-a or -d or -p]! following $0\033[0m"
}
[ -z "$2" ]&&{ 判断是否输入相应文件
echo -e "\033[31mPlease input filename following scrip ! \033[0m"
exit 0
}
if [ "$1" = "-d" ] 当输入的命令为“-d”时,删除相应文件
then
`rm -fr "$2"`
echo -e "\033[32m$2 is deleted...\033[0m"
elif [ "$1" = "-a" ] 当输入的命令为“-a”时,判断文件是否存在,如果存在则报错,不存在则新建相应文件
then
[ -e "$2" ]&&{
echo -e "\033[31m$2 is exist...\033[0m"
}||{
`touch "$2"`
echo -e "\033[32m$2 is added...\033[0m"
}
elif [ "$1" = "-p" ] 当输入的命令为“-p”时,对相应文件进行备份,如果备份文件已存在则进行提示
then
[ -e "${2}.bak" ]&&{
echo -e "\033[31m${2}.bak is exist...\033[0m"
}||{
cp $2 ${2}.bak
echo -e "\033[32m$2 is copy...\033[0m"
}
else 当输入的命令是其他命令是,提示输入正确命令
echo -e "\033[31mPlease input -a or -d or -p following $0...\033[0m"
fi
【2】编写脚本实现功能:使用if语句,输入文件名查看文件类型
#!/bin/bash
READ() 设定函数
{
read -p "Please input filename [or exit to quit] : " NAME 获取文件名变量
if [ "$NAME" = "exit" -o "$NAME" = "EXIT" ] 当输入“exit”时,直接退出
then
echo -e "\033[31mbye~\033[0m"
exit 0
elif [ -L "$NAME" ] 判断文件是否为软链接
then
echo -e "\033[32m$NAME is softlink file...\033[0m"
elif [ -d "$NAME" ] 判断文件是否为目录
then
echo -e "\033[32m$NAME is direcotry...\033[0m"
elif [ -f "$NAME" ] 判断文件是否为规则文件
then
echo -e "\033[32m$NAME is common file...\033[0m"
else 如果都不是则报错并重新再次执行函数
echo -e "\033[31m$NAME is not exist...\033[0m"
READ
fi
}
READ 执行函数
3.case判断语句
使用case语句可以对条件进行同时判断,相对于if判断语句效率更高。
格式:
case #变量# in
判断条件1)
(满足条件1需要执行的动作)
;;
判断条件2)
(满足条件2需要执行的动作)
;;
判断条件3)
(满足条件3需要执行的动作)
;;
*) (不满足以上条件的其他条件)
(以上条件均不满足需要执行的动作)
esac
【3】编写脚本实现功能:使用case语句,实现输入命令与文件,调用相应功能对文件进行操作
#!/bin/bash
if [ "$#" -lt "2" ] 判断脚本后的字符串是否够两个(判断用户是否正确输入命令与文件)
then
echo -e "\033[31mError:Please input option [-a|-p|-d] and filename following $0\033[0m"
exit 0
fi
case $1 in 使用case对命令变量进行判断
-d|-D|d|D) 如果是-d|-D|d|D ,则执行删除命令
rm -fr $2
echo -e "\033[32m$2 is deleted!!!\033[0m"
;;
-a|-A|a|A) 如果是-a|-A|a|A ,则执行新建命令
[ -e "$2" ]&&{ 判断文件是否存在,存在则报错并退出,不存在则直接新建
echo -e "\033[31m$2 is exist...\033[0m"
exit 0
}||{
touch $2
echo -e "\033[32m$2 is created!!!\033[0m"
}
;;
-p|-P|p|P) 如果是-p|-P|p|P,则进行备份
[ -e "/mnt/${2}.bak" ]&&{ 判断备份文件是否存在,如果存在则报错并退出,不存在则进行备份
echo -e "\033[31m${2}.bak is exist...\033[0m"
exit 1
}||{
cp $2 ${2}.bak &> /dev/null
echo -e "\033[32m$2 is copy!!!\033[0m"
}
;;
*) 如果都不是则进行提示
echo -e "\033[31mError:Please input option [-a|-p|-d] and filename following $0\033[0m"
esac
4.expect语句
expect | 自动应答命令,用于交互式命令的自动执行 |
---|---|
spawn | expect中的监控程序,其运行后监控命令提出的交互问题 |
send | 发送问题答案交给交互命令 |
\r | 表示回车 |
exp_continue | 表示方问题不存在时继续回答下面的问题 |
expect eof | 表示问题回答完毕退出expect环境 |
interact | 表示问题回答完毕留在交互界面 |
set NAME [ lindex $argv n ] | 定义变量 |
部属expect:
yum install expect -y
systemctl start expect
systemctl enable expect
【4】使用expect语句编写脚本实现功能:输入ip和密码,实现自动ssh连接
#!/user/bin/expect
set IP [ lindex $argv 0 ] 设定变量IP是命令后的第一个字符串
set PWD [ lindex $argv 1 ] 设定变量PWD是命令后的第二个字符串
spawn ssh root@$IP 对"ssh"动作进行监听
expect {
"(yes/no)?" {send "yes\r";exp_continue} 设定当遇到"(yes/no)?"时,填写“yes“并回车
"password:" {send "$PWD\r"} 设定当遇到"password"时,填写“$PWD变量“并回车
}
interact 表示不结束(expect eof 则表示结束)
【5】使用expect语句编写脚本实现功能:自动测试十台主机是否可以ping,可以则显示主机名
#!/bin/bash
Connect() 定义函数
{
/usr/bin/expect <<EOF 输出重定向至expect环境
spawn ssh root@$1 $2 对"ssh"动作进行监听
expect {
"(yes/no)?" { send "yes\r";exp_continue } 设定当遇到"(yes/no)?"时,填写“yes“并回车
"password:" { send "westos\r" } 设定当遇到"password"时,填写“$PWD变量“并回车
}
expect eof 表示问题回答完毕退出expect环境
EOF
}
for IP in {1..10} 设置变量IP的范围为1-10
do
ping -c1 -w1 172.25.254.$IP &> /dev/null 尝试ping
if [ "$?" = "0" ] 如果成功则显示主机名
then
Connect 172.25.254.$IP hostname | tail -n 1 调用函数
fi
done
【6】编辑脚本实现功能:执行命令后建立名单中的用户,并设定密码为指定文件中的密码。当执行脚本时没有输入用户名单以及密码文件时、当用户名单与密码文件的行数不同时、当有文件不存在时、当新建的用户已存在时均报错。
vim users_create.sh
#!/bin/bash
if [ "$#" -lt "2" ] 判断是否输入了用户名单以及密码文件,如果没有输入两个文件则报错并退出
then
echo -e "\033[31mPlease input userlist and passlist following $0 !!!\033[0m"
exit 0
fi
[ "$1" = "0" -o "$2" = "0" ]&&{ 判断输入的两个文件是否存在
echo -e "\033[31mPlease input right file !!! \033[0m"
exit 1
}
NAME=`awk 'BEGIN{N=0}{N++}END{print N}' $1` 统计用户名单的行数
PWD=`awk 'BEGIN{M=0}{M++}END{print M}' $2` 统计密码文件的行数
if [ "$NAME" -ne "$PWD" ] 当两个文件行数不一致时,报错并退出
then
echo -e "\033[31mPlease input right file !!! \033[0m"
exit 2
fi
for NUM in `seq 1 $NAME` 设定NUM变量的取值范围(从1用户名单的总行数)
do
USERNAME=`sed -n ${NUM}p $1` 设定用户名变量
PASSWORD=`sed -n ${NUM}p $2` 设定用户密码变量
useradd $USERNAME &> /dev/null &&{ 添加用户,如果成功则进行改密
echo $PASSWORD | passwd --stdin $USERNAME &> /dev/null 为新加用户设置密码
echo -e "\033[32m$USERNAME is created ! \033[0m"
}||{ 添加失败则提示用户已存在
echo -e "\033[31m$USERNAME is exist !!! \033[0m"
}
done
【7】编辑脚本实现功能:执行脚本并输入密码后会备份数据库中的所有库到/mnt/db/musqldump目录中。并且备份文件名称为“库名称.sql”,当此文件存在时报错并询问动作:输入“S”跳过备份,输入“B”时备份“库名词.sql”文件为“库名称_backup.sql”,输入“O”则覆盖源文件。
vim db_dump.sh
#!/bin/bash
ACTION() 定义函数ACTION
{
case $CHOOSE in 使用case语句定义变量CHOOSE
S|s) 当变量CHOOSE为“S”或“s”时执行退出命令
exit 0
;;
B|b) 当变量CHOOSE为“B”或“b”时自动备份已存在的文件并备份数据库
mv /mnt/db/mysqldump/${DATABASE}.sql /mnt/db/mysqldump/${DATABASE}_backup.sql
mysqldump -uroot -p"$1" $DATABASE > /mnt/db/mysqldump/${DATABASE}.sql
echo -e "\033[32m${DATABASE} is dumped successfully !!!\033[0m"
;;
O|o) 当变量CHOOSE为“O”或“o”时覆盖已存在的文件
mysqldump -uroot -p$1 $DATABASE > /mnt/mysqldump/db/${DATABASE}.sql
echo -e "\033[32m${DATABASE} is dumped successfully !!!\033[0m"
;;
*) 当变量CHOOSE时其他数据时进行报错,并重新执行ACTION函数
echo -e "\033[31mError:Please input right choose !!! \033[0m"
ACTION
esac 结尾
}
if [ ! -e "/var/lib/mysql/mysql.sock" ] 判断数据库是否开启,未开启则报错并退出脚本
then
echo -e "\033[31mMysql is not running !!!\033[0m"
exit 1
fi
if [ -z "$1" ] 判断是否已经输入密码,没有则报错并退出脚本
then
echo -e "\033[31mPlease input password for Mysql following $0 !!\033[0m"
exit 2
fi
mysql -uroot -p$1 -e "SHOW DATABASES;" &> /dev/null 使用输入的密码尝试查看数据库,判断输入的密码是否正确
if [ ! "$?" = "0" ] 判断退出值是否为0(判断输入的密码是否正确),不是0时(不正确)则报错并退出脚本
then
echo -e "\033[31mPassword error !!!\033[0m"
exit 3
fi
for DATABASE in `mysql -uroot -pwestos -e "SHOW DATABASES;" -EN | grep -E '\*|schema$' -v` 采集并定义数据库名变量
do
[ -d "/mnt/db/mysqldump" ] || mkdir -p /mnt/db/mysqldump 判断备份的目录是否存在,不存在则自动新建目录
if [ ! -e "/mnt/db/mysqldump/${DATABASE}.sql" ] 判断备份文件如果不存在就执行备份动作
then
mysqldump -uroot -p$1 $DATABASE > /mnt/db/mysqldump/${DATABASE}.sql
echo -e "\033[32m${DATABASE} is dumped successfully !!!\033[0m"
else 如果备份文件存在则进行提示,剧提示进行相关动作
read -p "The ${DATABASE}.sql is exist,please choose [S]kip or [B]ackup or [O]ver : " CHOOSE
ACTION westos
fi
done
5.shell中常用的运算命令
运算操作与运算命令 | 含义 |
---|---|
(()) | 用于整数运算 |
let | 用于证书运算,与(())类似 |
expr | 用于整数运算,功能相对较多 |
bc | linux下的计算器,适合整数和小数的运算 |
$[] | 用于整数运算 |
【8】编辑脚本实现功能:进行数字运算
运用bc进行计算:
vim bc.sh
#!/bin/bash
read -p "请输入您要操作的数字:" N
read -p "请输入要操作的运算:" T
read -p "请输入要操作的第二个数字:" M
bc<<EOF
${N}${T}${M}
EOF
运用运算符进行计算(无法运算小数):
vim jisuanji.sh
#!/bin/bash
read -p "请输入您要操作的数字:" N 采集变量“N”
read -p "请输入要操作的运算:" T 采集变量“T”
read -p "请输入要操作的第二个数字:" M 采集变量“M”
case $T in 对变量“T“进行判断
+) “T”为“+”时,进行加法运算,赋值给变量“NUM”
let NUM=${N}+${M}
;;
-) “T”为“-”时,进行减法运算,赋值给变量“NUM”
let NUM=${N}-${M}
;;
\*) “T”为“*”时,进行乘法运算,赋值给变量“NUM”
let NUM=${N}*${M}
;;
/) “T”为“/”时,进行除法运算,赋值给变量“NUM”
let NUM=${N}/${M}
;;
%) “T”为“%”时,进行取余运算,赋值给变量“NUM”
let NUM=${N}%${M}
;;
\**) “T”为“**”时,进行幂运算,赋值给变量“NUM”
let NUM=${N}**${M}
esac
echo -e "\033[32m结果为:$NUM\033[0m" 显示变量“NUM”
【9】编辑脚本实现功能:实现1分10秒的倒计时
vim daojishi.sh
#!/bin/bash
for NUM in {70..1} 定义变量NUM取值范围为1-70
do
let MIN=$NUM/60 对分的变量“MIN”进行取值
let SEC=$NUM%60 对秒的变量“SEC”进行取值
echo -ne "\033[32mAftrer ${MIN}m:${SEC}s will end ... \033[0m" 进行显示
echo -ne "\r" 每次变化都进行覆盖
sleep 1 延迟一秒执行
done