Gatling包装Shell脚本执行报ClassNotFound错误排查
问题:Shell脚本执行Gatling压测时JVM参数被误识别为主类
问题背景
编写Shell脚本批量执行Gatling压测,脚本中调用gatling.sh并通过-erjo参数传递JVM系统属性,但执行时出现ClassNotFoundException,系统将JVM选项误当作主类处理。直接复制脚本打印的命令到终端执行却能正常运行。
错误信息
GATLING_HOME is set to /home/ec2-user/gatling-charts-highcharts-bundle-3.10.3 20:00:35.108 [DEBUG] i.g.c.ZincCompiler$ - [zinc] IncrementalCompile ----------- 20:00:35.116 [DEBUG] i.g.c.ZincCompiler$ - IncrementalCompile.incrementalCompile 20:00:35.121 [DEBUG] i.g.c.ZincCompiler$ - previous = Stamps for: 1 products, 1 sources, 2 libraries 20:00:35.122 [DEBUG] i.g.c.ZincCompiler$ - current source = Set(/home/ec2-user/perf-test/simulation/com/contoso/simulation/OnlineTableSimulation.java) 20:00:35.163 [DEBUG] i.g.c.ZincCompiler$ - > initialChanges = InitialChanges(Changes(added = Set(), removed = Set(), changed = Set(), unmodified = ...),Set(),Set(),API Changes: Set()) 20:00:35.167 [DEBUG] i.g.c.ZincCompiler$ - No changes 20:00:35.256 [DEBUG] i.g.c.ZincCompiler$ - Compilation successful Error: Could not find or load main class "-Dconcurrent_users=4000 Caused by: java.lang.ClassNotFoundException: "-Dconcurrent_users=4000
原因分析
脚本中给-erjo、-s、-rf、-rd等参数添加了多余的转义双引号(比如-erjo \"\"-Dconcurrent_users=${users}...\"\"),导致这些引号被作为参数的一部分传递给gatling.sh。当gatling.sh通过"$@"将参数转发给Java命令时,这些多余的引号会被解析成参数内容,Java错误地将"-Dconcurrent_users=4000当作主类名,从而抛出异常。
而直接在终端执行打印的命令时,Shell会自动处理这些引号,将其作为参数边界而非内容,所以能正常运行。
解决方案
移除所有参数值周围的转义双引号,直接传递参数即可。Shell会自动处理包含空格的参数,无需额外添加转义引号。
修正后的脚本片段
修改do_run函数中的命令打印和执行部分:
echo JAVA_HOME=/usr/lib/jvm/java-11-amazon-corretto.x86_64 \ ${HOME}/gatling-charts-highcharts-bundle-3.10.3/bin/gatling.sh \ -rm local \ -s "OnlineTableSimulation" \ -sf "/home/ec2-user/perf-test/simulation" \ -rf "${HOME}/results/${instance}/${users}" \ -erjo "-Dconcurrent_users=${users} -Dendpoint=${endpoint} -Dtoken=${token}" \ -rd "${instance} instance, ${users} concurrent users" export JAVA_HOME=/usr/lib/jvm/java-11-amazon-corretto.x86_64 echo echo "Running simulation:" echo ${HOME}/gatling-charts-highcharts-bundle-3.10.3/bin/gatling.sh \ -erjo "-Dconcurrent_users=${users} -Dendpoint=${endpoint} -Dtoken=${token}" \ -rm local \ -s "OnlineTableSimulation" \ -sf "/home/ec2-user/perf-test/simulation" \ -rf "${HOME}/results/${instance}/${users}" \ -rd "${instance} instance, ${users} concurrent users"
关键修正点
- 去掉
-erjo、-s、-rf、-rd参数值外层的\"\",只保留一层双引号包裹带空格或变量的参数 - 确保变量(如
${users}、${endpoint})在双引号内正确展开,同时Shell能识别参数边界
内容的提问来源于stack exchange,提问作者feroze
相关产品推荐
相关产品推荐

