Linux中shell编程的函数递归用法和脚本自动化讲解

一、函数递归

1.1 函数简介

样式1:函数间调用
    - 函数体内部调用其他的函数名
样式2:文件间调用
    - 函数体内部调用另外一个文件的函数名
    - 需要额外做一步文件source的加载动作
    注意:我们将专门提供函数的文件称为 -- 函数库
样式3:函数自调用
    - 函数体内部调用自己的函数名,将复杂的逻辑简单化

1.2 简单实践

需求: 实现数学阶乘的实践
    示例:5的阶乘
         完整格式:5! = 1 * 2 * 3 * 4 * 5 = 120
         简写格式:5! = 5 * (1 * 2 * 3 * 4) = 5 * 4!
    公式: x! = x * (x-1)!

查看脚本内容
[root@localhost ~]# vim a.sh
#!/bin/bash
# 功能:函数自调用实践# 定制功能函数框架
self_func(){# 接收一个参数num=$1if [ ${num} -eq 1 ];thenecho 1else# 定制一个临时本地变量,获取递减后的值local temp=$[ ${num} - 1 ]# 使用函数自调用方式获取内容local result=$(self_func $temp)# 格式化输出信息echo $[ $result * ${num} ]fi
}# 检测逻辑效果
while true
doread -p "请输入一个您要查询的阶乘:" valueresult=$(self_func ${value})echo "${value}的阶乘是: ${result}"
done

1.3 案例实践

实践1-遍历制定目录下的所有文件

[root@localhost ~]# vim a.sh
#!/bin/bash
# 功能:扫描目录下所有文件
# 版本:v0.1
# 作者:书记
# 联系:# 定制功能函数框架
# 定制目录扫描功能函数
scan_dir() {# 定制临时局部功能变量# cur_dir 当前目录 workdir 工作目录local cur_dir workdir# 接收要检查的目录,进入到目录中workdir=$1cd ${workdir}# 对工作目录进行简单判断,根目录没有父目录if [ ${workdir} = "/" ]thencur_dir=""elsecur_dir=$(pwd)fi# 查看当前目录下的文件列表for item in $(ls ${cur_dir})do# 如果文件是目录,则继续查看目录下文件if test -d ${item};thencd ${item}scan_dir ${cur_dir}/${item}cd ..# 如果文件是普通文件,则输出信息即可elseecho ${cur_dir}/${item}fidone
}# 检测逻辑效果
while true
doread -p "请输入一个您要查询的目录:" valueif [ -d ${value} ]thenscan_dir ${value}elseecho "您输入的不是目录,请重新输入!"fi
done

二、脚本自动化

2.1 简介

信号描述信号描述
1SIGHUP挂起进程15SIGTERM优雅的终止进程
2SIGINT终止进程17SIGSTOP无条件停止进程,不终止进程
3SIGQUIT停止进程18SIGTSTP停止或暂停进程,不终止进程
9SIGKILL无条件终止进程19SIGCONT继续运行停止的进程

  默认情况下,bash shell会忽略收到的任何SIGQUIT(3)和SIGTERM(15)信号(正因为这样交互式shell才不会被意外终止)。但是bash shell会处理收到的SIGHUP(1)和SIGINT(2)信号。

    如果bash shell收到SIGHUP信号,它会退出。但在退出之前,它会将信号传给shell启动的所有进程(比如shell脚本)。通过SIGINT信号,可以中断shell,Linux内核停止将CPU的处理时间分配给shell,当这种情况发生时,shell会将SIGINT信号传给shell启动的所有进程。

生成信号

终止进程:ctrl+c,
暂停进程:ctrl+z,停止的进程继续保留在内存中,并能从停止的位置继续运行
恢复进程:jobs查看运行任务,fg num 重新执行
杀死进程:kill -9 pid

2.2 信号捕捉

简介

    shell编程提供了一种方式,让我们可以随意的控制脚本的运行状态,这就需要涉及到信号的捕获操作。在shell编程中,我们可以借助于 trap命令实现指定shell脚本要watch哪些linux信号并从shell中拦截。如果脚本收到了trap命令中列出的信号,它会阻止它被shell处理,而在本地处理。

trap命令格式

命令格式trap commands signals命令示例:# 收到指定信号后,执行自定义指令,而不会执行原操作trap '触发指令' 信号# 忽略信号的操作trap '' 信号# 恢复原信号的操作trap '-' 信号# 列出自定义信号操作trap -p# 当脚本退出时,执行finish函数trap finish EXIT

