2026/4/18 10:30:38
网站建设
项目流程
网站正常打开速度慢,深圳app网站设计,外贸小语种网站建设,jsp编写网站while 循环和 until 循环的应用实践 文章目录while 循环和 until 循环的应用实践1 当型和直到型循环语法1.1 while 循环语句1.2 until 循环语句2 当型和直到型循环的基本范例3 让 Shell 脚本在后台运行的知识并发控制wait 指令4 企业生产实战#xff1a;while 循环语句实践5 w…while 循环和 until 循环的应用实践文章目录while 循环和 until 循环的应用实践1 当型和直到型循环语法1.1 while 循环语句1.2 until 循环语句2 当型和直到型循环的基本范例3 让 Shell 脚本在后台运行的知识并发控制wait 指令4 企业生产实战while 循环语句实践5 while 循环按行读文件的方式总结6 企业级生产高级实战案例循环语句命令常用于重复执行一条指令或一组指令直到条件不再满足时停止Shell脚本语言的循环语句常见的有while、until、for及select循环语句。while 循环语句主要用来重复执行一组命令或语句在企业实际应用中常用于守护进程或持续运行的程序除此以外大多数循环都会用后文即将讲解的for循环语句。1 当型和直到型循环语法1.1 while 循环语句while 循环语句的基本语法为while条件表达式do指令...done提示注意代码缩进。while 循环语句会对紧跟在while命令后的条件表达式进行判断:如果该条件表达式成立则执行while 循环体里的命令或语句即语法中do和done之间的指令)每一次执行到done时就会重新判断while条件表达式是否成立直到条件表达式不成立时才会跳出while 循环体。如果一开始条件表达式就不成立那么程序就不会进入循环体即语法中do和done之间的部分中执行命令了。为了便于大家记忆下面是某女生写的while条件语句的中文形象描述:# 如果男朋友努力工作则继续相处while男朋友努力工作do继续相处donewhile 循环执行流程对应的逻辑图如下1.2 until 循环语句until 循环语句的语法为:until条件表达式do指令...doneuntil 循环语句的用法与while 循环语句的用法类似区别是until会在条件表达式不成立时进入循环执行指令条件表达式成立时终止循环。为了便于大家记忆下面是某女生写的until条件语句的中文形象描述:# 如果男朋友不努力工作就不继续相处until男朋友不努力工作do继续相处doneuntil 循环执行流程对应的逻辑图如下2 当型和直到型循环的基本范例示例1竖向打印54321while格式#!/bin/bashi5while((i0))doecho$i((i--))doneuntil格式#!/bin/bashi5until((i0))doecho$i((i--))done示例2计算123…99100的和#!/bin/bashi1sum0while((i100))do((sumi))# let sumsumi((i))# let idoneecho123...99100$sum示例3计算5的阶乘#!/bin/bashi1sum1while((i5))do((sum*i))((i))doneecho5的阶乘为$sum示例4猴子吃桃。猴子第一天摘下若干个桃子当即吃了一半还不过瘾又多吃了一个。第二天早上又将第一天剩下的桃子吃掉一半又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第 10 天早上想再吃时发现只剩下一个桃子了。问一共有多少个桃子解题方法1while 循环9次#!/bin/bash# 当天桃子数量第一天为1today1# 前一天桃子数量lastday0# 只需要迭代9次i1while((i9))do# 计算上一天桃子数量lastday$[(today1)*2]# 把上一天的数量当作今天的数量today${lastday}((i))doneecho猴子第一天摘的桃子数量是$today。解题方法2函数递归调用#!/bin/bashfunctionsum(){if[[$11]];thenecho$1elseecho$[($(sum$[$1 -1])1)*2]fi}echo猴子第一天摘的桃子数量是$(sum10)。示例5系统随机产生一个50以内数字猜出该数字并记录猜测次数。#!/bin/bash# 生成随机数字并保存到文件/tmp/numberrandom_num$[RANDOM%501]echo${random_num}/tmp/number# 记录猜测次数i0whiletruedoread-p猜一猜系统产生的50以内随机数是numif((num1num50));then((i))if[$num-eq${random_num}];thenecho恭喜你第$i次猜对了# 清理临时文件rm-f /tmp/numberexitelseecho-n第$i次猜测加油。[$num-gt${random_num}]echo太大了往小猜。||echo太小了往大猜。fielseecho请输入一个介于1-50之间的数字。fidone在实际工作中一般会通过客户端SSH连接服务器因此可能就会有在脚本或命令执行期间不能中断的需求若中断则会前功尽弃更要命的是会破坏系统数据。下面是防止脚本执行中断的几个可行方法使用sh /server/scripts/while_01.sh 命令即使用在后台运行脚本。使用nohup /server/scripts/uptime.sh 命令即使用nohup加在后台运行脚本。利用screen保持会话然后再执行命令或脚本即使用screen保持当前会话状态。3 让 Shell 脚本在后台运行的知识脚本运行的相关用法和说明sh whilel.sh 把脚本whilel.sh放到后台执行在后台运行脚本时常用的方法。ctlc停止执行当前脚本或任务。ctlz暂停执行当前脚本或任务。bg把当前脚本或任务放到后台执行。bg可以理解为background。fg把当前脚本或任务放到前台执行如果有多个任务可以使用fg加任务编号调出对应的脚本任务如fg 2调出第二个脚本任务。fg可以理解为frontground。jobs查看当前执行的脚本或任务。kill关闭执行的脚本任务即以“kill %任务编号”的形式关闭脚本。任务编号可以通过jobs命令获得。示例1让所有 CPU 满负荷工作#!/bin/bashcpu_count$(lscpu|grep^CPU(s)|awk{print$2})i1while((i${cpu_count}))do{while:do((11))done}((i))done注意{ comand1;command2;command3; …; } 将多个命令放到后台运行{} 内部两侧有空格。最后一个命令后有分号。并发控制示例1消耗完所有CPU[laomashell ~]$vimcpu_load#!/bin/bashwhiletruedo((11))done[laomashell ~]$vimmulti_cpu_load#!/bin/bashcpu_count$(lscpu|awk/^CPU\(s\):/ { print$2})i1while[$i-le2]dobash/home/laoma/cpu_load((i))done示例2控制并发数量不能超过CPU数量[laomashell ~]$vimcpu_load#!/bin/bashwhiletruedo((11))done# 只允许进程运行10spid$!sleep10kill-9$pid[laomashell ~]$vimmulti_cpu_load#!/bin/bashcpu_count$(lscpu|awk/^CPU\(s\):/ { print$2})whiletruedobash/home/laoma/cpu_load# 控制并发数量不能大于cpu数量whiletruedojobs$(jobs-l|wc-l)if[$jobs-ge$cpu_count];then# 如果并发数大于cpu数量则sleep 3s后继续检测sleep3else# 如果并发数小于cpu数量则退出当前while 循环的并发检测breakfidonedonewait 指令等后台任务运行完成。#!/bin/bash/tmp/sleepi1while[$i-le10]do(sleep$iechosleep$i/tmp/sleep)((i))done# 等待前面后台任务运行完成后再运行wait后指令waitcat/tmp/sleep需求开发两个脚本。第一个cpu_load 用于消耗1个CPU使用率。第二个all_load 用于消耗完系统中所有CPU使用率并且如果发现我的负载程序cpu_load数量少于CPU实际数量则继续运行cpu_load程序指导达到CPU实际数量。[rootserver bin13:51:53]# cat cpu_load#!/bin/bashwhiletruedo((11))done[rootserver bin13:52:38]# cat all_load#!/bin/bashtotal_cpu_count$(lscpu|awkNR4 { print$2})whiletruedocurrent_cpu_count$(psaxu|grepcpu_load|grep-vgrep-c)if((current_cpu_counttotal_cpu_count));thenbash/root/bin/cpu_loadelsesleep3fidone4 企业生产实战while 循环语句实践示例1每隔2秒输出一次系统负载负载是系统性能的基础重要指标情况。[laomashell ~]$catwhile1.sh#!/bin/bashwhiletruedouptimesleep2done[laomashell ~]$bashwhile1.sh17:45:08 up8:39,2users, load average:0.00,0.01,0.0517:45:10 up8:39,2users, load average:0.00,0.01,0.0517:45:12 up8:39,2users, load average:0.00,0.01,0.0517:45:14 up8:39,2users, load average:0.00,0.01,0.05^C# 按 ctrlc 停止运行[laomashell ~]$catwhile2.sh#!/bin/bashwhiletruedouptime/tmp/loadaverage.logsleep2done# 放到后台运行[laomashell ~]$bashwhile2.sh[laomashell ~]$tail-f while2.sh示例2后台检测sshd服务如果未运行则重启sshd服务。while格式#!/bin/bashwhiletruedosystemctl is-active sshd.service/dev/nullif[$?-ne0];thensystemctl restart sshd.service/dev/nullfisleep5doneuntil格式#!/bin/bashuntilfalsedosystemctl is-active sshd.service/dev/nullif[$?-ne0];thensystemctl restart sshd.service/dev/nullfisleep5done示例3使用while守护进程的方式监控网站每隔3秒确定一次网站是否正常。[laomashell scripts]$catcheck_url.sh#!/bin/bashif[$#-ne1];thenechoUsage:$0urlexit1fiurl$1whiletruedoifcurl-o /dev/null -s --connect-timeout5$url;thenecho$urlis ok.elseecho$urlis error.fisleep3done执行结果[laomashell scripts]$bashcheck_url.sh Usage: check_url.sh url[laomashell scripts]$bashcheck_url.sh www.baidu.com www.baidu.com is ok. www.baidu.com is ok. ^C[laomashell scripts]$bashcheck_url.sh www.baidu.co www.baidu.co is error. www.baidu.co is error. ^C示例4手机发信息平台每发一次短信输出当前余额花费1角5分钱当余额低于1角5分钱时就不能再发短信了提示“余额不足请充值”用户充值后可以继续发短信#!/bin/bash# 默认金额money0.5# 保存消息的文件msg_file/tmp/message# 清空消息文件$msg_file# 手机操作菜单functionprint_menu(){catEOF 1. 查询余额 2. 发送消息 3. 充值 4. 退出 EOF}# 检查数字函数functioncheck_digit(){expr$11/dev/nullreturn0||return1}# 显示余额函数functioncheck_money_all(){echo余额为$money。}# 检查余额是否充足functioncheck_money(){new_money$(echo$money*100|bc|cut-d.-f1)if[${new_money}-lt15];thenecho余额不足请充值。# 余额不足返回值为1return1else# 余额充足返回值为0return0fi}# 充值函数functionchongzhi(){read-p充值金额单位元chongzhi_moneywhiletruedocheck_digit$chongzhi_moneyif[$?-eq0][${chongzhi_money}-ge1];thenmoney$(echo($money${chongzhi_money})|bc)echo当前余额为$moneyreturn0elseread-p重新输入充值金额chongzhi_moneyfidone}# 发送消息函数functionsend_msg(){# 检查余额是否充足check_money# 返回值与0比较判定余额是否充足if[$?-eq0];thenread-pmsg: messageecho$message${msg_file}# bc计算器计算的结果如果值小于1则前面的0省略new_money$(echoscale2;($money*100-15)|bc|cut-d. -f1)if[${new_money}-ge100];thenmoney$(echoscale2;${new_money}/100|bc)elsemoney0$(echoscale2;${new_money}/100|bc)fiecho当前余额为$moneyfi}# 主程序whiletruedoprint_menuechoread-p请输入你的选择choiceclearcase$choicein1)check_money_all;;2)send_msg;;3)chongzhi;;4)exit;;*)echo只能从1、2、3、4中选择。;;esacechodone5 while 循环按行读文件的方式总结示例读取/etc/hosts内容[laomashell scripts]$ cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 10.1.8.88 laoma-shell方式1采用exec读取文件然后进入while 循环处理。#!/bin/bashexec/etc/hostswhilereadlinedoecho$linedone方式2使用cat读取文件内容然后通过管道进入while 循环处理。#!/bin/bashcat/etc/hosts|whilereadlinedoecho$linedone方式3在while 循环结尾done处通过输入重定向指定读取的文件。#!/bin/bashwhilereadlinedoecho$linedone/etc/hosts方式4定义shell分隔符为换行符#!/bin/bashIFS$\nforlinein$(cat/etc/hosts)doecho$linedone6 企业级生产高级实战案例写一个Shell脚本解决类DDoS攻击的生产案例。示例1请根据Web日志监控某个IP短时内PV达到一个阈值即调用防火墙命令封掉对应的IP。防火墙命令“iptables -I INPUT -s IP地址 -j DROP”分析题目分析Web日志可以每分钟或每小时分析一次这里给出按小时处理的方法。可以将日志按小时进行分割分成不同的文件根据分析结果把PV数高的单IP封掉。例如每小时单IP的PV数超过500则即刻封掉这里简单地把日志的每一行近似看作一个PV实际工作中需要计算实际页面的数量而不是请求页面元素的数量另外很多公司都是以NAT形式上网的因此每小时单IP的PV数超过多少就会被封掉还要根据具体的情况具体分析本题仅给出一个实现的案例读者使用时需要考虑自身网站的业务去使用。参考答案#!/bin/bashlogfile$1whiletruedoawk{print$1}$logfile|grep-v^$|sort|uniq-c/tmp/tmp.logexec/tmp/tmp.logwhilereadlinedo# 获取IPip$(echo$line|awk{print$2})# 获取对应数量count$(echo$line|awk{print$1})# 如果数量超过500而且当前防火墙列表中没有封该IP则调用iptables封掉该IPif[$count-gt500][$(iptables -L -n|grep$ip|wc-l)-lt1];theniptables -I INPUT -s$ip-j DROP# 记录IP地址echo$ipis dropped/tmp/droplist_$(date%F).logfidone# 1小时统计一次sleep3600done示例2请根据系统网络连接数监控某个IP的并发连接数如果连接数达到100即调用防火墙命令封掉对应的IP。防火墙命令“iptables -I INPUT -s IP地址 -j DROP”分析题目首先要分析单IP占网络连接数的情况即取当前网络连接状态为ESTABLISHED的行数然后分析对应客户端列不同IP连接数量的排序对排序比较高的IP进行封堵。参考答案#!/bin/bashwhiletruedoss -t|grepESTAB|awk{print$4}|cut-d: -f1|sort|uniq-c/tmp/tmp.logexec/tmp/tmp.logwhilereadlinedo# 获取IPip$(echo$line|awk{print$2})# 获取对应数量count$(echo$line|awk{print$1})# 如果数量超过500而且当前防火墙列表中没有封该IP则调用iptables封掉该IPif[$count-gt500][$(iptables -L -n|grep$ip|wc-l)-lt1];theniptables -I INPUT -s$ip-j DROP# 记录IP地址echo$ipis dropped/tmp/droplist_$(date%F).logfidone# 10秒统计一次sleep10done