9.Shell之随机数,嵌套循环,阶段总结,expect

小破站学习笔记
一切都是未知数
系统变量:RANDOM,默认产生0-32767的随机整数

打印一个随机数
echo $RANDOM
产生0-1之间的随机数
echo $[RANDOM%2]
产生0-2之间的随机数
echo $[RANDOM%3]
产生0-10之间的随机数
echo $[RANDOM%11]
产生1-50之间的随机数
0-49
echo $[RANDOM%50+1]
产生50-100之间的随机数
0-50
echo $[RANDOM%51+50]
产生10-99之间的随机数
0-89
echo $[RANDOM%90+10]
产生100-999之间的随机数
0-899
echo $[RANDOM%900+100]

实战案例

  • 随机产生以139开头的号码1000个

思路:循环1000次 139后面的每个数都是随机的

#!/bin/bash
file=/zss.txt
for i in {1..1000}
	do
		n1=$[RANDOM%10]
		n2=$[RANDOM%10]
		n3=$[RANDOM%10]
		n4=$[RANDOM%10]
		n5=$[RANDOM%10]
		n6=$[RANDOM%10]
		n7=$[RANDOM%10]
		n8=$[RANDOM%10]
		echo "139$n1$n2$n3$n4$n5$n6$n7$n8" >> $file
		let i++
	done

##cat zss.txt | sort -u | wc -l
  • 随机抽取5位幸运观众

从1000个手机号抽取5个 号码只显示前3位和后4位
思路:确定幸运观众所在的行 随机数 将号码提取出 head -899 zss.txt | tail -1 显示前3个和后4个 echo 139****1234

#!/bin/bash
phone=/zss.txt
for ((i=1;i<=5;i++))
	do
		#确定幸运观众所在的行
		line=`wc -l $phone | cut -d ' ' -f1`
		luck_line=$[RANDOM%$line+1]
		#抽出幸运观众的手机号
		luck_num=`head -$luck_line zss.txt | tail -1`
		#显示到屏幕
		echo "139****${luck_num:7:4}"
		echo $luck_num >> luck.txt
		#删除已经被抽取的幸运观众号码
		sed -i "/$luck_num/d" $phone
	done 
  • 批量创建用户 密码随机生成

思路:循环5次创建 产生一个文件用来 保存随机密码 赋值

#!/bin/bash
echo user0{1..5}:zss$[RANDOM%9000+1000]#@~|tr ' ' '\n' >> user_pass.file
for ((i=1;i<=5;i++))
	do
		user=`head -$i user_pass.file | tail -1 | cut -d: -f1`
		pass=`head -$i user_pass.file | tail -1 | cut -d: -f2`
		useradd $user
		echo $pass|passwd --stdin $user
	done

总结

for

for i in {1..5};do echo $i;done
for ((i=1;i<=5;i++));do echo $i;done

while

i=1;while [ $i -le 5 ];do echo $i;let i++;done
i=1;while (( $i <= 5 ));do echo $i;let i++;done

until

i=1;until (( $i > 5 ));do echo $i;let i++;done

嵌套循环

一个循环体内又包含另一个完整的循环结构,称为循环的嵌套
每次外部循环都会触发内部循环,直至内部循环完成,才会执行下一次外部循环
for while until 都可以互相嵌套

应用实例

1
12
123
1234
12345
#!/bin/bash
for y in {1..5}
        do
                for ((i=1;i<=$y;i++))
                        do
                                echo -n $i
                                #不换行
                        done
                echo
                #换行
        done

for ((y=1;y<=5;y++))
	do
		x=1
		while (($x<=$y))
			do
				echo -n $x
				let x++
			done
		echo
	done

5
54
543
5432
54321
#!/bin/bash
for y in {1..5}
        do
                for ((i=1;i<=$y;i++))
                        do
                                echo -n $i
                        done
                echo
        done
#外部打印换行 内部打印54321

阶段型总结

  • 变量的定义
变量名=变量值
echo $变量名
echo ${变量名}

read -p "提示用户信息:" 变量名
#交互式
declare -i/-x/-r 变量名=变量值
#定义变量类型
  • 流程控制语句
if [ 条件判断 ];then
	command
fi

if [ 条件判断 ];then
	command
else
	command
fi

if [ 条件判断1 ];then
	command
elif [ 条件判断2 ];then
	command2
else
	command3
fi
  • 循环语句
目的:某个动作要重复去做
for
while
until
  • 影响shell程序的内置命令
exit	退出整个程序
break	结束当前循环,或跳出本层循环
continue	忽略本次循环剩下的代码,直接进入下一次循环
shift	使位置参数向左移动,默认移动一位,可以使用shirt 2 向左移动2位

