简体   繁体   English

Bash变量扩展导致Java命令行中断

[英]Bash variable expansion causes Java commandline to break

I've been experiencing a strange issue the last couple of days while writing a shell script which executes Java (starting the JBoss AS). 最近几天,我在编写执行Java的Shell脚本(启动JBoss AS)时遇到了一个奇怪的问题。 I have a variable JAVA_OPTS that I am creating, and finally passing to the 'java' command. 我有一个正在创建的变量JAVA_OPTS,最后传递给“ java”命令。 When I hard code the values in JAVA_OPTS rather than using variable expansion, the java process executes normally. 当我用JAVA_OPTS硬编码值而不是使用变量扩展时,java进程会正常执行。 When I use variable expansion, I get errors from the java executable. 当我使用变量扩展时,我从Java可执行文件中得到错误。 Here is the relevant portions of the script: 这是脚本的相关部分:

SERVER="-server"
MEM_OPTS="-Xms512m -Xmx1024m"

case "$1" in
start)
    java "$SERVER" "$MEM_OPTS" $JAVA_OPTS \
    -classpath "${JBOSS_CLASSPATH}" \
    -Dorg.jboss.resolver.warning=true \
    -Dsun.rmi.dgc.client.gcInterval=3600000 \
    -Dsun.rmi.dgc.server.gcInterval=3600000 \
    -Djboss.server.name=${SERVICE_NAME} \
    -Djboss.server.base.dir=`dirname ${EC_APP_HOME}` \
    -Djboss.server.base.url=file://`dirname ${EC_APP_HOME}` \
    -Djboss.server.home.dir=${EC_APP_HOME} \
    -Djboss.server.home.url=file://${EC_APP_HOME} \
    org.jboss.Main >> out.log 2>&1 &

Executing this gives the following: 执行此操作将得到以下结果:

Invalid initial heap size: -Xms512m -Xmx1024m
Could not create the Java virtual machine.

However when I remove the variable expansion like so: 但是,当我像这样删除变量扩展时:

    java "$SERVER" -Xms512m -Xmx1024m $JAVA_OPTS \

java executes no problems. Java没有执行任何问题。 As an aside, when I include "-server" in the MEM_OPTS var, I get the error "unrecognized option". 顺便说一句,当我在MEM_OPTS变量中包含“ -server”时,出现错误“无法识别的选项”。

So obviously, there is something up with the variable expansion. 因此,显然,变量扩展有问题。 I've hexdump'd the script, and made sure there are no extra characters in the string, and verified that I'm using Unix line endings. 我已经对脚本进行了十六进制转储,并确保字符串中没有多余的字符,并确认我正在使用Unix行尾。 I've also reproduced the problem on two different linux machines, albeit both running the same version of ubuntu (one 32bit, the other 64bit). 我还在两台不同的linux机器上重现了该问题,尽管它们都运行相同版本的ubuntu(一个32位,另一个64位)。

EDIT: I get the same result with all forms of variable substitution: $MEM_OPTS, ${MEM_OPTS}, "${MEM_OPTS}" 编辑:使用所有形式的变量替换都会得到相同的结果:$ MEM_OPTS,$ {MEM_OPTS},“ $ {MEM_OPTS}”

Any ideas? 有任何想法吗?

When you use "$MEM_OPTS" , you're passing -Xms512m -Xmx1024m as a single option. 当您使用"$MEM_OPTS" ,您将-Xms512m -Xmx1024m作为单个选项传递。

Try this instead: 尝试以下方法:

java "$SERVER" $MEM_OPTS $JAVA_OPTS \

A good guide to variable substitution and quoting with examples: http://tldp.org/LDP/abs/html/varsubn.html 很好的变量替换和引用示例指南: http : //tldp.org/LDP/abs/html/varsubn.html

I am not 100% sure about the semantics of the quotes, but "$MEM_OPTS" may create a single argument "-Xms512m -Xmx1024m" , whereas the JVM needs to see two seperate arguments. 我不确定引号的语义,但是"$MEM_OPTS"可能会创建一个参数"-Xms512m -Xmx1024m" ,而JVM需要查看两个单独的参数。 Can you try without the quotes? 您可以不加引号尝试吗?

java $SERVER $MEM_OPTS $JAVA_OPTS 

认为如果删除$ MEM_OPTS周围的引号,它应该起作用,因为引号告诉bash将扩展内容作为单个令牌参数传递给execv()

My mistake - I was setting IFS to "\\n" only in a script I sourced in, functions.sh. 我的错误-我仅在源于functions.sh的脚本中将IFS设置为“ \\ n”。 I was never resetting the IFS to "\\n\\t ", so the variables were not split on spaces. 我从来没有将IFS重置为“ \\ n \\ t”,因此变量不会在空格上分割。

Thanks for the responses! 感谢您的回复!

It should be a simple matter of changing: 更改应该很简单:

java "$SERVER" "$MEM_OPTS" $JAVA_OPTS \

to: 至:

java "$SERVER" $MEM_OPTS $JAVA_OPTS \

so that the memory options are passed as two arguments. 这样内存选项将作为两个参数传递。

But, since you say that doesn't work (?), please try the following. 但是,由于您说那行不通(?),请尝试以下操作。

A) Create a shell script fakejava.sh containing: A)创建一个包含以下内容的shell脚本fakejava.sh

#!/usr/bin/bash
echo $#
while [[ $# -ne 0 ]] ; do
    echo "    [$1]"
done

(you may need to alter that first line if your bash is somewhere else: use which bash to figure out where). (如果您的bash在其他位置,则可能需要更改第一行:使用which bash找出位置)。

B) Set its permissions correctly: B)正确设置其权限:

chmod 700 fakejava.sh

C) Replace your entire java command with: C)将整个java命令替换为:

./fakejava.sh "$SERVER" $MEM_OPTS $JAVA_OPTS xx

and see how many arguments there actually are. 看看实际上有多少个论点。 I get: 我得到:

5
    [-server]
    [-arg1]
    [-arg2]
    [none]
    [xx]

from the controlling script: 从控制脚本中:

#!/usr/bin/bash
JAVA_OPTS="none"
SERVER="-server"
MEM_OPTS="-arg1 -arg2"
./fakejava.sh "$SERVER" $MEM_OPTS $JAVA_OPTS xx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM