一.shell循环:for

1. 语法结构

语法

for    变量名      [ in 取值列表 ]
do
循环体
done

示例
自动创建3个用户

[root@localhost ~]# cat useradd-for.sh 
#!/bin/bash
for i in {1..3} 
do
useradd u$i
echo "u$i created !"
done

或者
for i in $(seq 1 3)
for i in `seq 3`

对比c语言

C语言:
for         ((初值;条件;步长))
do 
循环体
done

2.案例1:ping测试主机

通过循环工具,探测网段主机,将在线主机记录在文本中。

[root@localhost ~]# cat ping-for.sh 
>up.txt
>down.txt
#每次执行前会清空up,down文件
#!/bin/bash
for i in `seq 255`
do
ip=10.8.162.$i
ping -c1 -W1 $ip &> /dev/null
if [ $? -eq 0 ] 
	then echo "$ip" &>> up.txt
	else echo "$ip" &>> down.txt
fi
done

3.案例2:通过用户列表文件创建用户

通过用户列表文件创建用户

[root@localhost ~]# vim user.txt
u1
u2
u3
[root@localhost ~]# vim useradd-for.sh
#!/bin/bash
for user in `cat user.txt`
do
useradd $user
echo "$user is created"
done

用户可以使用参数的形式,自定义用户名文件。
如果用户没有输入用户名文件,提示用户输入。
如果用户输入的不是文件,提示用户更正。
启动循环创建用户
如果用户已经存在,提示存在。
如果用户不存在,则创建成功,提示成功。

[root@localhost ~]# vim useradd-for.sh

#!/bin/bash
pass=123

#判断脚本是否有参数

if [ $# -eq 0 ] 
		then
        echo "usage:$0 filename "
        exit 1
fi

#判断用户输入的是否是文件

if [ ! -f $1 ]
		then
        echo "error filename"
        exit 2
fi

#设置循环,读取文件,创建用户

for user in `cat $1`
do
        id $user &> /dev/null
        
#如果用户不存在,则创建用户,否则提示已经存在。

if [ $? -eq 0 ]
		then
        echo "user $user already exists"
		else
        useradd $user
        echo "$pass" | passwd --stdin $user &> /dev/null
        
#判断用户是否创建成功,并提示

        if [ $? -eq 0 ]
        then
        echo "$user is created."
		fi
fi
done

4.案例3:使用for实现批量主机root密码的修改

前提1:已经完成秘钥登录配置(ssh-keygen)
前提2:定义主机地址列表
前提3:并了解远程修改密码的方法

[root@localhost ~]# vim ip.txt
10.8.162.66
10.8.162.88
[root@localhost ~]# vim passwdfix.sh 
#!/bin/bash
>passwd-yes.txt
>passwd-no.txt
while :
do
read -s -p "input a new password:" passwd1 
echo ""
read -s -p "reconfirm new password:" passwd2
if [ ! $passwd1 == $passwd2 ] 
	then echo "this is different"
	else 
		break
fi
done
echo "success"
for ip in `cat ip.txt`
do
{
ping -c1 -w1 $ip &> /dev/null
if [ $? -eq 0 ] 
	then ssh $ip "echo $passwd2 | passwd --stdin root"
	if [ $? -eq 0 ] 
		then echo "$ip" >> passwd-yes.txt
		else echo "$ip" >> passwd-no.txt
	fi
	else echo "$ip" >> passwd-no.txt
fi
} &
done
wait
echo "finished"

二.shell循环:while 、until

循环次数不一定是固定的
while语法结构

1.while语句结构(死循环/逐行处理文件)
while 条件测试
do
循环体
done
==当条件测试成立(条件测试为真),执行循环体

2.示例:每秒显示1个数字,每次递增+1


[root@localhost ~]# vim while.sh
while :
do
let i++
sleep 1
echo $i
done

until语法结构

1.until语法结构
until 条件测试
do
循环体
done
==当条件测试成立(条件测试为假时成立),执行循环体

2.示例1:每秒循环一个数字
[root@localhost ~]# vim until.sh
until [[ $i -eq 5  ]]
do
let i++
sleep 1
echo $i
done


3.示例2:每隔5秒查看js用户是否登录,循环往复。
		如果该用户登录,请显示登录并退出监控程序;
		否则显示当前时间,并输出js尚未登录
[root@localhost ~]# vim until-user.sh 
#!/bin/bash
until who | grep js &> /dev/null
do
echo "$(date) js not login" >> login-user.txt
sleep 1
done
echo "$(date) js login" >> login-user.txt
exit 1

三.循环总结

固定:for
逐行:while
逐行/不固定:while ,until

四.expect

1.前言

有些程序难以避免的需要交互,expect用于解决骄傲胡问题

2.名词解释

解决人机交互的问题

一、概述
  我们通过Shell可以实现简单的控制流功能,如:循环、判断等。但是对于需要交互的场合则必须通过人工来干预,有时候我们可能会需要实现和交互程序如telnet服务器等进行交互的功能。而Expect就使用来实现这种功能的工具。
  Expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预。Expect的作者Don Libes在1990年开始编写Expect时对Expect做有如下定义:Expect是一个用来实现自动交互功能的软件套件 (Expect [is a] software suite for automating
  interactive tools)。使用它系统管理员 的可以创建脚本用来实现对命令或程序提供输入,而这些命令和程序是期望从终端(terminal)得到输入,一般来说这些输入都需要手工输入进行的。 Expect则可以根据程序的提示模拟标准输入提供给程序需要的输入来实现交互程序执行。甚至可以实现实现简单的BBS聊天机器人。:)
  Expect是不断发展的,随着时间的流逝,其功能越来越强大,已经成为系统管理员的的一个强大助手。Expect需要Tcl编程语言的支持,要在系统上运行Expect必须首先安装Tcl。
