草庐IT

基于arthas热更新class脚本

行到水穷处 坐看云起时 2023-04-16 原文

1. 概述

基于arthas工具的retransform命令热替换class,此方法用于在不重启项目的前提下,替换更新的class,如关键类添加打印日志,排查线上问题

但arthas工具的命令稍显复杂,有那个时间还不如重新部署,因此需要一个可以快速替换的工具来进行替换

2. 方法一:ArthasHotSwap插件

使用idea插件 ArthasHotSwap插件,安装后,选中类名数据右键点击“swap this class”,会复制一个脚本,然后粘贴到项目启动的服务器上,可完成替换,具体网上均有教程,此处不多赘述。

3. 方法二:自定义shell脚本

我本人也使用过这个插件,但是试过几次均没有成功因此模仿ArthasHotSwap插件的流程,写了一个自定义脚本。

3.1. ArthasHotSwap 插件流程

大致流程如下:

1.将本地需替换的class文件,编码成base64文本文件,并上传至文件服务器(可能是OSS)
2.提供一个默认执行脚本,给用户复制
3.用户拿到复制脚本后,在服务器上执行
4.脚本下载base64文本文件,并解析成class文件
5.启动arthas命令,如果用户没有安装,脚本会自动安装,默认路径 /home/用户名xxx/.arthas/
6.执行arthas中的retransform 命令,将解析出来的class文件替换至运行的jvm中 

插件脚本源码:

点击查看代码
#Copyright (c) 2020, 2021, xxxtai. All rights reserved.
#!/usr/bin/env bash

echo "
  /\$\$\$\$\$\$              /\$\$     /\$\$
 /\$\$__  \$\$            | \$\$    | \$\$
| \$\$  \ \$\$  /\$\$\$\$\$\$  /\$\$\$\$\$\$  | \$\$\$\$\$\$\$   /\$\$\$\$\$\$   /\$\$\$\$\$\$\$
| \$\$\$\$\$\$\$\$ /\$\$__  \$\$|_  \$\$_/  | \$\$__  \$\$ |____  \$\$ /\$\$_____/
| \$\$__  \$\$| \$\$  \__/  | \$\$    | \$\$  \ \$\$  /\$\$\$\$\$\$\$|  \$\$\$\$\$\$
| \$\$  | \$\$| \$\$        | \$\$ /\$\$| \$\$  | \$\$ /\$\$__  \$\$ \____  \$\$
| \$\$  | \$\$| \$\$        |  \$\$\$\$/| \$\$  | \$\$|  \$\$\$\$\$\$\$ /\$\$\$\$\$\$\$/
|__/  |__/|__/         \___/  |__/  |__/ \_______/|_______/
 /\$\$   /\$\$             /\$\$            /\$\$\$\$\$\$
| \$\$  | \$\$            | \$\$           /\$\$__  \$\$
| \$\$  | \$\$  /\$\$\$\$\$\$  /\$\$\$\$\$\$        | \$\$  \__/ /\$\$  /\$\$  /\$\$  /\$\$\$\$\$\$   /\$\$\$\$\$\$
| \$\$\$\$\$\$\$\$ /\$\$__  \$\$|_  \$\$_/        |  \$\$\$\$\$\$ | \$\$ | \$\$ | \$\$ |____  \$\$ /\$\$__  \$\$
| \$\$__  \$\$| \$\$  \ \$\$  | \$\$           \____  \$\$| \$\$ | \$\$ | \$\$  /\$\$\$\$\$\$\$| \$\$  \ \$\$
| \$\$  | \$\$| \$\$  | \$\$  | \$\$ /\$\$       /\$\$  \ \$\$| \$\$ | \$\$ | \$\$ /\$\$__  \$\$| \$\$  | \$\$
| \$\$  | \$\$|  \$\$\$\$\$\$/  |  \$\$\$\$/      |  \$\$\$\$\$\$/|  \$\$\$\$\$/\$\$\$\$/|  \$\$\$\$\$\$\$| \$\$\$\$\$\$\$/
|__/  |__/ \______/    \___/         \______/  \_____/\___/  \_______/| \$\$____/
                                                                      | \$\$
                                                                      | \$\$
                                                                      |__/
"
echo "************************************************** 1. Prepare the workspace **********************************************************"
if [ ! -d "./arthas-hot-swap" ]
then
  mkdir ./arthas-hot-swap
  echo "******* mkdir ./arthas-hot-swap success"
else
  rm -rf ./arthas-hot-swap
  mkdir ./arthas-hot-swap
  echo "******* ./arthas-hot-swap exists, delete the directory first, and then create a new one"
fi
cd ./arthas-hot-swap
rm -f $(pwd)/arthas-hot-swap-result