简单实践

实践1-捕获终止信号

查看脚本内容
[root@localhost ~]# vim a.sh
#!/bin/bash
# 功能:脚本信号捕捉# 捕获关闭信号
trap "echo '你敢关我,就不关,气死你'" SIGINT SIGTERM
trap "echo '走了,不送'" EXIT# 检测逻辑效果
while true
doread -p "请输入一个数据:" valueecho "您输入的数据是: ${value}"
done

效果:

脚本执行效果
[root@localhost ~]# /bin/bash a.sh
请输入一个数据:4
您输入的数据是: 4
请输入一个数据:^Csignal_trap_test1.sh:行1: 你敢关我,就不关,气死你: 未找到命令您输入的数据是:
请输入一个数据:^Z
[1]+  已停止               /bin/bash signal_trap_test1.sh
[root@localhost ~]#
[root@localhost ~]# jobs
[1]+  已停止               /bin/bash signal_trap_test1.sh
[root@localhost ~]# fg 1
/bin/bash signal_trap_test1.sh您输入的数据是:
请输入一个数据:3
您输入的数据是: 3
另开一个终端,直接kill进程
[root@localhost ~]# ps aux | grep sign
root      39142  0.0  0.0 113288  1460 pts/0    S+   17:43   0:00 /bin/bash signal_trap_test1.sh
[root@localhost ~]# kill -9 39142回到之前的终端查看效果
[root@localhost ~]# fg 1
/bin/bash signal_trap_test1.sh您输入的数据是:
请输入一个数据:3
您输入的数据是: 3
请输入一个数据:已杀死

实践2-捕获正常退出

查看脚本内容
[root@localhost ~]# vim a.sh
#!/bin/bash
# 功能:脚本信号捕捉# 捕获关闭信号
trap "echo '走了.不送'" EXITvalue="0"
# 检测逻辑效果
while true
doread -p "请输入一个数据:" valueif [ ${value} == "9" ]thenexitelseecho "您输入的数据是: ${value}"fi
done

实践3-移除捕获

查看脚本内容
[root@localhost ~]# vim a.sh
#!/bin/bash
# 功能:移除脚本信号捕捉# 捕获关闭信号
trap "echo '走了.不送'" EXITi=1
# 检测逻辑效果
while [ $i -le 3 ]
doread -p "请输入一个数据:" valueif [ ${value} == "9" ]thenexitelseecho "您输入的数据是: ${value}"filet i+=1
done# 移除捕获信号
trap - EXIT
echo "移除了捕获信号"

三、expect基础

3.1 基础知识

场景需求

        在日常工作中,经常会遇到各种重复性的"手工交互"操作,虽然没有什么技术含量,但是相当的重要。在实际的工作场景中,这种重复性的手工操作动作,非常的繁多,但是对于量大的工作来说,效率就非常低效了。所以我们就需要有一种工具,能够简化我们重复的手工操作。

expect简介

        expect是一个免费的编程工具,由DonLibes制作,作为Tcl脚本语言的一个扩展,它可以根据程序的提示,模拟标准输入提供给程序,从而实现自动的交互式任务,而无需人为干预,可以用作Unix系统中进行应用程序的自动化控制和测试的软件工具。

        说白了,expect就是一套用来实现自动交互功能的软件。它主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互通信。在使用的过程中,主要是以脚本文件的样式来存在

官方网站:
    https://www.nist.gov/services-resources/software/expect
工具手册:
    man expect

软件部署

安装软件
[root@localhost ~]# yum install expect -y进入专用的命令交互界面
[root@localhost ~]# expect
expect1.1>  ls
anaconda-ks.cfg
expect1.2> exit
命令帮助-c:	执行脚本前先执行的命令,可多次使用,多个命令之间使用;隔开-d:	debug模式,可以在运行时输出一些诊断信息,与在脚本开始处使用exp_internal 1相似。-D:	启用交换调式器,可设一整数参数。-f:	从文件读取命令,仅用于使用#!时。如果文件名为"-",则从stdin读取(使用"./-"从文件名为-的文件读取)。-i:	交互式输入命令,使用"exit"或"EOF"退出输入状态。--:	标示选项结束(如果你需要传递与expect选项相似的参数给脚本时),可放到#!行:#!/usr/bin/expect --。-v:	显示expect版本信息

