AI智能
改变未来

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-49echo $[RANDOM%50+1]产生50-100之间的随机数0-50echo $[RANDOM%51+50]产生10-99之间的随机数0-89echo $[RANDOM%90+10]产生100-999之间的随机数0-899echo $[RANDOM%900+100]

实战案例

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

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

#!/bin/bashfile=/zss.txtfor i in {1..1000}don1=$[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\" >> $filelet 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/bashphone=/zss.txtfor ((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\" $phonedone
  • 批量创建用户 密码随机生成

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

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

总结

for

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

while

i=1;while [ $i -le 5 ];do echo $i;let i++;donei=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 都可以互相嵌套

应用实例

112123123412345#!/bin/bashfor y in {1..5}dofor ((i=1;i<=$y;i++))doecho -n $i#不换行doneecho#换行donefor ((y=1;y<=5;y++))dox=1while (($x<=$y))doecho -n $xlet x++doneechodone554543543254321#!/bin/bashfor y in {1..5}dofor ((i=1;i<=$y;i++))doecho -n $idoneechodone#外部打印换行 内部打印54321

阶段型总结

  • 变量的定义
变量名=变量值echo $变量名echo ${变量名}read -p \"提示用户信息:\" 变量名#交互式declare -i/-x/-r 变量名=变量值#定义变量类型
  • 流程控制语句
if [ 条件判断 ];thencommandfiif [ 条件判断 ];thencommandelsecommandfiif [ 条件判断1 ];thencommandelif [ 条件判断2 ];thencommand2elsecommand3fi
  • 循环语句
目的:某个动作要重复去做forwhileuntil
  • 影响shell程序的内置命令
exit	退出整个程序break	结束当前循环,或跳出本层循环continue	忽略本次循环剩下的代码,直接进入下一次循环shift	使位置参数向左移动,默认移动一位,可以使用shirt 2 向左移动2位#!/bin/bashsum=0while [ $# -ne 0 ]dolet sum=$sum+$1#shiftshift 2doneecho sum=$sum
  • 补充扩展expect

expect 自动应答 tcl语言

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

#!/usr/bin/expect#开启一个程序spawn ssh [email protected]#捕获相关内容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/expectset ip 192.168.0.160set pass zss@123set timeout 5spawn ssh root@$ipexpect {\"(yes/no)?\" { send \"yes\\r\";exp_continue }\"password:\" { send \"$pass\\r\" }}interact

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

#!/usr/bin/expectset ip 192.168.0.160set pass zss@123set timeout 5spawn ssh root@$ipexpect {\"(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/expectset ip [ lindex $argv 0 ]#位置参数 第一个和第二个set pass [ lindex $argv 1 ]set timeout 5spawn ssh root@$ipexpect {\"(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`dodoneip.txt192.168.0.150 [email protected] zss@123#!/bin/bashwhile read ip pass#定义ip pass 2个变量 来自于文件ip.txtdo#调用expect/usr/bin/expect <<-END &>/dev/null#- 不加的话 下面的END要顶格写spawn ssh root@$ipexpect {\"(yes/no)?\" { send \"yes\\r\";exp_continue }\"password:\" { send \"$pass\\r\" }}expect \"#\" { send \"useradd yy1;rm -rf /tmp/*;exit\\r\"}#传递执行命令expect eofENDecho \"$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-keygenssh-copy-id [email protected] -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 <<-ENDspawn su - zssexpect \"~]$\\r\"send { \"[ ! -f /home/zss/.ssh/id_rsa.pub ] && ssh-keygen -P \'\' -f id_rsa &>/dev/null;\\r\" }expect eofEND[ ! -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 passdo#{ping -c1 $ip &>/dev/nullif [ $? -eq 0 ];thenecho $ip > ./ip_up.txt/usr/bin/expect <<-END &>/dev/nullset timeout 10spawn ssh-copy-id root@$ipexpect {\"(yes/no)?\" { send \"yes\\r\";exp_continue}\"password:\" { send \"$pass\\r\" }}expect eofENDfi#}&done#waitecho \"$ip 公钥已经发送完毕\"#测试#sleep 15remote_ip=`tail -1 ./ip_up.txt`ssh root@$remote_ip hostname &>/dev/nulltest $? -eq 0 && echo \"公钥推送完毕\"

难搞呦还有点小瑕疵

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

– 需求5:统计web服务的不同连接状态的个数
涉及到下一个数组的知识点
1.找出查看网站连接状态的命令

ss -natp |grep :80 |cut -d \' \' -f1

2.如何统计出不同的状态 循环去统计

#!/bin/bashdeclare -A array1state=`ss -ant|grep 80|cut -d\' \' -f1`for i in $statesdolet arry1[$i]++done#统计#通过遍历数组里的索引和元素打印出来for j in ${!arry1[@]}do$j:${arry1[$j]}done
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 9.Shell之随机数,嵌套循环,阶段总结,expect