run.sh传递含空格的JVM参数报错:无法找到主类%l,求解决方案
解决Shell脚本中传递含空格JVM参数导致的主类找不到问题
这个问题我之前也踩过坑,本质是Shell脚本对空格的参数拆分逻辑在搞鬼。你遇到的Error: Could not find or load main class %l,是因为Shell把%h %l拆成了两个独立的参数:%h和%l,JVM误以为%l是你要运行的主类名,自然就报错了。而命令行直接运行正常,是因为你在命令行输入时,Shell会正确识别你手动维护的参数整体性(比如隐含的引号逻辑),但脚本里如果没做特殊处理,空格就会被当作参数分隔符。
下面给你几个靠谱的解决方案,按推荐程度排序:
1. 用数组存储JVM参数(最佳实践)
Bash数组可以完美处理带空格、特殊字符的参数,每个数组元素会被当作一个独立的参数传递,不会被拆分。比如:
#!/bin/bash # 定义JVM参数数组,每个元素是一个完整的参数项 JVM_ARGS=( "-Dsession.id=%h %l" # 带空格的参数直接作为数组元素 "-Xmx1024m" "-XX:+UseParallelGC" ) # 运行Java命令,注意数组展开时要用双引号包裹@符号 java "${JVM_ARGS[@]}" -jar your-application.jar
这种方式不仅解决了空格问题,后续维护参数也更清晰,不容易出错。
2. 给含空格的参数添加双引号
如果你的脚本里是直接拼接参数字符串,确保带空格的参数被双引号包裹。比如:
#!/bin/bash # 给带空格的JVM参数加上双引号(注意内部的引号要转义) JVM_ARGS="-Dsession.id=\"%h %l\" -Xmx512m" # 运行时也要把JVM_ARGS用双引号包裹,避免被拆分 java "$JVM_ARGS" -jar your-application.jar
不过这种方式如果参数多了容易搞混转义符号,不如数组直观。
3. 用eval执行命令(不推荐,仅作应急)
如果你的COMMAND_PATH是一个包含完整命令的字符串,直接运行会拆分参数,这时候可以用eval强制Shell按整体解析命令:
#!/bin/bash COMMAND_PATH="java -Dsession.id=\"%h %l\" -jar your-application.jar" eval "$COMMAND_PATH"
但要注意eval有安全风险,如果COMMAND_PATH包含不可信内容,可能会执行恶意命令,所以尽量不用。
额外调试建议
你可以在脚本开头加上set -x,开启Shell的调试模式,运行脚本时会输出每一步实际执行的命令,能直观看到参数是否被正确传递。比如:
#!/bin/bash set -x # 开启调试 JVM_ARGS=( "-Dsession.id=%h %l" "-Xmx512m" ) java "${JVM_ARGS[@]}" -jar your-application.jar
运行后会输出类似这样的内容,能清楚看到参数有没有被拆分:
+ java '-Dsession.id=%h %l' -Xmx512m -jar your-application.jar
内容的提问来源于stack exchange,提问作者Ahmet Karakaya
相关产品推荐
相关产品推荐