echo "**************************************************** 2. install openssl **************************************************************"
openssl version
if [[ $? -eq 0 ]]; then
    echo "*******  openssl has been installed successfully "
else
    echo "*******  openssl is not installed, and installation were start next "
    sudo yum install openssl openssl-devel
fi

echo "********************************************* 3. Download the encrypted file *********************************************************"
curl  http://xxxtai-arthas-hot-swap.oss-cn-beijing.aliyuncs.com/public/WHObQxW0HIDDniGwtf0QetenxurLDcwehvqFZPmVx6I=x >> encrypt-FrameController.txt

echo "************************************************* 4. Encrypt the file ****************************************************************"
openssl enc -aes-128-cbc -a -d -in encrypt-FrameController.txt -out FrameController.class -K $1 -iv $2

echo "************************************************* 5. Install arthas ******************************************************************"
specifyJavaHome=
arthas_start_cmd=''

if [[ ${specifyJavaHome} == '' ]]
then
    curl -L https://arthas.aliyun.com/install.sh | sh
    arthas_start_cmd='./as.sh'
else
    curl -O https://arthas.aliyun.com/arthas-boot.jar
    arthas_start_cmd=${specifyJavaHome}" -jar arthas-boot.jar"
fi

selectJavaProcessName=%[selectJavaProcessName]

if [[ ${selectJavaProcessName} != '' ]]
then
    arthas_start_cmd=${arthas_start_cmd}" --select "${selectJavaProcessName}
fi

echo "************************************************* 6. Create a pipeline ***************************************************************"
rm -f tmp_in
mknod tmp_in p
exec 8<> tmp_in
${arthas_start_cmd} <&8 &

echo "********************************************* 7. Choose the java process *************************************************************"
sleep 1s
echo "
" >> tmp_in

echo "*********************************************** 8. Redefine the class ****************************************************************"
sleep 3s
echo "retransform $(pwd)/FrameController.class > $(pwd)/arthas-hot-swap-result" >> tmp_in
sleep 4s
echo "quit" >> tmp_in
sleep 2s

swapResult=$(cat $(pwd)/arthas-hot-swap-result | grep "success")
echo $swapResult
if [[ $swapResult != "" ]]
then
echo '
****************************************** 9. The following files were successfully hot deployed *************************** ****************
*****
***** FrameController.class
*****
********************************************************************************************************************************************
'
else
echo '
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 9. Failed to hot deployed the following files %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%
%%%%% FrameController.class
%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
'
cat $(pwd)/arthas-hot-swap-result
fi

3.2. 自定义脚本

按照这个流程,自定义写了一个脚本,去掉了上传文件服务器步骤,只需要把许替换的文件上传至服务器指定目录,启动脚本时指定项目包名称,即可完成指定项目多个class文件热替换

#热刷新class指定路径配置
updateClassPath="/tmp/replace"
#服务器上arthas路径
arthasPath="/home/cmp/.arthas/lib/3.6.7/arthas"
#入参 项目包名称,支持模糊匹配
projectName=$1

rm -f tmp_in
mknod tmp_in p
exec 8<> tmp_in
sh ${arthasPath}/as.sh --select $projectName <&8 &
echo "********************************************* Arthas HotSwap The Java Class *************************************************************"
sleep 1s
echo "
" >> tmp_in
sleep 3s
echo "开热加载......"
#遍历目录中的所有class文件
for file in ${updateClassPath}/*
do
    echo ${file}
    #如果file后缀是class 执行替换
    if [ "${file##*.}" = "class" ]; then
        #开始启动arthas项目
        echo "热加载${file}"
        echo "retransform ${file}" >> tmp_in
    fi
done
echo "quit" >> tmp_in

有关基于arthas热更新class脚本的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  3. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

  4. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  5. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  6. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  7. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  8. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  9. objective-c - 在设置 Cocoa Pods 和安装 Ruby 更新时出错 - 2

    我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U

  10. ruby - 确定 ruby​​ 脚本是否已经在运行 - 2

    有没有一种简单的方法可以判断ruby​​脚本是否已经在运行,然后适本地处理它?例如:我有一个名为really_long_script.rb的脚本。我让它每5分钟运行一次。当它运行时,我想看看之前运行的是否还在运行,然后停止第二个脚本的执行。有什么想法吗? 最佳答案 ps是一种非常糟糕的方法,并且可能会出现竞争条件。传统的Unix/Linux方法是将PID写入文件(通常在/var/run中)并在启动时检查该文件是否存在。例如pid文件位于/var/run/myscript.pid然后你会在运行程序之前检查它是否存在。有一些技巧可以避免

随机推荐