3.2 简单实践

    在进行expect脚本编写的时候,我们需要记住 -- expect 用的不是我们普通的shell或者python语法,它使用的是Tcl语法。

    Tcl 全称是 Tool command Language。它是一个基于字符串的命令语言,基础结构和语法非常简单,易于学习和掌握。Tcl 语言是一个解释性语言,所谓解释性是指不象其他高级语言需要通过编译和联结,它象其他 shell 语言一样,直接对每条语句顺次解释执行。

    Tcl 数据类型简单。对 Tcl 来说,它要处理的数据只有一种——字符串。Tcl 将变量值以字符串的形式进行存储,不关心它的实际使用类型。

输出语法

输出:tcl使用”puts"关键字来作为输出语句
样式:puts -nonewline string
属性解析:
    如果string中间有特殊字符,可以使用 {} 或者 "" 将其作为一个小组,共同输出
    -nonewline 代表输出结果的时候,不输出换行符
    put 和 puts 都可以在命令行使用,但是脚本中,最好用puts

脚本基础

1 文件名后缀   
    .expect 作为标识符
2 文件首行,要指定命令的执行解释器 
    #!/usr/bin/expect
3 脚本文件的执行
    expect 脚本名

脚本内容示例
[root@localhost ~]# vim a.expect
#!/usr/bin/expect
# 设定一个环境变量
set var nihao
# 输出环境变量
puts $var脚本执行效果
[root@localhost ~]# expect expect_test.expect
nihao

3.3 语法实践

赋值语法

        赋值:tcl 使用“set”关键字来定义参数,不必指定变量值的类型,因为变量值的类型仅一种——字符串
样式:set varName [value] 
注意:
    变量名是由 数字、下划线、字符组成,数字不能开头,大小写敏感。

expect1.7> set a Hello			# 设定一个变量名a
Hello
expect1.8> put $a				# 使用$ 符号获取变量名的存储值
Hello
expect1.9> put "$a"				# 使用 "" 方式打印变量的值
Hello
expect1.10> put {$a}			# {} 有别于"" 的特点在于原字符输出
$a
expect1.11> set b $a			# 变量的传递
Hello
expect1.12> puts $b
Hello

替换语法

替换(解析):- $符号可以实现引用替换,用于引用变量名代替的参数值,但是TCL对嵌套的”$”不于理睬- [] 方括号“[]”完成命令替换。用“[]”将一条命令括起来,命令执行完成后,返回结果
expect1.20> set b [set a 5]					# 相当于 set b $a,传递赋值
5
expect1.21> puts $b
5
expect1.22> set c [expr 5 * 10 ]			# expr是执行系统命令,将计算结果交给c
50
expect1.24> puts $c
50

注意事项

变量的设定
expect1.13> set var value					# 设定一个普通变量名
value
expect1.14> puts $var						# 获取变量名的值
value不支持嵌套$
expect1.15> set var1 $$value				# TCL不支持嵌套的$
can't read "value": no such variablewhile executing
"set var1 $$value"
expect1.16> set var1 $$var					# 由于$var 已经是变量,所以前面的$就无效了
$value
expect1.17> puts $var1
$value原字符输出
expect1.18> set var2 {$var1}				# {} 代表原字符输出
$var1
expect1.19> puts $var2
$var1

脚本实践

内置变量

对于tcl来说,它内部包含了大量的内置变量,可以让我们实现快速的功能操作。


常见的内置变量有:
    argc    指命令行参数的个数。
    argv    指包含命令行参数的列表。
    argv0    是指被解释的文件或由调用脚本的名称的文件名。
    env        用于表示是系统环境变量的内容,普通变量我们还是使用$即可
    tcl_version    返回Tcl解释器的最新版本,注意不是expect的版本号

内置参数实践

[root@localhost ~]# cat expect_test1.expect
#!/usr/bin/expect
# 查看当前文件传递的参数数量
puts "当前文件传递的参数数量: $argc"# 查看当前文件传递的参数
puts "当前文件传递的参数: $argv"# 查看当前文件名称
puts "当前文件名称: $argv0"# 获取变量值
puts "当前系统变量PATH的值是: $env(PATH)"
set key value
puts "普通变量 key 的值是: $key"# 查看版本信息
puts "当前tcl版本信息: $tcl_version"
脚本执行效果
[root@localhost ~]# expect expect_test1.expect
当前文件传递的参数数量: 0
当前文件传递的参数:
当前文件名称: expect_test1.expect
当前系统变量PATH的值是: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
普通变量 key 的值是: value
当前tcl版本信息: 8.5

