1

I'm getting shellcheck suggestion SC2806 i.e. Double quote to prevent globbing and word splitting for $JAVA_OPTS.

When I apply that to my code java $JAVA_OPTS -Dhttps.proxyHost=%PROXY_HOST%

I get the 503 Error Back-end server busy error. The ec2 instance activity reports that the instance health check failed.

But when I don't use "" to $JAVA_OPTS, then it works and I get 200 OK response and everything works.

when I echoed $JAVA_OPTS it echoed as empty.

What could be the reason for this?

SK16
  • 623
  • 8
  • 17
  • 1
    You did not specify how you defined `JAVA_OPTS`, but if it contains a bunch of options for Java, having it as a string is the wrong approach anyway. You have several individual options, some may contain a space and some don't. In this case `JAVA_OPTS` should be defined as array with one element for each Java-parameter. The correct expansion would then be `"${JAVA_OPTS[@]}"`. – user1934428 Jul 05 '23 at 08:47
  • _when I echoed $JAVA_OPTS it echoed as empty._ : This means that you have forgotten to set this variable, or that you have set it to an empty value. – user1934428 Jul 05 '23 at 08:47
  • @user1934428 Unfortunately `JAVA_OPTS` is almost certainly an environment variable (both because it’s all-caps, and because that name is a conventional, specific environment variable), and environment variables can’t be arrays. – Konrad Rudolph Jul 06 '23 at 07:11
  • @KonradRudolph: I don't have much experience with Java, but this raises some questions: (1) If it is a variable with predefined meaning for Java, why is the OP passing it on the command line? It would be sufficient then to just export ist. (2) If Java expects the options in this variable, which escape mechanism does Java define for the case that we have embedded spaces? (3) If `JAVA_OPTS` is predefined, the OP could simply use a different name (say: `java_opts`) and follow his approach with the array; I think this would be the cleanest way. – user1934428 Jul 06 '23 at 08:50
  • @user1934428 (1) It’s predefined in the sense that there’s a widespread convention around using it, and it is used automatically [by several widely used third-party utilities](https://stackoverflow.com/a/12335001/1968), but it is not predefined *by Java*, and the `java` command line utility does not know about it. (3) I’m assuming that OP gets the variable from elsewhere rather than defining it themselves in the current script. Otherwise I agree that using an array would be (vastly) superior. – Konrad Rudolph Jul 06 '23 at 09:52

2 Answers2

3

The other answer explains what causes the issue.

Here’s how to fix it: instead of passing $JAVA_OPTS (either quoted or unquoted) to java, pass ${JAVA_OPTS:+"$JAVA_OPTS"}. This will cause the parameter expansion only if it is non-empty. If $JAVA_OPTS is empty, no expansion will be passed to the command.

See the documentation for more information about the :+ expansion.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • Note: This answer only works if passing the entire `JAVA_OPTS` as a single string is valid. Often times arguments can't be crammed into a single string like that, in which case you need to refactor your arguments list to use an array instead of a string. The unquoted `${JAVA_OPTS}` sorta-kinda works because it can undergo word splitting to create multiple arguments, but gets flagged by shellcheck because it can't handle arguments that contain certain characters like whitespace. `"${JAVA_OPTS}"` will fail if the contents need to be passed separately. – tjm3772 Jul 05 '23 at 19:49
  • @tjm3772 That’s a good comment in general. In the context of this specific environment variable we *know* that this is the case by convention. — In general, a (much!) better answer in Bash would be to declare an array parameter and pass that as `"${java_opts[@]}"`, but unfortunately environment variables can’t be arrays. – Konrad Rudolph Jul 06 '23 at 07:10
0

So if JAVA_HOME is not set (which it looks like it isn’t), then what bash expands the command to differs depending on how you provide it. For example: java $JAVA_HOME --version

expands to:

java --version

In this case, bash ends up passing in a single argument to java which will be --version (it ignores any extra spaces) and this works just fine.

However, contrast that to:

java "$JAVA_HOME" --version

this expands to:

java "" --version

So, in this case, bash will pass TWO arguments to java: an empty string and --version.

The first parameter to Java is supposed to be the class name to execute and you can see it complain if you try to run this command:

java "" --version

Error: Could not find or load main class  Caused by: java.lang.ClassNotFoundException:

So, TLDR is, that the quotes matter if JAVA_OPTS is not set to anything.

SK16
  • 623
  • 8
  • 17