Skip to content

Commit

Permalink
Introduce ES_JAVA_HOME (#68954)
Browse files Browse the repository at this point in the history
This commit introduces a dedicated envirnoment variable ES_JAVA_HOME to
determine the JDK used to start (if not using the bundled JDK). This
environment variable will replace JAVA_HOME. The reason that we are
making this change is because JAVA_HOME is a common environment variable
and sometimes users have it set in their environment from other JDK
applications that they have installed on their system. In this case,
they would accidentally end up not using the bundled JDK despite their
intentions. By using a dedicated environment variable specific to
Elasticsearch, we avoid this potential for conflict. With this commit,
we introduce the new environment variable, and deprecate the use of
JAVA_HOME. We will remove support for JAVA_HOME in a future commit.
  • Loading branch information
jasontedor committed Feb 17, 2021
1 parent 16a1662 commit 79e8aae
Show file tree
Hide file tree
Showing 19 changed files with 126 additions and 57 deletions.
2 changes: 2 additions & 0 deletions .ci/os.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ else
fi

sudo bash -c 'cat > /etc/sudoers.d/elasticsearch_vars' << SUDOERS_VARS
Defaults env_keep += "ES_JAVA_HOME"
Defaults env_keep += "JAVA_HOME"
Defaults env_keep += "SYSTEM_JAVA_HOME"
SUDOERS_VARS
Expand All @@ -63,6 +64,7 @@ sudo mkdir -p /elasticsearch/qa/ && sudo chown jenkins /elasticsearch/qa/ && ln
sudo -E env \
PATH=$BUILD_JAVA_HOME/bin:`sudo bash -c 'echo -n $PATH'` \
RUNTIME_JAVA_HOME=`readlink -f -n $RUNTIME_JAVA_HOME` \
--unset=ES_JAVA_HOME \
--unset=JAVA_HOME \
SYSTEM_JAVA_HOME=`readlink -f -n $RUNTIME_JAVA_HOME` \
./gradlew -g $HOME/.gradle --scan --parallel --continue $@
Expand Down
1 change: 1 addition & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,7 @@ def sh_install_deps(config,
ensure expect
cat \<\<SUDOERS_VARS > /etc/sudoers.d/elasticsearch_vars
Defaults env_keep += "ES_JAVA_HOME"
Defaults env_keep += "JAVA_HOME"
Defaults env_keep += "SYSTEM_JAVA_HOME"
SUDOERS_VARS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ private void runElasticsearchBinScript(String tool, CharSequence... args) {

private Map<String, String> getESEnvironment() {
Map<String, String> defaultEnv = new HashMap<>();
getRequiredJavaHome().ifPresent(javaHome -> defaultEnv.put("JAVA_HOME", javaHome));
getRequiredJavaHome().ifPresent(javaHome -> defaultEnv.put("ES_JAVA_HOME", javaHome));
defaultEnv.put("ES_PATH_CONF", configFile.getParent().toString());
String systemPropertiesString = "";
if (systemProperties.isEmpty() == false) {
Expand Down
16 changes: 11 additions & 5 deletions distribution/src/bin/elasticsearch-env
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,29 @@ ES_HOME=`dirname "$ES_HOME"`
ES_CLASSPATH="$ES_HOME/lib/*"

# now set the path to java
if [ ! -z "$JAVA_HOME" ]; then
if [ ! -z "$ES_JAVA_HOME" ]; then
JAVA="$ES_JAVA_HOME/bin/java"
JAVA_TYPE="ES_JAVA_HOME"
elif [ ! -z "$JAVA_HOME" ]; then
# fallback to JAVA_HOME
echo "warning: usage of JAVA_HOME is deprecated, use ES_JAVA_HOME" >&2
JAVA="$JAVA_HOME/bin/java"
JAVA_TYPE="JAVA_HOME"
else
# use the bundled JDK (default)
if [ "$(uname -s)" = "Darwin" ]; then
# macOS has a different structure
JAVA="$ES_HOME/jdk.app/Contents/Home/bin/java"
else
JAVA="$ES_HOME/jdk/bin/java"
fi
JAVA_TYPE="bundled jdk"
JAVA_TYPE="bundled JDK"
fi

if [ ! -x "$JAVA" ]; then
echo "could not find java in $JAVA_TYPE at $JAVA" >&2
exit 1
fi
echo "could not find java in $JAVA_TYPE at $JAVA" >&2
exit 1
fi

# do not let JAVA_TOOL_OPTIONS slip in (as the JVM does by default)
if [ ! -z "$JAVA_TOOL_OPTIONS" ]; then
Expand Down
19 changes: 13 additions & 6 deletions distribution/src/bin/elasticsearch-env.bat
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,23 @@ if "%1" == "nojava" (
exit /b
)

rem compariing to empty string makes this equivalent to bash -v check on env var
rem comparing to empty string makes this equivalent to bash -v check on env var
rem and allows to effectively force use of the bundled jdk when launching ES
rem by setting JAVA_HOME=
if "%JAVA_HOME%" == "" (
set JAVA="%ES_HOME%\jdk\bin\java.exe"
set "JAVA_HOME=%ES_HOME%\jdk"
set JAVA_TYPE=bundled jdk
) else (
if defined ES_JAVA_HOME (
set JAVA="%ES_JAVA_HOME%\bin\java.exe"
set JAVA_TYPE=ES_JAVA_HOME
) else if defined JAVA_HOME (
rem fallback to JAVA_HOME
echo "warning: usage of JAVA_HOME is deprecated, use ES_JAVA_HOME" >&2
set JAVA="%JAVA_HOME%\bin\java.exe"
set "ES_JAVA_HOME=%JAVA_HOME%"
set JAVA_TYPE=JAVA_HOME
) else (
rem use the bundled JDK (default)
set JAVA="%ES_HOME%\jdk\bin\java.exe"
set "ES_JAVA_HOME=%ES_HOME%\jdk"
set JAVA_TYPE=bundled JDK
)

if not exist !JAVA! (
Expand Down
12 changes: 6 additions & 6 deletions distribution/src/bin/elasticsearch-service.bat
Original file line number Diff line number Diff line change
Expand Up @@ -88,20 +88,20 @@ goto:eof

:doInstall
echo Installing service : "%SERVICE_ID%"
echo Using JAVA_HOME (%ARCH%): "%JAVA_HOME%"
echo Using ES_JAVA_HOME (%ARCH%): "%ES_JAVA_HOME%"

rem Check JVM server dll first
if exist "%JAVA_HOME%\jre\bin\server\jvm.dll" (
if exist "%ES_JAVA_HOME%\jre\bin\server\jvm.dll" (
set JVM_DLL=\jre\bin\server\jvm.dll
goto foundJVM
)

rem Check 'server' JRE (JRE installed on Windows Server)
if exist "%JAVA_HOME%\bin\server\jvm.dll" (
if exist "%ES_JAVA_HOME%\bin\server\jvm.dll" (
set JVM_DLL=\bin\server\jvm.dll
goto foundJVM
) else (
echo JAVA_HOME ("%JAVA_HOME%"^) points to an invalid Java installation (no jvm.dll found in "%JAVA_HOME%\jre\bin\server" or "%JAVA_HOME%\bin\server"^). Exiting...
echo ES_JAVA_HOME ("%ES_JAVA_HOME%"^) points to an invalid Java installation (no jvm.dll found in "%ES_JAVA_HOME%\jre\bin\server" or "%ES_JAVA_HOME%\bin\server"^). Exiting...
goto:eof
)

Expand Down Expand Up @@ -207,7 +207,7 @@ if not "%SERVICE_USERNAME%" == "" (
set SERVICE_PARAMS=%SERVICE_PARAMS% --ServiceUser "%SERVICE_USERNAME%" --ServicePassword "%SERVICE_PASSWORD%"
)
)
"%EXECUTABLE%" //IS//%SERVICE_ID% --Startup %ES_START_TYPE% --StopTimeout %ES_STOP_TIMEOUT% --StartClass org.elasticsearch.bootstrap.Elasticsearch --StartMethod main ++StartParams --quiet --StopClass org.elasticsearch.bootstrap.Elasticsearch --StopMethod close --Classpath "%ES_CLASSPATH%" --JvmMs %JVM_MS% --JvmMx %JVM_MX% --JvmSs %JVM_SS% --JvmOptions %OTHER_JAVA_OPTS% ++JvmOptions %ES_PARAMS% %LOG_OPTS% --PidFile "%SERVICE_ID%.pid" --DisplayName "%SERVICE_DISPLAY_NAME%" --Description "%SERVICE_DESCRIPTION%" --Jvm "%JAVA_HOME%%JVM_DLL%" --StartMode jvm --StopMode jvm --StartPath "%ES_HOME%" %SERVICE_PARAMS% ++Environment HOSTNAME="%%COMPUTERNAME%%"
"%EXECUTABLE%" //IS//%SERVICE_ID% --Startup %ES_START_TYPE% --StopTimeout %ES_STOP_TIMEOUT% --StartClass org.elasticsearch.bootstrap.Elasticsearch --StartMethod main ++StartParams --quiet --StopClass org.elasticsearch.bootstrap.Elasticsearch --StopMethod close --Classpath "%ES_CLASSPATH%" --JvmMs %JVM_MS% --JvmMx %JVM_MX% --JvmSs %JVM_SS% --JvmOptions %OTHER_JAVA_OPTS% ++JvmOptions %ES_PARAMS% %LOG_OPTS% --PidFile "%SERVICE_ID%.pid" --DisplayName "%SERVICE_DISPLAY_NAME%" --Description "%SERVICE_DESCRIPTION%" --Jvm "%ES_JAVA_HOME%%JVM_DLL%" --StartMode jvm --StopMode jvm --StartPath "%ES_HOME%" %SERVICE_PARAMS% ++Environment HOSTNAME="%%COMPUTERNAME%%"

if not errorlevel 1 goto installed
echo Failed installing '%SERVICE_ID%' service
Expand All @@ -219,7 +219,7 @@ echo The service '%SERVICE_ID%' has been installed.
goto:eof

:err
echo JAVA_HOME environment variable must be set!
echo ES_JAVA_HOME environment variable must be set!
pause
goto:eof

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/setup.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ https://openjdk.java.net[OpenJDK] from the JDK maintainers (GPLv2+CE)
within each distribution. The bundled JVM is the recommended JVM and
is located within the `jdk` directory of the Elasticsearch home directory.

To use your own version of Java, set the `JAVA_HOME` environment variable.
To use your own version of Java, set the `ES_JAVA_HOME` environment variable.
If you must use a version of Java that is different from the bundled JVM,
we recommend using a link:/support/matrix[supported]
https://www.oracle.com/technetwork/java/eol-135779.html[LTS version of Java].
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/setup/install/deb.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ locations for a Debian-based system:

| jdk
| The bundled Java Development Kit used to run Elasticsearch. Can
be overridden by setting the `JAVA_HOME` environment variable
be overridden by setting the `ES_JAVA_HOME` environment variable
in `/etc/default/elasticsearch`.
| /usr/share/elasticsearch/jdk
d|
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/setup/install/rpm.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ locations for an RPM-based system:

| jdk
| The bundled Java Development Kit used to run Elasticsearch. Can
be overridden by setting the `JAVA_HOME` environment variable
be overridden by setting the `ES_JAVA_HOME` environment variable
in `/etc/sysconfig/elasticsearch`.
| /usr/share/elasticsearch/jdk
d|
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/setup/install/sysconfig-file.asciidoc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[horizontal]
`JAVA_HOME`::
`ES_JAVA_HOME`::

Set a custom Java path to be used.

Expand Down
18 changes: 9 additions & 9 deletions docs/reference/setup/install/zip-windows.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -120,24 +120,24 @@ The commands available are:

`manager`:: Start a GUI for managing the installed service

The name of the service and the value of `JAVA_HOME` will be made available during install:
The name of the service and the value of `ES_JAVA_HOME` will be made available during install:

["source","sh",subs="attributes"]
--------------------------------------------------
c:\elasticsearch-{version}{backslash}bin>elasticsearch-service.bat install
Installing service : "elasticsearch-service-x64"
Using JAVA_HOME (64-bit): "c:\jvm\jdk1.8"
Using ES_JAVA_HOME (64-bit): "c:\jvm\jdk1.8"
The service 'elasticsearch-service-x64' has been installed.
--------------------------------------------------

NOTE: While a JRE can be used for the Elasticsearch service, due to its use of a client VM (as opposed to a server JVM which offers better performance for long-running applications) its usage is discouraged and a warning will be issued.

NOTE: The system environment variable `JAVA_HOME` should be set to the path to
the JDK installation that you want the service to use. If you upgrade the JDK,
you are not required to the reinstall the service but you must set the value of
the system environment variable `JAVA_HOME` to the path to the new JDK
installation. However, upgrading across JVM types (e.g. JRE versus SE) is not
supported, and does require the service to be reinstalled.
NOTE: The system environment variable `ES_JAVA_HOME` should be set to the path
to the JDK installation that you want the service to use. If you upgrade the
JDK, you are not required to the reinstall the service but you must set the
value of the system environment variable `ES_JAVA_HOME` to the path to the new
JDK installation. However, upgrading across JVM types (e.g. JRE versus SE) is
not supported, and does require the service to be reinstalled.

[[windows-service-settings]]
[discrete]
Expand Down Expand Up @@ -167,7 +167,7 @@ The Elasticsearch service can be configured prior to installation by setting the

The description of the service. Defaults to `Elasticsearch <version> Windows Service - https://elastic.co`.

`JAVA_HOME`::
`ES_JAVA_HOME`::

The installation directory of the desired JVM to run the service under.

Expand Down
1 change: 1 addition & 0 deletions modules/reindex/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ if (Os.isFamily(Os.FAMILY_WINDOWS)) {
dependsOn unzip
executable = "${BuildParams.runtimeJavaHome}/bin/java"
env 'CLASSPATH', "${-> project.configurations.oldesFixture.asPath}"
// old versions of Elasticsearch need JAVA_HOME
env 'JAVA_HOME', jdks.legacy.javaHomePath
args 'oldes.OldElasticsearch',
baseDir,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public void test20PluginsListWithNoPlugins() throws Exception {

public void test30MissingBundledJdk() throws Exception {
final Installation.Executables bin = installation.executables();
sh.getEnv().remove("JAVA_HOME");
sh.getEnv().remove("ES_JAVA_HOME");

final Path relocatedJdk = installation.bundledJdk.getParent().resolve("jdk.relocated");

Expand All @@ -74,7 +74,7 @@ public void test30MissingBundledJdk() throws Exception {
// ask for elasticsearch version to quickly exit if java is actually found (ie test failure)
final Result runResult = sh.runIgnoreExitCode(bin.elasticsearch.toString() + " -v");
assertThat(runResult.exitCode, is(1));
assertThat(runResult.stderr, containsString("could not find java in bundled jdk"));
assertThat(runResult.stderr, containsString("could not find java in bundled JDK"));
} finally {
if (distribution().hasJdk) {
mv(relocatedJdk, installation.bundledJdk);
Expand All @@ -84,21 +84,20 @@ public void test30MissingBundledJdk() throws Exception {

public void test31BadJavaHome() throws Exception {
final Installation.Executables bin = installation.executables();
sh.getEnv().put("JAVA_HOME", "doesnotexist");
sh.getEnv().put("ES_JAVA_HOME", "doesnotexist");

// ask for elasticsearch version to quickly exit if java is actually found (ie test failure)
final Result runResult = sh.runIgnoreExitCode(bin.elasticsearch.toString() + " -V");
assertThat(runResult.exitCode, is(1));
assertThat(runResult.stderr, containsString("could not find java in JAVA_HOME"));

assertThat(runResult.stderr, containsString("could not find java in ES_JAVA_HOME"));
}

public void test32SpecialCharactersInJdkPath() throws Exception {
final Installation.Executables bin = installation.executables();
assumeTrue("Only run this test when we know where the JDK is.", distribution().hasJdk);

final Path relocatedJdk = installation.bundledJdk.getParent().resolve("a (special) path");
sh.getEnv().put("JAVA_HOME", relocatedJdk.toString());
sh.getEnv().put("ES_JAVA_HOME", relocatedJdk.toString());

try {
mv(installation.bundledJdk, relocatedJdk);
Expand Down Expand Up @@ -132,16 +131,42 @@ public void test50StartAndStop() throws Exception {
stopElasticsearch();
}

public void test51EsJavaHomeOverride() throws Exception {
Platforms.onLinux(() -> {
String systemJavaHome1 = sh.run("echo $SYSTEM_JAVA_HOME").stdout.trim();
sh.getEnv().put("ES_JAVA_HOME", systemJavaHome1);
});
Platforms.onWindows(() -> {
final String systemJavaHome1 = sh.run("$Env:SYSTEM_JAVA_HOME").stdout.trim();
sh.getEnv().put("ES_JAVA_HOME", systemJavaHome1);
});

startElasticsearch();
ServerUtils.runElasticsearchTests();
stopElasticsearch();

String systemJavaHome1 = sh.getEnv().get("ES_JAVA_HOME");
assertThat(FileUtils.slurpAllLogs(installation.logs, "elasticsearch.log", "*.log.gz"), containsString(systemJavaHome1));
}

public void test51JavaHomeOverride() throws Exception {
Platforms.onLinux(() -> {
String systemJavaHome1 = sh.run("echo $SYSTEM_JAVA_HOME").stdout.trim();
sh.getEnv().put("JAVA_HOME", systemJavaHome1);
// ensure that ES_JAVA_HOME is not set for the test
sh.getEnv().remove("ES_JAVA_HOME");
});
Platforms.onWindows(() -> {
final String systemJavaHome1 = sh.run("$Env:SYSTEM_JAVA_HOME").stdout.trim();
sh.getEnv().put("JAVA_HOME", systemJavaHome1);
// ensure that ES_JAVA_HOME is not set for the test
sh.getEnv().remove("ES_JAVA_HOME");
});

final Installation.Executables bin = installation.executables();
final Result runResult = sh.run(bin.elasticsearch.toString() + " -V");
assertThat(runResult.stderr, containsString("warning: usage of JAVA_HOME is deprecated, use ES_JAVA_HOME"));

startElasticsearch();
ServerUtils.runElasticsearchTests();
stopElasticsearch();
Expand All @@ -150,6 +175,32 @@ public void test51JavaHomeOverride() throws Exception {
assertThat(FileUtils.slurpAllLogs(installation.logs, "elasticsearch.log", "*.log.gz"), containsString(systemJavaHome1));
}

public void test51EsJavaHomeOverrideOverridesJavaHome() throws Exception {
Platforms.onLinux(() -> {
String systemJavaHome1 = sh.run("echo $SYSTEM_JAVA_HOME").stdout.trim();
sh.getEnv().put("ES_JAVA_HOME", systemJavaHome1);
// deliberately set to a location that does not exist, if ES_JAVA_HOME takes precedence this is ignored
sh.getEnv().put("JAVA_HOME", "doesnotexist");
});
Platforms.onWindows(() -> {
final String systemJavaHome1 = sh.run("$Env:SYSTEM_JAVA_HOME").stdout.trim();
sh.getEnv().put("ES_JAVA_HOME", systemJavaHome1);
// deliberately set to a location that does not exist, if ES_JAVA_HOME takes precedence this is ignored
sh.getEnv().put("JAVA_HOME", "doesnotexist");
});

final Installation.Executables bin = installation.executables();
final Result runResult = sh.run(bin.elasticsearch.toString() + " -V");
assertThat(runResult.stderr, not(containsString("warning: usage of JAVA_HOME is deprecated, use ES_JAVA_HOME")));

startElasticsearch();
ServerUtils.runElasticsearchTests();
stopElasticsearch();

String systemJavaHome1 = sh.getEnv().get("ES_JAVA_HOME");
assertThat(FileUtils.slurpAllLogs(installation.logs, "elasticsearch.log", "*.log.gz"), containsString(systemJavaHome1));
}

public void test52BundledJdkRemoved() throws Exception {
assumeThat(distribution().hasJdk, is(true));

Expand All @@ -158,18 +209,18 @@ public void test52BundledJdkRemoved() throws Exception {
mv(installation.bundledJdk, relocatedJdk);
Platforms.onLinux(() -> {
String systemJavaHome1 = sh.run("echo $SYSTEM_JAVA_HOME").stdout.trim();
sh.getEnv().put("JAVA_HOME", systemJavaHome1);
sh.getEnv().put("ES_JAVA_HOME", systemJavaHome1);
});
Platforms.onWindows(() -> {
final String systemJavaHome1 = sh.run("$Env:SYSTEM_JAVA_HOME").stdout.trim();
sh.getEnv().put("JAVA_HOME", systemJavaHome1);
sh.getEnv().put("ES_JAVA_HOME", systemJavaHome1);
});

startElasticsearch();
ServerUtils.runElasticsearchTests();
stopElasticsearch();

String systemJavaHome1 = sh.getEnv().get("JAVA_HOME");
String systemJavaHome1 = sh.getEnv().get("ES_JAVA_HOME");
assertThat(FileUtils.slurpAllLogs(installation.logs, "elasticsearch.log", "*.log.gz"), containsString(systemJavaHome1));
} finally {
mv(relocatedJdk, installation.bundledJdk);
Expand All @@ -183,7 +234,7 @@ public void test53JavaHomeWithSpecialCharacters() throws Exception {
// once windows 2012 is no longer supported and powershell 5.0 is always available we can change this command
sh.run("cmd /c mklink /D '" + javaPath + "' $Env:SYSTEM_JAVA_HOME");

sh.getEnv().put("JAVA_HOME", "C:\\Program Files (x86)\\java");
sh.getEnv().put("ES_JAVA_HOME", "C:\\Program Files (x86)\\java");

// verify ES can start, stop and run plugin list
startElasticsearch();
Expand All @@ -208,7 +259,7 @@ public void test53JavaHomeWithSpecialCharacters() throws Exception {
try {
final String systemJavaHome = sh.run("echo $SYSTEM_JAVA_HOME").stdout.trim();
sh.run("ln -s \"" + systemJavaHome + "\" \"" + testJavaHome + "\"");
sh.getEnv().put("JAVA_HOME", testJavaHome);
sh.getEnv().put("ES_JAVA_HOME", testJavaHome);

// verify ES can start, stop and run plugin list
startElasticsearch();
Expand All @@ -229,7 +280,7 @@ public void test54ForceBundledJdkEmptyJavaHome() throws Exception {
// cleanup from previous test
rm(installation.config("elasticsearch.keystore"));

sh.getEnv().put("JAVA_HOME", "");
sh.getEnv().put("ES_JAVA_HOME", "");

startElasticsearch();
ServerUtils.runElasticsearchTests();
Expand Down
Loading

0 comments on commit 79e8aae

Please sign in to comment.