if语句
if 效率低,从上往下执行
语句格式:
if
then
elif
then
。。。
else
fi ##语句结束
简单的示例:
【1】只有if,then,fi
vim /mnt/test.sh
if [ -z "$1" ]
then
echo -e "\033[31mPlease input filename following $0!!!\033[0m"
exit 1
fi
sh /mnt/test.sh
sh /mnt/test.sh file
【2】只有if,then,elis,fi
vim /mnt/test.sh
#!/bin/bash
if [ -z "$1" ]
then
echo -e "\033[31mPlease input filename following $0!!!\033[0m"
exit 1
elif [ -e "$1" ]
then
echo "$1 is exist"
exit 0
fi
sh /mnt/test.sh
sh /mnt/test.sh
sh /mnt/test.sh westos
vim /mnt/test.sh
【3】加入else
vim /mnt/test.sh
#!/bin/bash
if [ -z "$1" ]
then
echo -e "\033[31mPlease input filename following $0!!!\033[0m"
exit 1
elif [ -e "$1" ]
then
echo "$1 is exist"
exit 0
else ##除了以上情况外,输入以下内容
echo "$1 is directory"
fi
sh /mnt/test.sh
sh /mnt/test.sh westos
sh /mnt/test.sh hello
练习1:
判断
先判断$1是否存在;
存在的时候,再判断类型
目录,文件,链接
每次判定完以后,输入exit(无论大小写),退出
[root@localhost mnt]# checkfiletype.sh \
> Please input filename: /mnt \
> /mnt is directory \
> /mnt is not exist \
> Please input filename: exit \
> bye
步骤:
vim /mnt/checkfiletype.sh
#!/bin/bash
while true
do
read -p "Please input filename [or exit or quit]: " NAME
if [ "$NAME" = "EXIT " -o "$NAME" = "exit" ]
then
echo bye~~~
exit 0
elif [ -L "$NAME" ]
then
echo "$NAME is softlink file"
elif [ -d "$NAME" ]
then
echo "$NAME is directory!"
elif [ -f "$NAME" ]
then
echo "$NAME is common file"
else
echo "$NAME is not exist!!!"
fi
done
sh /mnt/checkfiletype.sh
练习2:
当执行filectrl -a file
-d 删掉
-p 备份到/mnt目录下
什么都不是,则报错
vim /mnt/filectrl.sh
内容:
#!/bin/bash
Check_File() 【1】
{
if [ -e "$1" ]
then
$2 ##相当于【2】"echo $2 is exist !"
$3 ##相当于【2】exit
fi
}
if [ "$#" -lt "2" ]
then
echo -e "\033[31mError:Please input option [-a|-d|-p] and following filename $0:\033[0m"
exit 1
elif [ "$1" = "-a" ]
then
Check_File $2 "echo $2 is exist !" exit 【2】
touch $2
elif [ "$1" = "-d" ]
then
Check_File $2 "rm -fr $2" exit
echo "$2 is not exist"
elif [ "$1" = "-p" ]
then
Check_File $2 "cp -rp $2 /mnt" exit
echo "$2 is not exist!!!"
else
echo "Please input option [-a|-d|-p] following $0!!"
fi
测试:
sh /mnt/filectrl.sh -a file
sh /mnt/filectrl.sh -d file
sh /mnt/filectrl.sh -p /etc/passwd
ls /mnt
case
Case 和 if
Case是点名机制,只判断一次速度快,做整体对比,进行匹配
if每次都会判断
case
esca
易懂的示例:
cd /mnt
vim case.sh
#!/bin/bash
case $1 in
westos)
echo linux
;;
linux)
echo redhat
;;
redhat)
echo westos
;;
*) ###输入其他,显示错误
echo Error
esac
sh case.sh westos
sh case.sh linux
sh case.sh redhat
sh case.sh haha
##练习3:在练习2 的基础上修改
vim filectrl.sh
#!/bin/bash
Check_File() ##添加一个函数
{
if [ -e "$1" ]
then
$2
$3
fi
}
if [ "$#" -lt "2" ]
then
echo "Error:Please input option [-a|-d|-p] and following filename $0"
exit 1
fi
case $1 in
-a|a|-A|A)
Check_File $2 "echo $2 is exist !" exit
touch $2
;;
-d|d|-D|D)
Check_File $2 "rm -fr $2" exit
echo "$2 is not exist"
;;
-p|p|-P|P)
Check_File $2 "cp -rp $2 /mnt" exit
echo "$2 is not exist"
;;
*)
echo "Please input option [-a|-d|-p] following $0!!"
esac
测试:
sh /mnt/filectrl.sh -a file
sh /mnt/filectrl.sh -d file
sh /mnt/filectrl.sh -p /etc/passwd
ls /mnt
expect
expect :是自动应答命令用于交互式命令的自动执行
spawn :是expect中的监控程序,其运行后监控命令提出的交互问题
send :发送问题答案给交互命令
"\r":表示回车
exp_continue ##表示当问题不存在时继续回答下面问题
expext eof :表示问题回答完毕退出expect环境
interact: 表示问题回答完毕留在交互界面,适用于远程登陆
set NAME [ lindex $argv n ] ##定义变量 ,从0开始计数(对于不固定答案)
即执行 expect /mnt/answer.exp 后跟的第n个参数
例如: 看【2】 expect /mnt/answer.exp hedan
expect file.exp ##运行
只有#!/usr/bin/expect
才能识别spawn
远程登陆的时候用到interact
set timeout 5 : 等待5妙,没反应直接跳过
先做几个简单例子来理解:
问问题的脚本:
cd /mnt
vim ask.sh
#!/bin/bash
read -p "What is you name: " NAME
read -p "HOW old are you: " AGE
read -p "Which object you study: " CLASS
echo $NAME is $AGE old study $CLASS
sh ask.sh ##运行脚本输入答案
yum install expect -y ##安装自动应答交互式服务
vim /mnt/answer.exp
内容:
#!/usr/bin/expect ##此路径才能时别spawn
spawn /mnt/ask.sh ##监控此脚本
expect "name" ##挑明显的问题 name
send "hedan\r" ##发送的应答
expect "old"
send "20\r"
expect "object"
send "Linux\r"
expect eof ##结束此环境
chmod +x ask.sh
expect answer.exp ##运行
vim /mnt/answer.exp
【1】脚本中:监控问题脚本,发送应答
vim /mnt/answer.exp
#!/usr/bin/expect
spawn /mnt/ask.sh
expect {
"name" { send "hedan\r";exp_continue }
"old" { send "20\r";exp_continue }
"object" { send "linux\r" } ##此问题是最后一个问题,所以不需要exp_continue
}
expect eof
chomd +x /mnt/answer.exp
/mnt/answer.exp ##运行脚本,显示问题与相应的答案
vim /mnt/answer.exp
【2】定义变量;对于不固定的应答
vim /mnt/answer.exp
#!/usr/bin/expect
set NAME [ lindex $argv 0 ] (1) ###定义变量
spawn /mnt/ask.sh
expect {
"name" { send "$NAME\r";exp_continue } (2)
"old" { send "20\r";exp_continue }
"object" { send "linux\r" }
}
expect eof
/mnt/answer.exp yibo (3) ##则问题NAME应答为 yibo
详解: (1)中的 0 是(3)命令后的第一个参数yibo,(2)中的$NAME就是 (1)中的NAME,发送$NAME,即收到应答为yibo
vim /mnt/answer.exp
【2】的延伸
vim /mnt/answer.exp
内容:
#!/usr/bin/expect
set NAME [ lindex $argv 0 ] ##命令后的第一个变量参数
set OLD [ lindex $argv 1 ] ##同上,第二个变量
set OBJECT [ lindex $argv 2 ]
spawn /mnt/ask.sh
expect {
"name" { send "$NAME\r";exp_continue }
"old" { send "$OLD\r";exp_continue }
"object" { send "$OBJECT\r" }
}
expect eof
/mnt/answer.exp yibo 20 dance ##显示yibo is 20 old study dance
vim /mnt/answer.exp
以下可以很好的区别 interact 和 expect eof
【3】 :练习
要求:
执行 ( /mnt/answer.exp 172.25.254.ip 密码pass )后自动连接此主机
(1)停留在交互式界面: interact
vim /mnt/auto_ssh.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
chmod +x /mnt/auto_ssh.exp
auto_ssh.exp 172.25.254.12 westos
vim /mnt/auto_ssh.exp
(2)退出expect环境:expect eof
vim /mnt/auto_ssh.exp
内容:
#!/usr/bin/expect
set timeout 5
set IP [ lindex $argv 0 ]
set PASS [ lindex $argv 1 ]
spawn ssh root@$IP
expect {
"yes/on" { send "yes\r";exp_continue }
"password" { send "$PASS\r" }
}
expect eof
auto_ssh.exp 172.25.254.12 westos ##连接到12以后,我自己的网络问题,等待几秒又退回到112主机 ,一般情况下,直接退出到当前环境
vim /mnt/auto_ssh.exp
【4】添加连接的主机名称hostname
vim /mnt/auto_ssh.exp
#!/usr/bin/expect
set timeout 5
set IP [ lindex $argv 0 ]
set PASS [ lindex $argv 1 ]
spawn ssh root@$IP hostname
expect {
"yes/no" { send "yes\r";exp_continue }
"password:" { send "$PASS\r" }
}
interact
chmod +x /mnt/auto_ssh.exp
/mnt/auto_ssh.exp 172.25.254.62 westos
/mnt/auto_ssh.exp 172.25.254.62 westos | tail -n 1 ##截取连接的主机的主机名称
vim /mnt/auto_ssh.exp
整合shell,expect环境
在shell环境中不能用expect的脚本格式,
以下将两个环境组合在一起,整合在shell里面,这样在shell环境中就能用expect的格式
expect 路径:/usr/bin/expect
练习:
【1】找出连接的主机的名称,并退出环境 (先用指定的ip 172.25.254.62为示例)
vim auto_ssh.exp
#!/bin/bash
Auto_Connect()
{
/usr/bin/expect <<EOF ##在此处需要顶格写
spawn ssh root@$1 $2
expect {
"yes/no" { send "yes\r";exp_continue }
"password:" { send "westos\r" }
}
expect eof
EOF
}
Auto_Connect 172.25.254.62 hostname | tail -n 1
/mnt/auto_ssh.sh
vim auto_ssh.exp
【2】在【1】的基础上将ip改为变量
vim auto_ssh.sh
内容:
#!/bin/bash
Auto_Connect()
{
/usr/bin/expect <<EOF ##expect的路径
spawn ssh root@$1 $2
expect {
"yes/no" { send "yes\r";exp_continue }
"password:" { send "westos\r" }
}
expect eof
EOF
}
Auto_Connect $1 hostname | tail -n 1
/mnt/auto_ssh.sh 172.25.254.62 ##$1即为此处的ip
vim auto_ssh.sh
练习【1】:
执行/mnt/auto_ssh.sh
将开着的主机名导入host_list
^M(ctrl + v ; ctrl + m )
思路: (1)检验哪些主机是开着的,即是否可以ping通
(2)然后 ssh 连接可以ping通的主机
(3)将ssh上的主机名截取
步骤:
vim /mnt/auto_ssh.sh
内容:
#!/bin/bash
Auto_Connect()
{
/usr/bin/expect <<EOF
spawn ssh root@$1 $2
expect {
"yes/no" { send "yes\r";exp_continue }
"password" { send "westos\r" }
}
expect eof
EOF
}
for NUM in {2..8} ##最好确保在这个范围内的主机密码都是westos
do
ping -c1 -w1 172.25.254.$NUM &> /dev/null ##检验哪些主机可以ping通
if [ "$?" = "0" ]
then
Auto_Connect 172.25.254.$NUM hostname | tail -n 1 >> /mnt/host_list
fi
done
chmod +x /mnt/auto_ssh.sh
/mnt/auto_ssh.sh
vim /mnt/auto_ssh.sh
练习【2】在远程登录的主机上建立用户密码:
/mnt/create_user.sh
userlist
passlist
思路:
1:先检验网络是否通畅,即是否可以ping通
2: 在ping通的主机上做,自动登陆,远程主机,
3:然后在远程的主机中建立用户密码
用户列表:
cat userlist
use1
use2
use3
cat passlist
use123
uer456
use789
脚本:
vim create1_user.sh
#!/bin/bash
Auto_Connect() ##写入一个函数,远程连接主机
{
/usr/bin/expect <<EOF
spawn ssh root@$1 $2
expect {
"yes/no" { send "yes\r";exp_continue }
"password" { send "westos\r" }
}
expect eof
EOF
}
Max_Line=`awk 'BEGIN{N=0}{N++}END{ print N}' $1` ##文件的行数
for NUM in {2..8} ##172.25.254.2--172.25.254.8
do
ping -c1 -w1 172.25.254.$NUM &> /dev/null ##检验哪些主机可以ping通
if [ "$?" = "0" ]
then
for User_NUM in `seq 1 $Max_Line` ##以下是将两个文件的内容相匹配为用户和密码
do
USERLIST=`sed -n ${User_NUM}p $1`
PASSLIST=`sed -n ${User_NUM}p $2`
Auto_Connect 172.25.254.$NUM "id $USERLIST &> /dev/null || useradd $USERLIST && echo $PASSLIST | passwd --stdin $USERLIST" &> /dev/null
done
fi
done
/mnt/create1_user.sh userlist passlist
解析:
id $USERLIST ##检测$USERLIST用户是否存在
(1) 若存在则不执行 || 后面的命令
(2) 若用户不存在,则执行 || 后面的建立用户和设置密码
测试:
ssh root@172.25.254.3
su - use1
su - use2
su - use3