3.4 交互基础

脚本基础

命令解释器

命令解释器
#!/usr/bin/expect
#!/usr/bin/expect -f    从文件中读取自动化命令
#!/usr/bin/expect -     如果文件名为 - ,那么从终端输入中读取
#!/usr/bin/expect -i	交互式输入命令
#!/usr/bin/expect -- 	脚本传递的选项参数和expect选项相似的参数给脚本
注意:#!是对脚本的解释器程序路径,脚本的内容是由解释器解释的注释信息
# 被注释的信息

常见符号

{ }:作用1:保留所有字符原有的意思,而不做解释,类似于shell中的单引号样式:set var {"nihao hehehe"}作用2:代码块儿,但是两个 {} 边界必须在一起。正确样式:if {代码块1 } {代码块2}错误示例:if {$count < 0}{break;}注意:无论什么时候,{}边界符号与其他内容都最好有空格隔开,尤其是边界外的内容
[]:作用:执行命令,类似shell中的 ``(反引号)或者 $()样式:set count [expr $count - 1 ]注意:在expect 中,没有小括号的概念和应用

常用命令

set 		设定环境变量格式:set 变量名 变量值样式:set host "192.168.8.12"spawn 		启动新的进程,模拟手工在命令行启动服务格式:spawn 手工执行命令样式:spawn ssh python@$hostexpect 		接收一个新进程的反馈信息,我们根据进程的反馈,再发送对应的交互命令格式:expect "交互界面用户输入处的关键字"样式:expect "*password*"send 		接收一个字符串参数,并将该参数发送到新进程。格式:send "用户输入的信息"	样式:send "$password\r"interact 	退出自动化交互界面,进入用户交互状态,如果需要用户交互的话,这条命令必须在最后一行格式:interact样式:interact其他命令exit		退出expect脚本expect eof	expect执行内容的结束标识符,退出当前脚本,与interact只能存在一个puts		输出变量的信息,相当于linux命令中的echowait		退出程序后,等待时间,回收僵尸进程disconnect	断开一个进程连接,但让它在后台继续运行。exp_continue 	expect获取期望后,还会有另外的期望,那么我们就把多个期望连续执行

简单实践

实践1-简单的登录交互脚本

查看脚本内容
[root@localhost ~]# cat login_test.expect
#!/usr/bin/expect# 1 设定环境变量
set username python# 2 发起远程登录请求
spawn ssh $username@192.168.66.146# 3 识别用户输入的位置关键字
expect "yes/no"# 4 发送正确的信息
send "yes\r"# 5 识别密码关键字,并传递密码信息
send "\r"
expect "password:"
send "123456\r"# 6 切换回用户交互界面
interact注意:由于password前面会涉及到一次Enter操作,所以在password匹配前,输入一次 \r

清理历史记录
[root@localhost ~]# rm -f ~/.ssh/known_hosts

执行脚本内容
[root@localhost ~]# expect login_test.expect
spawn ssh python@10.0.0.12
The authenticity of host '10.0.0.12 (10.0.0.12)' can't be established.
ECDSA key fingerprint is SHA256:XUJsgk4cTORxdcswxIKBGFgrrqFQzpHmKnRRV6ABMk4.
ECDSA key fingerprint is MD5:71:74:46:50:3f:40:4e:af:ad:d3:0c:de:2c:fc:30:c0.
Are you sure you want to continue connecting (yes/no)? yes

Warning: Permanently added '10.0.0.12' (ECDSA) to the list of known hosts.
python@10.0.0.12's password:
[python@localhost ~]$ id
uid=1000(python) gid=1000(python) 组=1000(python)

实践2-脚本结合

expect 除了使用专用的expect脚本来实现特定功能之外,它还可以与其他脚本嵌套在一起进行使用。最常用的结合方式就是 shell结合。

在于shell结合使用的时候,无非就是将expect的执行命令使用 <<-EOF  。。。 EOF 包装在一起即可。
样式:
/usr/bin/expect<<-EOF
spawn ...
...
expect eof 
EOF

注意:
    由于expect在shell中是作为一个子部分而存在的,所以,一般情况下,expect结束的时候,使用eof命令表示expect的内容到此结束

