Shell脚本在while循环中调用esscs.sh报错:找不到主类a
问题描述
执行读取文件的Shell脚本时,调用esscs.sh返回错误:Error: Could not find or load main class a
有问题的脚本如下:
cd /u01/oracle/essbase/products/Essbase/EssbaseServer/bin/cli/ while read application; do if [[ $application = "" || $application = "#"* ]] then continue else ./esscs.sh login -user usr -password xxx -essbaseurl https://bla/essbase ./esscs.sh lcmexport -application $application fi done < /tmp/exportLCM_applications.txt
而以下脚本可正常运行:
cd /u01/oracle/essbase/products/Essbase/EssbaseServer/bin/cli/ ./esscs.sh login -user usr -password xxx -essbaseurl https://bla/essbase ./esscs.sh lcmexport -application hardcodedapp
esscs.sh是Oracle Essbase的命令行工具,内容如下:
#!/bin/sh export ERR_MSG_JAVA_REQUIRED="Install JDK8 and set JAVA_HOME variable to JDK8 installed location" if [ -z "$JAVA_HOME" ] then echo echo $ERR_MSG_JAVA_REQUIRED echo exit 1 fi export JAVA_VERSION=$("$JAVA_HOME/bin/java" -version 2>&1 | awk -F '"' '/version/ {print $2}') if [[ "$JAVA_VERSION" < "1.8" ]] then echo echo You are using older java version $JAVA_VERSION echo $ERR_MSG_JAVA_REQUIRED echo exit 1 fi export SCRIPT_DIRECTORY=$(dirname "$(readlink -f "$0")") cd "$SCRIPT_DIRECTORY" export CLI_HOME=. export REST_CLI_HOME=$CLI_HOME/lib export CLASSPATH=.:$REST_CLI_HOME/ess_rest_cli.jar:$REST_CLI_HOME/ess_es_server.jar:$REST_CLI_HOME/ess_japi.jar:$REST_CLI_HOME/ess_svp.jar:$REST_CLI_HOME/commons-cli.jar:$REST_CLI_HOME/commons-io.jar:$REST_CLI_HOME/jersey-client.jar:$REST_CLI_HOME/javax.ws.rs-api.jar:$REST_CLI_HOME/jersey-common.jar:$REST_CLI_HOME/hk2-utils.jar:$REST_CLI_HOME/hk2-apijar:$REST_CLI_HOME/javax.inject.jar:$REST_CLI_HOME/hk2-locator.jar:$REST_CLI_HOME/hk2-api.jar:$REST_CLI_HOME/javax-annotation-javax-annotation-api.jar:$REST_CLI_HOME/jackson-annotations.jar:$REST_CLI_HOME/jackson-core.jar:$REST_CLI_HOME/jackson-databind.jar:$REST_CLI_HOME/jackson-mapper-asl-1.9.2.jar:$REST_CLI_HOME/ojdl.jar:$REST_CLI_HOME/jersey-guava.jar:$REST_CLI_HOME/cglib.jar:$REST_CLI_HOME/jackson-core-asl-1.9.2.jar:$JAVA_HOME/db/lib/derby.jar:$REST_CLI_HOME/ojdbc8.jar:$REST_CLI_HOME/ess-platform-common.jar:$REST_CLI_HOME/datasource-model.jar:$REST_CLI_HOME/excel-core.jar:$REST_CLI_HOME/lz4-java.jar:$REST_CLI_HOME/avatica-core.jar:$REST_CLI_HOME/calcite-core.jar:$REST_CLI_HOME/calcite-linq4j.jar:$REST_CLI_HOME/protobuf-java.jar:$REST_CLI_HOME/janino.jar:$REST_CLI_HOME/json-path.jar:$REST_CLI_HOME/checker-qual.jar:$REST_CLI_HOME/jts-core.jar:$REST_CLI_HOME/commons-compiler.jar:$REST_CLI_HOME/guava.jar:$REST_CLI_HOME/failureaccess.jar:$REST_CLI_HOME/slf4j-api.jar:$REST_CLI_HOME/slf4j-nop.jar:$REST_CLI_HOME/commons-lang3.jar:$REST_CLI_HOME/ons.jar:$REST_CLI_HOME/oraclepki.jar:$REST_CLI_HOME/orai18n.jar:$REST_CLI_HOME/osdt_core.jar:$REST_CLI_HOME/osdt_cert.jar:$REST_CLI_HOME/simplefan.jar:$REST_CLI_HOME/ucp.jar:$REST_CLI_HOME/xdb6.jar:$REST_CLI_HOME/esscatalog-model.jar
问题原因及解决办法
原因
核心问题是while read循环通过标准输入重定向读取文件时,标准输入被文件占用。esscs.sh调用的Java程序或脚本内部可能隐式尝试读取标准输入,导致read命令提前获取到非预期内容,使得$application变量被错误赋值,最终传递给esscs.sh的参数异常,触发找不到主类的错误。
另外,原脚本中$application未加引号,若应用名称包含空格或特殊字符,会导致参数拆分错误,进一步加剧问题。
解决办法
1. 隔离循环的输入来源
使用文件描述符重定向,将文件读取绑定到非标准输入的描述符(如3),避免占用esscs.sh需要的标准输入:
cd /u01/oracle/essbase/products/Essbase/EssbaseServer/bin/cli/ while read -u3 application; do if [[ $application = "" || $application = "#"* ]] then continue else ./esscs.sh login -user usr -password xxx -essbaseurl https://bla/essbase ./esscs.sh lcmexport -application "$application" fi done 3< /tmp/exportLCM_applications.txt
2. 给变量添加引号
将$application改为"$application",防止应用名称含特殊字符时出现参数拆分错误,提升脚本健壮性。
3. 优化登录逻辑(可选)
原脚本每次循环都执行登录操作,而Essbase CLI的登录状态会保留在会话中,可将登录命令移到循环外,减少重复操作:
cd /u01/oracle/essbase/products/Essbase/EssbaseServer/bin/cli/ ./esscs.sh login -user usr -password xxx -essbaseurl https://bla/essbase while read -u3 application; do if [[ $application = "" || $application = "#"* ]] then continue else ./esscs.sh lcmexport -application "$application" fi done 3< /tmp/exportLCM_applications.txt
内容的提问来源于stack exchange,提问作者sebroux
相关产品推荐
相关产品推荐

