Skip to content

Commit b9c504b

Browse files
Replace most shell script logic with Java (#85758)
Elasticsearch provides several command line tools, as well as the main script to start elasticsearch. While most of the logic is abstracted away for cli tools, the main elasticsearch script has hundreds of lines of platform specific shell code. That code is difficult to maintain because it uses many special shell features which then must also exist in other platforms (ie windows batch files). Additionally, the logic in these scripts are not easy to test, we must be on the actual platform and test with a full installation of Elasticsearch, which is relatively slow (compared to most in process tests). This commit replaces logic of the main server script, as well as the windows service management script, with Java. The new entrypoints use the CliToolLauncher. The server cli figures out all the jvm options and such necessary, then launches the real server process. If run in the foreground, the launcher will stay alive for the lifetime of Elasticsearch; the streams are effectively inherited so all output from Elasticsearch still goes to the console. If daemonizing, the launcher waits around until Elasticsearch is "ready" (this means the Node startup completed), then detaches and exits. Co-authored-by: William Brafford <[email protected]>
1 parent 096d7fe commit b9c504b

File tree

58 files changed

+3113
-1253
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+3113
-1253
lines changed

distribution/build.gradle

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) {
230230
* Properties to expand when copying packaging files *
231231
*****************************************************************************/
232232
configurations {
233-
['libs', 'libsVersionChecker', 'libsCliLauncher', 'libsServerCli', 'libsPluginCli', 'libsKeystoreCli', 'libsSecurityCli', 'libsGeoIpCli', 'libsAnsiConsole'].each {
233+
['libs', 'libsVersionChecker', 'libsCliLauncher', 'libsServerCli', 'libsWindowsServiceCli', 'libsPluginCli', 'libsKeystoreCli', 'libsSecurityCli', 'libsGeoIpCli', 'libsAnsiConsole'].each {
234234
create(it) {
235235
canBeConsumed = false
236236
canBeResolved = true
@@ -253,6 +253,7 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) {
253253
libsVersionChecker project(':distribution:tools:java-version-checker')
254254
libsCliLauncher project(':distribution:tools:cli-launcher')
255255
libsServerCli project(':distribution:tools:server-cli')
256+
libsWindowsServiceCli project(':distribution:tools:windows-service-cli')
256257
libsAnsiConsole project(':distribution:tools:ansi-console')
257258
libsPluginCli project(':distribution:tools:plugin-cli')
258259
libsKeystoreCli project(path: ':distribution:tools:keystore-cli')
@@ -278,6 +279,9 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) {
278279
into('tools/server-cli') {
279280
from(configurations.libsServerCli)
280281
}
282+
into('tools/windows-service-cli') {
283+
from(configurations.libsWindowsServiceCli)
284+
}
281285
into('tools/geoip-cli') {
282286
from(configurations.libsGeoIpCli)
283287
}
@@ -295,7 +299,6 @@ configure(subprojects.findAll { ['archives', 'packages'].contains(it.name) }) {
295299
}
296300
}
297301

298-
299302
modulesFiles = { platform ->
300303
copySpec {
301304
eachFile {

distribution/packages/src/common/systemd/elasticsearch.service

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ After=network-online.target
66

77
[Service]
88
Type=notify
9+
# the elasticsearch process currently sends the notifications back to systemd
10+
# and for some reason exec does not work (even though it is a child). We should change
11+
# this notify access back to main (the default), see https://github.com/elastic/elasticsearch/issues/86475
12+
NotifyAccess=all
913
RuntimeDirectory=elasticsearch
1014
PrivateTmp=true
1115
Environment=ES_HOME=/usr/share/elasticsearch

distribution/src/bin/elasticsearch

Lines changed: 3 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,5 @@
11
#!/bin/bash
22

3-
# CONTROLLING STARTUP:
4-
#
5-
# This script relies on a few environment variables to determine startup
6-
# behavior, those variables are:
7-
#
8-
# ES_PATH_CONF -- Path to config directory
9-
# ES_JAVA_OPTS -- External Java Opts on top of the defaults set
10-
#
11-
# Optionally, exact memory values can be set using the `ES_JAVA_OPTS`. Example
12-
# values are "512m", and "10g".
13-
#
14-
# ES_JAVA_OPTS="-Xms8g -Xmx8g" ./bin/elasticsearch
15-
16-
source "`dirname "$0"`"/elasticsearch-env
17-
18-
CHECK_KEYSTORE=true
19-
ATTEMPT_SECURITY_AUTO_CONFIG=true
20-
DAEMONIZE=false
21-
ENROLL_TO_CLUSTER=false
22-
# Store original arg array as we will be shifting through it below
23-
ARG_LIST=("$@")
24-
25-
while [ $# -gt 0 ]; do
26-
if [[ $1 == "--enrollment-token" ]]; then
27-
if [ $ENROLL_TO_CLUSTER = true ]; then
28-
echo "Multiple --enrollment-token parameters are not allowed" 1>&2
29-
exit 1
30-
fi
31-
ENROLL_TO_CLUSTER=true
32-
ATTEMPT_SECURITY_AUTO_CONFIG=false
33-
ENROLLMENT_TOKEN="$2"
34-
shift
35-
elif [[ $1 == "-h" || $1 == "--help" || $1 == "-V" || $1 == "--version" ]]; then
36-
CHECK_KEYSTORE=false
37-
ATTEMPT_SECURITY_AUTO_CONFIG=false
38-
elif [[ $1 == "-d" || $1 == "--daemonize" ]]; then
39-
DAEMONIZE=true
40-
fi
41-
if [[ $# -gt 0 ]]; then
42-
shift
43-
fi
44-
done
45-
46-
if [ -z "$ES_TMPDIR" ]; then
47-
ES_TMPDIR=`"$JAVA" -cp "$SERVER_CLI_CLASSPATH" org.elasticsearch.server.cli.TempDirectory`
48-
fi
49-
50-
if [ -z "$LIBFFI_TMPDIR" ]; then
51-
LIBFFI_TMPDIR="$ES_TMPDIR"
52-
export LIBFFI_TMPDIR
53-
fi
54-
55-
# get keystore password before setting java options to avoid
56-
# conflicting GC configurations for the keystore tools
57-
unset KEYSTORE_PASSWORD
58-
KEYSTORE_PASSWORD=
59-
if [[ $CHECK_KEYSTORE = true ]] \
60-
&& bin/elasticsearch-keystore has-passwd --silent
61-
then
62-
if ! read -s -r -p "Elasticsearch keystore password: " KEYSTORE_PASSWORD ; then
63-
echo "Failed to read keystore password on console" 1>&2
64-
exit 1
65-
fi
66-
fi
67-
68-
if [[ $ENROLL_TO_CLUSTER = true ]]; then
69-
CLI_NAME="auto-configure-node" \
70-
CLI_LIBS="modules/x-pack-core,modules/x-pack-security,lib/tools/security-cli" \
71-
bin/elasticsearch-cli "${ARG_LIST[@]}" <<<"$KEYSTORE_PASSWORD"
72-
elif [[ $ATTEMPT_SECURITY_AUTO_CONFIG = true ]]; then
73-
# It is possible that an auto-conf failure prevents the node from starting, but this is only the exceptional case (exit code 1).
74-
# Most likely an auto-conf failure will leave the configuration untouched (exit codes 73, 78 and 80), optionally printing a message
75-
# if the error is uncommon or unexpected, but it should otherwise let the node to start as usual.
76-
# It is passed in all the command line options in order to read the node settings ones (-E), while the other parameters are ignored
77-
# (a small caveat is that it also inspects the -v option in order to provide more information on how auto config went)
78-
if CLI_NAME="auto-configure-node" \
79-
CLI_LIBS="modules/x-pack-core,modules/x-pack-security,lib/tools/security-cli" \
80-
bin/elasticsearch-cli "${ARG_LIST[@]}" <<<"$KEYSTORE_PASSWORD"; then
81-
:
82-
else
83-
retval=$?
84-
# these exit codes cover the cases where auto-conf cannot run but the node should NOT be prevented from starting as usual
85-
# eg the node is restarted, is already configured in an incompatible way, or the file system permissions do not allow it
86-
if [[ $retval -ne 80 ]] && [[ $retval -ne 73 ]] && [[ $retval -ne 78 ]]; then
87-
exit $retval
88-
fi
89-
fi
90-
fi
91-
92-
# The JVM options parser produces the final JVM options to start Elasticsearch.
93-
# It does this by incorporating JVM options in the following way:
94-
# - first, system JVM options are applied (these are hardcoded options in the
95-
# parser)
96-
# - second, JVM options are read from jvm.options and jvm.options.d/*.options
97-
# - third, JVM options from ES_JAVA_OPTS are applied
98-
# - fourth, ergonomic JVM options are applied
99-
ES_JAVA_OPTS=`export ES_TMPDIR; "$JAVA" -cp "$SERVER_CLI_CLASSPATH" -Des.distribution.type="$ES_DISTRIBUTION_TYPE" org.elasticsearch.server.cli.JvmOptionsParser "$ES_PATH_CONF" "$ES_HOME/plugins"`
100-
101-
# Remove enrollment related parameters before passing the arg list to Elasticsearch
102-
for i in "${!ARG_LIST[@]}"; do
103-
if [[ ${ARG_LIST[i]} = "--enrollment-token" || ${ARG_LIST[i]} = "$ENROLLMENT_TOKEN" ]]; then
104-
unset 'ARG_LIST[i]'
105-
fi
106-
done
107-
108-
# manual parsing to find out, if process should be detached
109-
if [[ $DAEMONIZE = false ]]; then
110-
exec \
111-
"$JAVA" \
112-
$ES_JAVA_OPTS \
113-
-Des.path.home="$ES_HOME" \
114-
-Des.path.conf="$ES_PATH_CONF" \
115-
-Des.distribution.type="$ES_DISTRIBUTION_TYPE" \
116-
-cp "$ES_CLASSPATH" \
117-
org.elasticsearch.bootstrap.Elasticsearch \
118-
"${ARG_LIST[@]}" <<<"$KEYSTORE_PASSWORD"
119-
else
120-
exec \
121-
"$JAVA" \
122-
$ES_JAVA_OPTS \
123-
-Des.path.home="$ES_HOME" \
124-
-Des.path.conf="$ES_PATH_CONF" \
125-
-Des.distribution.type="$ES_DISTRIBUTION_TYPE" \
126-
-cp "$ES_CLASSPATH" \
127-
org.elasticsearch.bootstrap.Elasticsearch \
128-
"${ARG_LIST[@]}" \
129-
<<<"$KEYSTORE_PASSWORD" &
130-
retval=$?
131-
pid=$!
132-
[ $retval -eq 0 ] || exit $retval
133-
if ! ps -p $pid > /dev/null ; then
134-
exit 1
135-
fi
136-
exit 0
137-
fi
138-
139-
exit $?
3+
CLI_NAME=server
4+
CLI_LIBS=lib/tools/server-cli
5+
source "`dirname "$0"`"/elasticsearch-cli

distribution/src/bin/elasticsearch-env

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ while [ "`basename "$ES_HOME"`" != "bin" ]; do
3232
done
3333
ES_HOME=`dirname "$ES_HOME"`
3434

35-
# now set the classpath
36-
ES_CLASSPATH="$ES_HOME/lib/*"
37-
SERVER_CLI_CLASSPATH="$ES_CLASSPATH:$ES_HOME/lib/tools/server-cli/*"
38-
3935
# now set the path to java
4036
if [ ! -z "$ES_JAVA_HOME" ]; then
4137
JAVA="$ES_JAVA_HOME/bin/java"

0 commit comments

Comments
 (0)