长话短说

长话短说

这可能是重复的,但我发现答案的最初问题并没有解决问题。

问题的另一个重写。

我有这个Java应用程序:

public static void main(final String[] args) {
    System.out.println("DEBUG: arguments passed to the main - " + Arrays.toString(args));
    System.exit(new TaskRunner().run(args));
}

如果我直接用两个参数调用代码:

$ nohup ${JAVA_HOME}/bin/java -cp /opt/fxudply/fxcal-client-jar/current/lib:/opt/fxudply/fxcal-client-jar/current/lib/*:/opt/fxudply/fxcal-config/current/wib-config:/opt/fxudply/fxcal-config/current/wib-config/* wib.runner.TaskRunner -taskExtRef "QUOTES_UPLOAD IPV - EOD Rates Input - Commodities Volatilities" > /opt/sw/calypso/logs/taskrunner/log.direct.log 2>&1

它打印

[TaskRunner] DEBUG: : arguments passed to the main - [-taskExtRef, QUOTES_UPLOAD IPV - EOD Rates Input - Commodities Volatilities]

这正是我所期望的。但如果我写这个 shell 脚本 ( startScheduledTask.sh):

NOW_DATE=`date '+%Y%m%d%H%M%S'`

nohup ${JAVA_HOME}/bin/java -cp some:classpath:values package.name.classname "$@"   > /opt/random/path/tplogs/classname/${aVariableLogName}.${NOW_DATE}.log 2>&1

并将其运行为

$ ./startScheduledTask.sh -taskExtRef "QUOTES_UPLOAD IPV - EOD Rates Input -   Commodities Volatilities" &

我得到这个输出:

[TaskRunner] DEBUG: : arguments passed to the main - [-taskExtRef, QUOTES_UPLOAD, IPV, -, EOD, Rates, Input, -, Commodities, Volatilities]

(即,第二个参数被分解为九个参数,因为它包含八个空格)。因此我认为剧本有问题。

我该如何解决?

答案1

当 shell 解析命令行时,它会删除引号,但会记住它们所暗示的文本结构。 (这是一种严重的过于简单化;参见重击(1)或者外壳命令语言了解更多详细信息。)例如,命令行输入

-blah apple -secondfruit "green banana" -some more

使 shell 识别六个单词或标记:

  1. -blah
  2. apple
  3. -secondfruit
  4. green banana
  5. -some
  6. more

它将被存储在内存中

-blahⓧappleⓧ-secondfruitⓧgreen bananaⓧ-someⓧmoreⓧ

其中表示空字节。有时这会显示或报告为

-blah apple -secondfruit green banana -some more

所以你可能会认为引号只是被忽略了,而你有七个单词,而事实上,你已经有了你想要的。

笔记:

上式中,代表空字节。我在这里描述的是标准shell 参数解析处理。如果您输入

ls -l fruit.sh "I came here for an argument" startScheduledTask.sh

/bin/ls使用字符串调用程序

lsⓧ-lⓧfruit.shⓧI came here for an argumentⓧstartScheduledTask.shⓧ

在内存中,这被解释为

  • argv[0] =ls
  • argv[1] =-l
  • argv[2] =fruit.sh
  • argv[3] =I came here for an argument
  • argv[4] =startScheduledTask.sh

完全相同的过程如果你是的话就会发生

  1. java直接在主交互式 shell 中输入命令,
  2. 执行javashell 脚本中的命令,或者
  3. ./startScheduledTask.sh 通过直接在主交互式 shell 中键入命令来运行 shell 脚本,

所以这不是问题。  任何无法处理其参数由空字符分隔的程序 无法在 Unix 和 Linux 中工作。

长话短说

你的第一个命令是正确的。  "$@"给你你想要的;这是 shell 脚本将其参数传递给它调用的程序的正确方法。如果您将调试代码添加到程序中以循环遍历其参数,将每个参数打印在新行和/或括号中(但不是全部打印在一行上,仅用空格分隔),您将看到正在"$@"传递六个参数到程序。


好吧,还有更多:

  • 你的类路径有星号(*s) 在里面?真的吗?我对 Java 有点不太熟悉,但这对我来说似乎很奇怪。请仔细检查您的系统是否正确执行了该操作。但是,如果当您“直接”输入带有星号的类路径(即直接进入您的主 shell;您的主要交互式 shell;您的登录 shell)时它可以正常工作,那么那就是大概不是问题。

    但无论如何,请幽默我并将该字符串放入引号中。

  • 你的问题太复杂了。当你建造一架飞机时,你不会建造整个飞机然后尝试驾驶它。然后,当它不飞时,你不会退后一步问:“飞机出了什么问题?”不,你要分块测试它。你需要简化。

    • 停止在后台运行它。
    • 别说了nohup
    • 停止重定向输出。
    • 不要在问题中显示 42 个字符的长 shell 提示符。
    • 你的问题是关于一个参数中包含空格,所以不要将其删除,但它不必是 60 个字符长且包含 8 个空格。  green banana是一个伟大的测试值。
    • 尝试使用程序的参数不是以。。。开始-(短跑)。
    • 甚至可以注释掉new TaskRunner().run(args)程序的一部分,只留下 DEBUG 和System.exit(0);.

    都不是应该做出改变。但它们会让人分心,让人很难看清重要的事情。如果您可以在最小的测试配置中演示该问题,我们就可以排除与该问题相关的所有其他事情。但是,如果删除不相关的内容后问题消失了,那么问题可能是其中之一引起的。

    另外,请停止在问题中混合假/测试数据和真实数据(即水果和任务)。

  • 请编写这个脚本(称之为fruity.sh):

    #!/bin/sh
    
                    # classpath
    CP="/opt/fxudply/fxcal-client-jar/current/lib:/opt/fxudply/fxcal-client-jar/current/lib/*:/opt/fxudply/fxcal-config/current/wib-config:/opt/fxudply/fxcal-config/current/wib-config/*"
                    # package.name.classname
    PC=wib.runner.TaskRunner
    
    "$JAVA_HOME"/bin/java  -cp "$CP"  "$PC"  "$@"
    

    并运行

    ./fruity.sh taskExtRef "green banana"
    

    如果调试说

    …[taskExtRef, green banana]
    

    那么它"$@"工作正常,问题出在脚本的其他地方。尝试找到它。一次进行一项更改,看看行为如何变化。如果您无法弄清楚,我们也许可以帮助您,但前提是您向我们展示脚本中的部分内容导致问题。 

    但如果调试说

    …[taskExtRef, green, banana]
    

    然后让我们知道。

相关内容