小破站学习笔记
一切都是未知数
系统变量: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