#!/bin/bash
sum=0
while [ $# -ne 0 ]
	do
		let sum=$sum+$1
		#shift
		shift 2
	done
echo sum=$sum

  • 补充扩展expect

expect 自动应答 tcl语言

需求:A远程登录到server上什么都不做

#!/usr/bin/expect
#开启一个程序
spawn ssh root@192.168.0.160
#捕获相关内容
expect {
		"(yes/no)?" { send "yes\r";exp_continue }
		"password:" { send "zss@123\r" }
}
interact   //交互

#脚本执行方式
#./expect1.sh
#/zss/expect1.sh
#expect -f expect1.sh

定义变量
#!/usr/bin/expect
set ip 192.168.0.160
set pass zss@123
set timeout 5
spawn ssh root@$ip
expect {
		"(yes/no)?" { send "yes\r";exp_continue }
		"password:" { send "$pass\r" }
}
interact

需求2:A远程登录到server上操作

#!/usr/bin/expect
set ip 192.168.0.160
set pass zss@123
set timeout 5
spawn ssh root@$ip
expect {
		"(yes/no)?" { send "yes\r";exp_continue }
		"password:" { send "$pass\r" }
}
expect "#"
send "rm -rf /tmp/*\r"
send "touch /tmp/file{1..3}\r"
send "date\r"
send "exit\r"
expect eof

#使用位置参数
#!/usr/bin/expect
set ip [ lindex $argv 0 ]
#位置参数 第一个和第二个
set pass [ lindex $argv 1 ]
set timeout 5
spawn ssh root@$ip
expect {
		"(yes/no)?" { send "yes\r";exp_continue }
		"password:" { send "$pass\r" }
}
interact

需求3:shell脚本和expect结合使用,在多台服务器上创建1个用户
思路:循环for 远程登陆 ssh 从文件获取ip和密码 expect 解决交互问题

for i in `wc -l ip.txt|cut -d ' ' -f1`
	do
	done
	
ip.txt
192.168.0.150 zss@123
192.168.0.160 zss@123

#!/bin/bash
while read ip pass
#定义ip pass 2个变量 来自于文件ip.txt
	do
		#调用expect
		/usr/bin/expect <<-END &>/dev/null
		#- 不加的话 下面的END要顶格写
		spawn ssh root@$ip
		expect {
		"(yes/no)?" { send "yes\r";exp_continue }
		"password:" { send "$pass\r" }
}
		expect "#" { send "useradd yy1;rm -rf /tmp/*;exit\r"}
		#传递执行命令
		expect eof
		END
	echo "$ip 服务器yy1用户创建完毕"
	done < ip.txt

#cat >> file << !
#sadasd
#adadasdasd 
#!
  • 需求4:推送公钥给别的所有服务器
  • 1.用户生成密钥对

账号是否存在id 判断该用户是否有密钥对文件-f

  • 2.判断expect是否存在
  • 3.判断局域网内主机是否ping通
    循环判断 for while
    do...done ping主机 通 expect自动应答推送公钥
  • 4.推送公钥给可以ping的主机

验证是否免密登录成功
循环判断主机是否ping通
检查服务器上ssh服务
推送成功 保存文件
关闭防火墙和selinux
日志记录
推送公钥需要自动应答expect

ssh-keygen
ssh-copy-id root@192.168.0.160
ssh-keygen -P '' -f ~/.ssh/id_rsa

#!/bin/env bash
# 实现批量推送公钥
id zss &>/dev/null
[ $? -ne 0 ] && useradd zss && echo 123|passwd --stdin zss
#判断用户是否存在
rpm -q expect
[ $? -ne 0 ] && yum -y install expect && echo "expect软件安装成功"
/usr/bin/expect <<-END
spawn su - zss
expect "~]$\r"
send { "[ ! -f /home/zss/.ssh/id_rsa.pub ] && ssh-keygen -P '' -f id_rsa &>/dev/null;\r" }
expect eof
END
[ ! -f /home/zss/.ssh/id_rsa.pub ] && ssh-keygen -P '' -f id_rsa 
#!/bin/env bash
# 实现批量推送公钥
#id zss &>/dev/null
#[ $? -ne 0 ] && useradd zss && echo 123|passwd --stdin zss
#判断用户是否存在
#rpm -q expect
#[ $? -ne 0 ] && yum -y install expect && echo "expect软件安装成功"
#判断expect软件是否安装
[ ! -f /home/zss/.ssh/id_rsa.pub ] && ssh-keygen -P '' -f ~/.ssh/id_rsa &>/dev/null
#判断公钥是否存在
tr ':' ' ' < /home/zss/zss/ip.txt|while read ip pass
do
#{
        ping -c1 $ip &>/dev/null
        if [ $? -eq 0 ];then
                echo $ip > ./ip_up.txt
                /usr/bin/expect <<-END &>/dev/null
                set timeout 10
                spawn ssh-copy-id root@$ip
                expect {
                  "(yes/no)?" { send "yes\r";exp_continue}
                  "password:" { send "$pass\r" }
                       }
                expect eof
                END
                fi
#}&
done
#wait
echo "$ip 公钥已经发送完毕"
#测试
#sleep 15
remote_ip=`tail -1 ./ip_up.txt`
ssh root@$remote_ip hostname &>/dev/null
test $? -eq 0 && echo "公钥推送完毕"

难搞呦还有点小瑕疵

  • visudo
root ALL=(ALL) ALL
zss ALL=(root) NOPASSWD:ALL,!/sbin/shoudown
#除了关机的所有权限 一般不这样写 只允许某些个别的命令

- 需求5:统计web服务的不同连接状态的个数
涉及到下一个数组的知识点
1.找出查看网站连接状态的命令ss -natp |grep :80 |cut -d ' ' -f1
2.如何统计出不同的状态 循环去统计

#!/bin/bash

declare -A array1
state=`ss -ant|grep 80|cut -d' ' -f1`
for i in $states
	do
		let arry1[$i]++
	done
#统计

	#通过遍历数组里的索引和元素打印出来
for j in ${!arry1[@]}
	do
		$j:${arry1[$j]}
	done
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值