Skip to content

Instantly share code, notes, and snippets.

@julianxhokaxhiu
Last active July 21, 2021 20:08
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save julianxhokaxhiu/66d6337d5091d0abacb894e73909dcea to your computer and use it in GitHub Desktop.
Save julianxhokaxhiu/66d6337d5091d0abacb894e73909dcea to your computer and use it in GitHub Desktop.
How to pass system properties with spaces in Java within your Bash scripts
#!/usr/bin/env bash
######################################################################################################################
# This script is a solution of when you want to pass Java options when they do come to the script as environment
# variable, or when you declare them inside a variable, using quotes. When you do so, you may obtain from the Java
# process an error that looks like this:
#
# $ ./java.sh
# Error: Could not find or load main class ...
#
# This usually means that your Bash environment split the arguments of your command by space, and this break the
# overall evaluation of the command to be execute. One possible solution can be the `eval`, although this brings
# with it also a security issue. So the other only option is to use Array notation.
#
# This script will serve the purpose of using this last scenario ensuring you have no potential security issue in
# your script.
######################################################################################################################
add_java_options() {
# Required to preserve the script integrity
SAVEIFS=$IFS
# Use a special character to split the string
IFS="|"
# Trim spaces around
JAVA_OPTIONS=$(echo $JAVA_OPTIONS | xargs)
# Ensure there is a space at the beginning so we don't need to check for - or not on each item later on
in_options=" $JAVA_OPTIONS"
# Split the string...
in_options=${in_options//\ \-/\|}
# ...and remove the first separator in order to not have a first item in array that is empty...
in_options=${in_options#"|"}
# ...finally dump the split items into an array
array_options=($in_options)
# Restore the IFS, we're done here
IFS=$SAVEIFS
# Add each item in the array inside of JAVA_CMD
for (( i=0; i<${#array_options[@]}; i++ ))
do
_arg=$(echo "-${array_options[$i]}" | xargs)
JAVA_CMD+=("$_arg")
done
}
# Your custom options here
JAVA_OPTIONS="-Xms2G -Dprop=val -Danotherprop=\"a special value here that contains spaces, remember to use quotes around it\""
# The ONLY correct way to attach custom parameters to the java binary including system properties with spaces
JAVA_CMD=("java")
add_java_options
# Feel free to use any other parameter here to run your Java application, remember that for each "space" your would type in your terminal it correspongs to a new item in the array
JAVA_CMD+=("-jar")
JAVA_CMD+=("path/to/file.jar")
# Finally run the whole command inside the bash environment
exec "${JAVA_CMD[@]}"
@julianxhokaxhiu
Copy link
Author

julianxhokaxhiu commented Aug 29, 2019

If you want to test the script, this is a small Java application that you can build yourself:

import java.util.Properties;

public class PrintSystemProperties {
    public static void main(String[] args) {
        Properties properties = System.getProperties();
        properties.forEach((k, v) -> System.out.println(k + ":" + v));
    }
}

How to build:

#!/usr/bin/env bash
set -e

APP="PrintSystemProperties"

javac ${APP}.java
jar cfe ${APP}.jar ${APP} ${APP}.class

@solry
Copy link

solry commented Feb 14, 2021

This was super helpful, thanks for publishing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment