第三章 循环及交互

1. for循环
1.1 语法结构
bash
for 变量名 [ in 取值列表 ]
do
循环体
done
1.2 示例-自动循环创建/删除10个用户
bash
[root@shell-test ~]# vim for_user.sh
#!/bin/bash
read -p "新建/删除10个用户(create/delete)选择方式:" select
if [ "$select" = "create" ]
then
for x in {1..10}
do
useradd user$x
done
wait
echo "10个用户已创建完毕...."
tail -n 10 /etc/passwd
else
for x in {1..10}
do
userdel -r user$x
done
wait
echo "10个用户已删除完毕...."
tail -n 10 /etc/passwd
fi
1.3 示例-在线主机Ping测试
1.3.1 常规ping测试脚本
bash
[root@shell-test ~]# vim ping-1.sh
#!/bin/bash
read -p "请输入你要测试的主机IP: " ip
ping -c1 -W1 $ip &> /dev/null
if [ $? -eq 0 ]
then
echo "$ip" | tee -a ip-yes.txt
echo "$ip在线,IP地址已存至 ip-yes.txt"
else
echo "$ip不在线,已退出。"
fi
1.3.2 循环+并发
bash
[root@shell-test ~]# vim ping-2.sh
#!/bin/bash
>ip.txt #清空记录文本
for i in {2..254}
do
{
ip=172.25.254.$i
ping -c1 -W1 $ip &> /dev/null
if [ $? -eq 0 ] ;then
echo "$ip" |tee -a ip.txt
fi
}& # 后台执行
done
wait # 等待前一个程序执行完毕。在执行下一个命令。
echo "finishi...."
1.4 示例-通过用户列表文件创建用户
bash
[root@shell-test ~]# cat > user.txt <<EOF
> dhj
> jky
> yyc
> lx
> EOF
[root@shell-test ~]# vim new_user.sh
#!/bin/bash
for i in `cat user.txt`
do
useradd $i
echo "$i已经被创建。"
done
[root@shell-test ~]# chmod +x new_user.sh
[root@shell-test ~]# ./new_user.sh
dhj已经被创建。
jky已经被创建。
yyc已经被创建。
lx已经被创建。
说明:升级
用户可以使用参数的形式,自定义用户名文件。
如果用户没有输入用户名文件,提示用户输入
如果用户输入的不是文件,提示用户更正。
启动循环创建用户
如果用户已经存在,提示存在
如果用户不存在,则创建成功,提示成功
bash
#!/bin/bash
pass=123456
if [ $# -eq 0 ]
then
echo "filename不能为空,例下:"
echo "$0 filename"
echo "程序已退出...请重试..."
exit
fi
if [ ! -f "$1" ]
then
echo "请换成文件格式,谢谢"
exit
fi
for i in `cat $1`
do
id $i &> /dev/null
if [ $? -eq 0 ]
then
echo "$i已经被创建,无需进行创建"
else
useradd $i
echo "$pass" | passwd --stdin $i &> /dev/null
echo "$i已经被创建,密码为$pass"
fi
done
1.5 示例-使用for循环实现批量主机root密码的修改
bash
[root@shell-test ~]# ssh-keygen
[root@shell-test ~]# ssh-copy-id 172.25.254.61
[root@shell-test ~]# ssh-copy-id 172.25.254.62
[root@shell-test ~]# ssh-copy-id 172.25.254.63
bash
#!/bin/bash
read -p "请您输入指定的远程主机地址聚合批量文件名(ps: ip.txt): " file
read -p "请您输入新的密码: " pass
for i in $(cat $file)
do
{
ping -c1 -W1 $i &> /dev/null
echo
if [ $? -eq 0 ]
then
ssh root@$i "echo $pass | passwd --stdin root" &> /dev/null
if [ $? -eq 0 ]
then
echo "$i" >> ok.txt
echo "$i已完成修改,IP地址已存入 ok.txt"
else
echo "$i" >> error.txt
echo "$i出现错误,IP地址已存入 error.txt"
fi
else
echo "$i" >> loss.txt
echo "$i处于离线状态,请检查,IP地址已存入 loss.txt"
fi
}&
done
2.while/until循环
循环次数不一定是固定的。
2.1 while语法结构及示例
bash
while 条件测试
do
循环体
done
==当条件测试成立(条件测试为真),执行循环体
bash
#!/bin/bash
while :
do
let i++
sleep 1
echo $i
done
2.2 until语法结构及示例
bash
until 条件测试
do
循环体
done
==当条件测试成立(条件测试为假视为成立),执行循环体
bash
#!/bin/bash
i=0
until [ $i -eq 9 ]
do
let i++
sleep 1
echo $i
done
3.expect交互
说明:有些程序难以避免的需要交互。你该如何解决脚本与程序的交互问题?
bash
[root@shell-test ~]# yum install -y expect tcl tcl-devel
3.1 示例1-通过expect解决ssh交互问题
bash
#!/usr/bin/expect
spawn ssh root@172.25.254.63
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "root\r"}
}
interact
3.2 示例2-公钥推送
bash
#!/bin/bash
> ip.txt
rpm -q expect &> /dev/null
if [ $? -ne 0 ]
then
yum install -y expect &> /dev/null
fi
if [ ! -f ~/.ssh/id_rsa ]
then
ssh-keygen -P "" -f ~/.ssh/id_rsa &> /dev/null
fi
echo
echo "前置环境执行完毕...开始记录"
for i in {3..254}
do
{
ip=172.25.254.$i
ping -c1 -W1 $ip &> /dev/null
if [ $? -eq 0 ]
then
echo "$ip" >> ip.txt
/usr/bin/expect << EOF &> /dev/null
set timeout 10
spawn ssh-copy-id root@$ip
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "root\r" }
eof
}
expect eof
EOF
fi
}&
done
wait
echo "Finish....."