二、Expect工作原理
  从最简单的层次来说,Expect的工作方式象一个通用化脚本工具。用来实现计算机之间需要建立连接时进行特定的登录会话的自动化。
 脚本由一系列expect-send对组成:expect等待输出中输出特定的字符,通常是一个提示符,然后发送特定的响应。

8

3.安装

[root@localhost ~]# yum install -y expect tcl tclx tcl-devel

4.示例1

通过expect解决ssh交互问题

1.通过expect编写脚本

[root@localhost ~]# vim expect.sh
#!/usr/bin/expect
spawn ssh root@192.168.0.111
expect {
        "yes/no" { send "yes\r";exp_continue }
        "password:" { send "666666\r" }
}
interact

2.登录验证免交互

spawn  expect 内部命令,启动一个shell程序。
expect 期望哪些内容
yes/no  就send发送 yes ,\r  表示回车 
password 就send发送 centos
exp_continue 跳过循环,就继续下一条语句。
interact 允许用户交互

4.示例2

expect实战:公钥推送

1.准备工作:安装expect,准备公钥
2.通过shell循环判断在线主机
3.通过expect进行交互
4.优化脚本

[root@localhost ~]# vim expect.sh 
#!/bin/bash
#创建一个IP地址文件

>ip.txt

#检测expect是否安装,检测公钥是否创建

rpm -q expect &> /dev/null
if [ $? -ne 0  ] 
        then yum install -y expect tcl tclx tcl-devel
fi
if [ ! -f ~/.ssh/id_rsa  ] 
        then ssh-keygen -P "" -f ~/.ssh/id_rsa
fi

#使用for循环ping测试主机是否在线

for i in {255} 
do
{
ip=192.168.36.$i
ping -c1 -w1 $ip &> /dev/null
if [ $? -eq 0  ] 
        then "$ip" >> ip.txt



#调用expect

/usr/bin/expect <<-EOF
set timeout 10
spawn ssh-copy-id $ip
expect{
"yes/no" { send "yes\r";exp_comtinue  } 
"password:" { send "666666\r"  }
} 
expect eof
EOF
fi
}&
done