查看脚本内容
[root@localhost ~]# cat expect_auto_login.sh
#!/bin/bash
# 功能:shell自动登录测试
# 版本:v0.1
# 作者:书记
# 联系:# 定制普通变量
host="$1"
username="$2"
password="$3"/usr/bin/expect <<-EOF
# 发出连接进程
spawn ssh ${username}@${host}# - 正常登陆
expect {"yes/no*" {  send "yes\n"; exp_continue  }"password:" {send "${password}\n";}
}
puts "测试完毕!!!"
expect eof
EOF

脚本测试效果
[root@localhost ~]# /bin/bash expect_auto_login.sh 10.0.0.12 python 123456
spawn ssh python@10.0.0.12
python@10.0.0.12's password: 测试完毕!!!

[python@localhost ~]$ exit
[root@localhost ~]#

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/pingmian/84653.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于数据库实现配置管理和定时任务启停

本文大纲 1、背景2、实现思路3、基于数据库实现4、总结 1、背景 项目中&#xff0c;定时任务的控制&#xff0c;常常通过配置文件中的开关&#xff0c;但如果定时任务很多&#xff0c;配置文件维护就很烦&#xff0c;且要考虑配置热部署的问题 2、实现思路 上一篇提到了一些…

Linux服务器上MySQL CPU使用率过高问题排查与定位

文章目录 一、CPU高负载常见成因分析1.1 全表扫描与索引缺失1.2 复杂计算与临时表1.3 锁竞争与线程上下文切换1.4 查询优化器误判1.5 硬件资源瓶颈 二、操作系统级初步定位2.1 使用top定位MySQL进程2.2 用pidstat分析线程级CPU2.3 vmstat分析系统负载 三、数据库层深度诊断3.1 …

Java解析前端传来的Unix时间戳

在Java中&#xff0c;前端传递的 1749571200000 是一个 Unix时间戳&#xff08;毫秒级&#xff09;&#xff0c;表示自1970年1月1日00:00:00 UTC以来经过的毫秒数。以下是两种常见的解析方式&#xff08;推荐使用Java 8的java.time API&#xff09;&#xff1a; 方法1&#xff…

error report

build/X86_VI_hammer_GPU/mem/ruby/network/garnet/fixed-pipeline/OutputUnit_d.cc: In member function ‘int OutputUnit_d::getVCBufferOccupancy(int)’: build/X86_VI_hammer_GPU/mem/ruby/network/garnet/fixed-pipeline/OutputUnit_d.cc:135:40: error: no matching fu…

本地部署模型 --vLLM + Docker 部署+封装接口

vLLM的介绍 vLLM的核心特性&#xff1a; 最先进的服务吞吐量 使用PageAttention高效管理注意力键和值的内存 量化&#xff1a;GPTQ&#xff0c;AWQ&#xff0c;INT4&#xff0c;INT8和FP8 VLLM的灵活性和易用性体现在以下方面&#xff1a; 具有高吞吐量服务以及各种解码算法…

每日一博 - JWT 安全实战指南

文章目录 Pre引言背景与原理简介核心安全挑战传输层安全实践签名算法与密钥管理Header 与 Claims 严格校验Token 生命周期管理存储与前端实践抗攻击措施日志与监控附加增强与高级方案小结与建议后续方向 引言&#xff1a;阐述 JWT 的流行与安全重要性背景与原理简介&#xff1a…

403 Access Denied Tomcat managerapp

提示 403 Access Denied You are not authorized to view this page. By default the Manager is only accessible from a browser running on the same machine as Tomcat. If you wish to modify this restriction, you’ll need to edit the Manager’s context.xml file.…

工业镜头选型讲解

B站 &#xff1a;道传科技上位机 观看教程 一、工业镜头介绍 镜头的主要作用是 将目标成像在图像传感器的光敏面上。 下图左一的型号为 焦距 50mm 最大光圈为F1.6 镜头的像面尺寸为2/3英寸&#xff08;最大能够兼容CCD芯片尺寸&#xff09; 二、工业镜头的分类 镜头的…

重构技术奇点的路径:三智双融认知大飞跃

结合三智双融理论认知大飞跃框架重构技术奇点的路径 构建一个三维修订框架&#xff1a;首先分析融智学视域下的奇点渗透本质&#xff0c;然后按时间线逐年修订预言并补充融智学维度&#xff0c;最后提出人机共生的实践路径。考虑设计表格对比原预言与修订后的差异&#xff0c;突…

