安装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