安装expect工具
expect是自动化脚本解释型的工具
yum install expect -y
主要命令
spawn 新建一个进程 这个进程是由expect控制
send 发送字符串给expect控制的进程
set 设置变量 set user root
exp_continue 重新执行expect分支
set timeout -1 设置超时时间 永远等待
set timeout 10 设置超时时间 10秒
interact 将脚本的控制权交给用户,用户继续使用shell执行命令
expect test.ex
#!/usr/bin/expect
set pass 123456
set user root
spawn ssh $user@10.0.1.10
expect {
"yes/no" { send "yes\r";exp_continue }
"password" { send "$pass\r" }
}
interact
批量获取在线的IP地址 主机 进行批量秘钥分发
#!/bin/sh
#1.获取在线的主机 能ping通在线
>ip.txt
for i in 7 8
do
ping -c1 -W1 10.0.0.$i &>/dev/null
if [ $? -eq 0 ];then
echo 10.0.0.$i >>ip.txt
fi
done
#2.判断公钥是否生成
if [ ! -f ~/.ssh/id_rsa ];then
ssh-keygen -P "" -f ~/.ssh/id_rsa
fi
#3.批量分发秘钥
pass=1
while read line
do
/usr/bin/expect<<EOF
set timeout 2
spawn ssh-copy-id root@$line
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send "$pass\r" };
}
expect eof
EOF
done<ip.txt
循环
for循环
语法
for 变量名 in 取值列表 {#取值列表可以是数字 字符串 序列 命令} 以空格分隔
do
命令的集合
done
for 手 in 苹果 梨 香蕉 橘子 变量的值 依次从左到右读取
do
echo 包裹${手}
done
包裹苹果
包裹梨
包裹香蕉
包裹橘子
案例1: 要求判断10.0.0.1-254网段的在线主机 能ping通则认为在线
注意: wait 等待上面的所有命令执行完成后才继续往下执行
#!/bin/sh
for i in {1..254}
do
{
IP=10.0.0.$i
ping -c1 -W1 $IP &>/dev/null
if [ $? -eq 0 ];then
echo "ping $IP is ok"
fi } &
done
wait
echo "在线取IP完成"
案例2: 使用for循环创建user.txt中的用户 附加 每个用户随机8位密码 用户名和密码统一输出到文件
user.txt
zs
ls
oldboy
alex
lz
#!/bin/sh
for i in `cat user.txt`
do
id $i &>/dev/null
if [ $? -eq 0 ];then
echo "useradd:$i already exists"
else
useradd $i &>/dev/null
if [ $? -eq 0 ];then
echo "create $i is ok"
else
echo "error"
fi
pass=`echo $((RANDOM))|md5sum|cut -c1-8`
echo $pass|passwd --stdin $i &>/dev/null
[ $? -eq 0 ] && echo "密码创建成功" || echo "密码创建失败"
echo -e "$i\t$pass" >> pass.txt
fi
done
for 循环笔试题
# 从1+100的和
#!/bin/bash
sum=0
for ((i=1;i<101;i++))
do
((sum+=i))
done
echo $sum
5050
案例:
企业项目实践机会(第6次)来了(本月中旬),但是,名额有限,队员限3人(班长带队)。
因此需要挑选学生,因此需要一个抓阄的程序
#!/bin/sh
>ran.txt
touch ran.txt
while true
do
RAN=`echo $((RANDOM%100+1))`
if [ `grep -w $RAN ran.txt|wc -l` -eq 1 ];then
continue
fi
read -p "请输入你的姓名: " name
if [ $name = "exit" ];then
echo "抓阄完毕统计结果如下"
sort -rnk2 ran.txt
exit
else
if [ `grep -w $name ran.txt|wc -l` -eq 1 ];then
echo "抓过阄了不要闹了"
continue
else
echo -e "$name\t$RAN"|tee -a ran.txt
fi
fi
done
while 循环
while [ 条件测试 ]
do
命令的集合
done
#!/bin/sh
while [ 10 -gt 10 ]
do
sleep 1
echo ok
done
while 批量创建用户
#!/bin/sh
while read user
do
useradd $user &>/dev/null
if [ $? -eq 0 ];then
echo "ok"
else
echo "error"
fi
done<user.txt
<user.txt 从文件中读取用户名 在循环里执行
Shell内置命令
exit 退出整个脚本
break 结束当前循环 或者跳出本层循环
continue 忽略本次循环剩余的代码,直接进入下一次循环
exit
[root@shell ~]# cat exit.sh
#!/bin/sh
while true
do
echo hehe
exit
echo test
done
echo done......
break
[root@shell ~]# cat break.sh
#!/bin/sh
while true
do
echo hehe
break
echo test
done
echo done......
continue
[root@shell ~]# cat break.sh
#!/bin/sh
while true
do
echo hehe
continue
echo test
done
echo done......
函数
函数的作用
1)命令的集合 完成特定功能的代码块
2)函数的优势可以使代码完全的模块化 便于复用 加强可读 易于修改
3)函数和变量类似 先定义才可调用,如果定义不调用则不执行
定义函数
函数的传参
函数内的变量返回值
return
定义函数
#!/bin/sh
fun1(){
echo "第一种定义方式"
}
function fun2 {
echo "第二种定义方式"
}
function fun3() {
echo "第三种定义方式"
}
fun1 # 调用函数非常简单 只需要写函数名即可
fun2
fun3
函数传参
1)函数名称后面跟字符串传参
[root@shell day5]# cat fun.sh
#!/bin/sh
fun(){
if [ -f $2 ];then
echo "$2 exists"
else
return 5
fi
}
fun /etc/hosts /etc/passwd
2)使用脚本的参数传参
[root@shell day5]# cat fun.sh
#!/bin/sh
fun(){
if [ -f $1 ];then
echo "$1 exists"
else
return 5
fi
}
fun $2 $1
[root@shell day5]# sh fun.sh /etc/hosts /etc/passwd
/etc/passwd exists
思考:
#!/bin/sh
fun(){
num=10
for i in `seq 10`
do
total=$[$i+$num]
done
echo "total的结果是: $total"
}
fun
传参
#!/bin/sh
#第一种定义方式
fun(){
num=$1
for i in `seq 10`
do
total=$[$i+$num]
done
echo "total的结果是: $total"
}
fun $2 $1
[root@shell day5]# sh fun.sh 20 30
total的结果是: 40
函数的变量
local num=20 只针对当前的函数生效 其他函数和语句无法接收local的变量
函数的返回值
#!/bin/sh
fun(){
echo 100
return 1
}
result=`fun`
echo "函数的状态码是: $?"
echo "函数的执行结果是: $result"
注意: $?上一条执行的如果有函数名称 则返回函数内的return值 如果不相关则上一条命令的返回值
#!/bin/sh
fun(){
if [ -f $1 ];then
return 50
else
return 100
fi
}
fun $1
#根据函数的返回状态码进行输出结果
re=$?
#[ $re -eq 50 ] && echo "文件存在"
#[ $re -eq 100 ] && echo "文件不存在"
if [ $re -eq 50 ];then
echo "文件存在"
elif [ $re -eq 100 ];then
echo "文件不存在"
fi
案例: 文件统计行
line 内置变量 按行读取
[root@shell day5]# wc -l /etc/passwd
37 /etc/passwd
[root@shell day5]# cat /etc/passwd|wc -l
37
[root@shell day5]# cat while1.sh
#!/bin/h
while read line
do
let i++
done</etc/passwd
echo $i
awk '{print NR}' /etc/passwd
sed '=' /etc/passwd|xargs -n2
grep -n . /etc/passwd
less -N /etc/passwd
cat -n /etc/passwd
数组
数组的分类
普通数组: 只能使用整数作为数组索引
关联数组: 可以使用字符作为数组索引
元素=索引=下标
普通数组定义
[root@shell ~]# array[0]=shell
[root@shell ~]# array[10]=MySQL
[root@shell ~]# echo ${array[0]}
shell
[root@shell ~]#
[root@shell ~]# echo ${array[10]}
MySQL
-----------------
[root@shell ~]# array=(shell MySQL Redis)
[root@shell ~]# echo ${array[0]}
shell
[root@shell ~]# echo ${array[1]}
MySQL
[root@shell ~]# echo ${array[2]}
Redis
----------------
[root@shell ~]# array=(Shell [5]=Docker Redis [10]=MySQL)
[root@shell ~]# echo ${array[0]}
Shell
[root@shell ~]# echo ${array[5]}
Docker
[root@shell ~]# echo ${array[6]}
Redis
[root@shell ~]# echo ${array[10]}
MySQL
---------------命令定义数组
[root@shell ~]# array=(`ls`)
[root@shell ~]# echo ${array[0]}
1.sh
[root@shell ~]# echo ${array[1]}
1.txt
[root@shell ~]# echo ${array[2]}
2.sh
[root@shell ~]# echo ${array[3]}
all.sh
常用的定义方式
array=(10.0.0.8 10.0.0.9 10.0.0.32)
取消定义数组
unset array
如何查看数组
[root@shell ~]# echo ${array[0]} # 使用索引查看
[root@shell ~]# echo ${array[*]} # 查看数组中所有的值
shell MySQL Redis
[root@shell ~]# echo ${array[@]} # 查看数组中所有的值
shell MySQL Redis
[root@shell ~]# echo ${!array[*]} # 查看索引
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
案例:
#!/bin/sh
#定义数组
ip=(
10.0.0.1
10.0.0.2
10.0.0.7
10.0.0.8
10.0.0.9
)
#调用数组
for i in ${ip[*]}
do
ping -c1 -W1 $i &>/dev/null
[ $? -eq 0 ] && echo "ping $i 没问题....." || echo "ping $i 不通....."
done
遍历索引
#!/bin/sh
#定义数组
ip=(
10.0.0.1 0
10.0.0.2 1
10.0.0.7 2
10.0.0.8 3
10.0.0.9 4
)
#调用数组
for i in ${!ip[*]}
do
ping -c1 -W1 ${ip[$i]} &>/dev/null
[ $? -eq 0 ] && echo "ping ${ip[$i]} 没问题....." || echo "ping ${ip[$i]} 不通....."
done
关联数组 索引可以是字符串
[root@shell day5]# declare -A array
[root@shell day5]# array[index1]=shell
[root@shell day5]# array[index2]=mysql
[root@shell day5]# array[index3]=redis
[root@shell day5]#
[root@shell day5]# echo ${array[index1]}
shell
[root@shell day5]# echo ${array[index2]}
mysql
[root@shell day5]# echo ${array[index3]}
redis
[root@shell day5]# echo ${array[*]}
shell mysql redis
[root@shell day5]# echo ${array[@]}
shell mysql redis
[root@shell day5]# echo ${!array[@]}
index1 index2 index3
[root@shell day5]# array=([index1]=shell [test]=Redis [index2]=Redis)
[root@shell day5]# echo ${array[*]}
shell Redis Redis
查看所有的当前shell定义的数组
declare -A
案例:
cat sex.txt
zs m
ls m
zp f
lw f
qq m
ww x
#!/bin/sh
#定义数组
declare -A array
while read sex
do
let array[$sex]++
done<sex.txt
for i in ${!array[*]}
do
echo "性别$i 出现了 ${array[$i]} 次"
done
----------------
[root@shell day5]# sh array.sh
性别f 出现了 2 次
性别m 出现了 3 次
性别x 出现了 1 次
统计/etc/passwd 解释器出现的次数
#!/bin/sh
declare -A bash
while read line
do
let bash[`echo $line|awk -F: '{print $NF}'`]++
done</etc/passwd
for i in ${!bash[*]}
do
echo "$i 出现了 ${bash[$i]}次"
done
统计nginx日志ip出现的次数
#!/bin/sh
declare -A IP
while read line
do
let IP[`echo $line|awk '{print $1}'`]++
done</var/log/nginx/access.log
for i in ${!IP[*]}
do
echo "$i 出现了 ${IP[$i]}次"
done
案例: 反向破解随机数
思路:
1.知道RANDOM总共的随机数 32767
使用脚本 统计出RANDOM 总共多少个随机数
2.循环取MD5进行cut
3.和已知的MD5值进行比对 如果相等 则输出数字
# ? ? ? 动手试试
#!/bin/bash
. /etc/init.d/functions
declare -a array
for i in $(seq 0 32767)
do
array[$i]=`echo $RANDOM|md5sum | cut -c 1-8`
done
keys=([0]=21029299 [1]=00205d1c [2]=a3da1677 [3]=1f6d12dd [4]=890684b)
action "mate" /bin/true
for key in ${keys[@]}
do
for i in `seq 0 32767`
do
if [[ "${array[i]}" = "$key" ]]; then
echo "破解成功" "密码:"$i------$key
action " " /bin/true
fi
done
done
#!/bin/bash. /etc/init.d/functionsdeclare -a arrayfor i in $(seq 0 32767)do array[$i]=`echo $RANDOM|md5sum | cut -c 1-8`donekeys=([0]=21029299 [1]=00205d1c [2]=a3da1677 [3]=1f6d12dd [4]=890684b)action "mate" /bin/truefor key in ${keys[@]} do for i in `seq 0 32767` do if [[ "${array[i]}" = "$key" ]]; then echo "破解成功" "密码:"$i------$key
action " " /bin/true fi donedone