LabVIEW利用Monte Carlo 工业数据模拟应用

基于LabVIEW 平台&#xff0c;结合 NI 工业级硬件构建 Monte Carlo 模拟系统&#xff0c;实现工业传感器数据不确定性分析与设备故障概率预测。通过图形化编程架构与高性能硬件协同&#xff0c;解决复杂工业场景下的随机问题量化分析需求&#xff0c;适用于智能制造、能源监控等…

2025年渗透测试面试题总结-天翼电子公司[社招]安全运营岗(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 天翼电子商务有限公司[社招]安全运营岗 1. Web服务加固方案 2. IAST技术解析 3. SCA&#xff08;软件成分…

Java NIO详解:新手完全指南

文章目录 1. NIO简介1.1 NIO的核心优势1.2 NIO的适用场景 2. NIO与IO的对比2.1 代码对比示例2.1.1 传统IO读取文件2.1.2 NIO读取文件 3. NIO核心组件3.1 Buffer&#xff08;缓冲区&#xff09;3.2 Channel&#xff08;通道&#xff09;3.3 Selector&#xff08;选择器&#xff…

webgl(three.js 与 cesium 等实例应用)之浏览器渲染应用及内存释放的关联与应用

文章目录 WebGL 概念1. 纹理&#xff08;Texture&#xff09;&#x1f4cc; 概念&#xff1a;&#x1f9e9; 应用方向&#xff1a;&#x1f4a1; 示例代码&#xff08;加载一张图片作为纹理&#xff09;&#xff1a; 2. 缓冲区&#xff08;Buffer&#xff09;&#x1f4cc; 概念…

黑马点评【缓存】

目录 一、为什么要使用缓存 二、添加商户缓存 1.缓存的模型和思路 2.代码 3.缓存更新策略 Redis内存淘汰机制&#xff1a; 3.1 被动淘汰策略&#xff08;不主动淘汰&#xff0c;仅在查询时触发&#xff09; 3.2 主动淘汰策略&#xff08;主动扫描内存&#xff0c;按规则…

【地图服务限制范围】

根据你提供的 eb_service_area 表结构&#xff0c;其中有两个字段与地理坐标相关&#xff1a;latlng 和 limit_latlng。这两个字段分别用于存储服务范围区域的坐标和限制区域的坐标。下面是对这两个字段的具体分析以及如何使用它们来定义执行范围。 字段分析 latlng&#xff0…

python数据结构和算法(1)

数据结构和算法简介 数据结构&#xff1a;存储和组织数据的方式&#xff0c;决定了数据的存储方式和访问方式。 算法&#xff1a;解决问题的思维、步骤和方法。 程序 数据结构 算法 算法 算法的独立性 算法是独立存在的一种解决问题的方法和思想&#xff0c;对于算法而言&a…

Linux操作系统-性能优化

1. 基础工具 top / htop top # 实时查看CPU、内存、进程 htop # 增强版&#xff08;支持鼠标操作&#xff09; 关键指标&#xff1a;%CPU&#xff08;CPU占用&#xff09;、%MEM&#xff08;内存占用&#xff09;、LOAD AVERAGE&#xff08;系统负载&#…

如何彻底解决缓存击穿、缓存穿透、缓存雪崩

一、缓存击穿 成因&#xff1a;缓存击穿通常发生在某个热点数据失效或清空后&#xff0c;大量请求同时涌入后端数据库&#xff0c;导致数据库崩溃或宕机。 解决方案&#xff1a; 互斥锁&#xff1a;在获取数据时&#xff0c;使用分布式锁&#xff08;如Redis的分布式锁&…

JDK 8、JDK 17和JDK 19综合对比分析

JDK 8、JDK 17和JDK 19在性能、特性、易用性及普及性等方面的综合对比分析&#xff0c;结合了各版本的核心改进和实际应用场景 目录 ⚡ 一、性能对比 ✨ 二、语言与特性演进 &#x1f6e0;️ 三、API与功能增强 &#x1f3af; 四、易用性改进 &#x1f4ca; 五、市场普及…

Vue-理解 vuex

一、前言 在开发中大型 Vue 应用时&#xff0c;我们常常会遇到多个组件之间共享数据、通信复杂的问题。例如&#xff1a; 多个组件需要访问同一个用户信息&#xff1b;组件之间需要传递状态或事件&#xff1b;数据变更需要同步更新多个组件&#xff1b; 这时&#xff0c;Vue…