/
erts.sh
executable file
·332 lines (311 loc) · 11.3 KB
/
erts.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
#!/usr/bin/env bash
set -e
__rel_apps() {
__releases="$RELEASE_ROOT_DIR/releases/RELEASES"
__vsn="${REL_VSN//+/\\\+}"
__rel="$(sed -E -n "/\{release,[^,]*,\"$__vsn\"/,/[^po]*(permanent|old)}/p" "$__releases")"
echo "$__rel" \
| grep -E '[{][A-Za-z_0-9]*,\"[0-9.]*[A-Za-z0-9.\_\+\-]*\"' \
| tail -n +2 \
| sed -e's/"[^"]*$//' \
-e's/^[^a-z]*//' \
-e's/,/-/' \
-e's/"//' \
-e's/","[^"]*$//'
}
code_paths=()
__set_code_paths() {
if [ ${#code_paths[@]} -eq 0 ]; then
code_paths=()
apps="$(__rel_apps)"
for app in $apps; do
if [ -d "${ERTS_LIB_DIR}/$app" ]; then
code_paths+=(-pa "${ERTS_LIB_DIR}/$app/ebin")
elif [ -d "${RELEASE_ROOT_DIR}/lib/$app" ]; then
code_paths+=(-pa "${RELEASE_ROOT_DIR}/lib/$app/ebin")
elif [ -L "${RELEASE_ROOT_DIR}/lib/$app" ]; then
code_paths+=(-pa "${RELEASE_ROOT_DIR}/lib/$app/ebin")
else
fail "Could not locate code path for $app!"
fi
done
fi
}
# Used post-upgrade to update the code paths used for commands
reset_code_paths() {
code_paths=()
__set_code_paths
}
# Echoes the path to the current ERTS binaries, e.g. erl
whereis_erts_bin() {
if [ -z "$ERTS_VSN" ]; then
set +e
__erts_bin="$(dirname "$(type -P erl)")"
set -e
echo "$__erts_bin"
elif [ -z "$USE_HOST_ERTS" ]; then
__erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
if [ -d "$__erts_dir" ]; then
echo "$__erts_dir/bin"
else
ERTS_VSN=
whereis_erts_bin
fi
else
ERTS_VSN=
whereis_erts_bin
fi
}
# Invokes erl with the provided arguments
erl() {
__bin="$(whereis_erts_bin)"
if [ -z "$__bin" ]; then
fail "Erlang runtime not found. If Erlang is installed, ensure it is in your PATH"
fi
__erl="$__bin/erl"
# Set flag for whether a boot script was provided by the caller
__boot_provided=0
if echo "$@" | grep '\-boot ' >/dev/null; then
__boot_provided=1
fi
# Set flag for whether the current erl is from a bundled ERTS
__erts_included=0
if [[ "$__erl" =~ ^$RELEASE_ROOT_DIR ]]; then
__erts_included=1
fi
if [ $__erts_included -eq 1 ] && [ $__boot_provided -eq 1 ]; then
# Bundled ERTS with -boot set
"$__erl" -boot_var ERTS_LIB_DIR "$RELEASE_ROOT_DIR/lib" \
${SYS_CONFIG_PATH:+-config "${SYS_CONFIG_PATH}"} \
-pa "${CONSOLIDATED_DIR}" \
${EXTRA_CODE_PATHS:+-pa "${EXTRA_CODE_PATHS}"} \
"$@"
elif [ $__erts_included -eq 1 ]; then
# Bundled ERTS, using default boot script 'start_clean'
"$__erl" -boot_var ERTS_LIB_DIR "$RELEASE_ROOT_DIR/lib" \
-boot "${RELEASE_ROOT_DIR}/bin/start_clean" \
${SYS_CONFIG_PATH:+-config "${SYS_CONFIG_PATH}"} \
-pa "${CONSOLIDATED_DIR}" \
${EXTRA_CODE_PATHS:+-pa "${EXTRA_CODE_PATHS}"} \
"$@"
elif [ $__boot_provided -eq 0 ]; then
# Host ERTS with -boot not set
"$__erl" -boot start_clean \
${SYS_CONFIG_PATH:+-config "${SYS_CONFIG_PATH}"} \
"${code_paths[@]}" \
-pa "${RELEASE_ROOT_DIR}"/lib/*/ebin \
-pa "${CONSOLIDATED_DIR}" \
${EXTRA_CODE_PATHS:+-pa "${EXTRA_CODE_PATHS}"} \
"$@"
elif [ -z "$ERTS_LIB_DIR" ]; then
# Host ERTS, -boot set, no ERTS_LIB_DIR available
"$__erl" \
${SYS_CONFIG_PATH:+-config "${SYS_CONFIG_PATH}"} \
"${code_paths[@]}" \
-pa "${CONSOLIDATED_DIR}" \
${EXTRA_CODE_PATHS:+-pa "${EXTRA_CODE_PATHS}"} \
"$@"
else
# Host ERTS, -boot set, ERTS_LIB_DIR available
"$__erl" -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
${SYS_CONFIG_PATH:+-config "${SYS_CONFIG_PATH}"} \
"${code_paths[@]}" \
-pa "${CONSOLIDATED_DIR}" \
${EXTRA_CODE_PATHS:+-pa "${EXTRA_CODE_PATHS}"} \
"$@"
fi
}
erlexec(){
__erl="$(whereis_erts_bin)/erl"
if [ -z "$__erl" ]; then
fail "Erlang runtime not found. If Erlang is installed, ensure it is in your PATH"
fi
if [[ "$__erl" =~ ^$RELEASE_ROOT_DIR ]]; then
# Bundled ERTS
exec "$BINDIR/erlexec" -boot_var ERTS_LIB_DIR "$RELEASE_ROOT_DIR/lib" \
${SYS_CONFIG_PATH:+-config "${SYS_CONFIG_PATH}"} \
-pa "${CONSOLIDATED_DIR}" \
${EXTRA_CODE_PATHS:+-pa "${EXTRA_CODE_PATHS}"} \
"$@"
else
# Host ERTS
exec "$BINDIR/erlexec" -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
${SYS_CONFIG_PATH:+-config "${SYS_CONFIG_PATH}"} \
-pa "${RELEASE_ROOT_DIR}"/lib/*/ebin \
-pa "${CONSOLIDATED_DIR}" \
${EXTRA_CODE_PATHS:+-pa "${EXTRA_CODE_PATHS}"} \
"$@"
fi
}
# Run Elixir
elixir() {
if [ $# -eq 0 ] || [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
echo "Usage: $(basename "$0") [options] [.exs file] [data]
-e COMMAND Evaluates the given command (*)
-r FILE Requires the given files/patterns (*)
-S SCRIPT Finds and executes the given script in PATH
-pr FILE Requires the given files/patterns in parallel (*)
-pa PATH Prepends the given path to Erlang code path (*)
-pz PATH Appends the given path to Erlang code path (*)
--app APP Starts the given app and its dependencies (*)
--cookie COOKIE Sets a cookie for this distributed node
--detached Starts the Erlang VM detached from console
--erl SWITCHES Switches to be passed down to Erlang (*)
--help, -h Prints this message and exits
--hidden Makes a hidden node
--logger-otp-reports BOOL Enables or disables OTP reporting
--logger-sasl-reports BOOL Enables or disables SASL reporting
--name NAME Makes and assigns a name to the distributed node
--no-halt Does not halt the Erlang VM after execution
--sname NAME Makes and assigns a short name to the distributed node
--version, -v Prints Elixir version and exits
--werl Uses Erlang's Windows shell GUI (Windows only)
** Options marked with (*) can be given more than once
** Options given after the .exs file or -- are passed down to the executed code
** Options can be passed to the Erlang runtime using ELIXIR_ERL_OPTIONS or --erl" >&2
exit 1
fi
MODE="elixir"
ERL=""
I=1
while [ $I -le $# ]; do
S=1
eval "PEEK=\${$I}"
case "$PEEK" in
+iex)
MODE="iex"
;;
+elixirc)
MODE="elixirc"
;;
-v|--compile|--no-halt)
;;
-e|-r|-pr|-pa|-pz|--remsh|--app)
S=2
;;
--detatched|--hidden)
ERL="$ERL `echo $PEEK | cut -c 2-`"
;;
--cookie)
I=$(expr $I + 1)
eval "VAL=\${$I}"
ERL="$ERL -setcookie "$VAL""
;;
--sname|--name)
I=$(expr $I + 1)
eval "VAL=\${$I}"
ERL="$ERL `echo $PEEK | cut -c 2-` "$VAL""
;;
--logger-otp-reports)
I=$(expr $I + 1)
eval "VAL=\${$I}"
if [ "$VAL" = 'true' ] || [ "$VAL" = 'false' ]; then
ERL="$ERL -logger handle_otp_reports "$VAL""
fi
;;
--logger-sasl-reports)
I=$(expr $I + 1)
eval "VAL=\${$I}"
if [ "$VAL" = 'true' ] || [ "$VAL" = 'false' ]; then
ERL="$ERL -logger handle_sasl_reports "$VAL""
fi
;;
--erl)
I=$(expr $I + 1)
eval "VAL=\${$I}"
ERL="$ERL "$VAL""
;;
*)
break
;;
esac
I=$(expr $I + $S)
done
if [ "$MODE" != "iex" ]; then ERL="-noshell -s elixir start_cli $ERL"; fi
erl $ELIXIR_ERL_OPTIONS $ERL -extra "$@"
}
# Run IEx
iex() {
elixir --no-halt --erl "-noshell -user Elixir.IEx.CLI" +iex "$@"
}
# Echoes the current ERTS version
erts_vsn() {
erl -noshell \
-eval 'Ver = erlang:system_info(version), io:format("~s~n", [Ver])' \
-s erlang halt
}
# Echoes the current ERTS root directory
erts_root() {
erl -noshell \
-eval 'io:format("~s~n", [code:root_dir()]).' \
-s erlang halt
}
# Echoes the current OTP version
otp_vsn() {
erl -noshell \
-eval 'Ver = erlang:system_info(otp_release), io:format("~s~n", [Ver])' \
-s erlang halt
}
# Use release_ctl for local operations
# Use like `release_ctl eval "IO.puts(\"Hi!\")"`
release_ctl() {
command="$1"; shift
elixir -e "Distillery.Releases.Runtime.Control.main" \
--logger-sasl-reports false \
-- \
"$command" "$@"
}
# Use release_ctl for remote operations
# Use like `release_remote_ctl ping`
release_remote_ctl() {
require_cookie
command="$1"; shift
name="${PEERNAME:-$NAME}"
elixir -e "Distillery.Releases.Runtime.Control.main" \
--logger-sasl-reports false \
-- \
"$command" \
--name="$name" \
--cookie="$COOKIE" \
"$@"
}
# DEPRECATED: Use release_remote_ctl instead
nodetool() {
release_remote_ctl "$@"
}
# Run an escript in the node's environment
# Use like `escript "path/to/escript"`
escript() {
scriptpath="$1"; shift
export RELEASE_ROOT_DIR
__escript="$(whereis_erts_bin)/escript"
"$__escript" "$ROOTDIR/$scriptpath" "$@"
}
# Test erl to make sure it works, extract key info about runtime while doing so
if __info="$(erl -noshell -eval 'io:format("~s~n~s~n", [code:root_dir(), erlang:system_info(version)]).' -s erlang halt)"; then
export ROOTDIR
ROOTDIR="$(echo "$__info" | head -n1)"
export ERTS_VSN
if [ -z "$ERTS_VSN" ]; then
if [ ! -f "${START_ERL_DATA}" ]; then
fail "Unable to boot release, missing start_erl.data at '"${START_ERL_DATA}"'"
fi
# Update start_erl.data
ERTS_VSN="$(echo "$__info" | tail -n1)"
echo "$ERTS_VSN $REL_VSN" > "$START_ERL_DATA"
else
ERTS_VSN="$(echo "$__info" | tail -n1)"
fi
export ERTS_DIR
ERTS_DIR="$ROOTDIR/erts-$ERTS_VSN"
export BINDIR
BINDIR="$ERTS_DIR/bin"
export ERTS_LIB_DIR
ERTS_LIB_DIR="$(readlink_f "$ERTS_DIR/../lib")"
export EMU="beam"
export PROGNAME="erl"
# Initialize code paths
__set_code_paths
else
fail "Unusable Erlang runtime system! This is likely due to being compiled for another system than the host is running"
fi