summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@gmail.com>2019-02-02 21:27:28 +0100
committerGitHub <noreply@github.com>2019-02-02 21:27:28 +0100
commita5395fc374a00c1b5622a1ea0ce5cbea6e4f46cb (patch)
tree9233cb9b7de62daa0d40cccd6d2293ca4f888aae
parentc95506bb44fe49571b57aae3311dae7192401dba (diff)
downloadelixir-a5395fc374a00c1b5622a1ea0ce5cbea6e4f46cb.tar.gz
Add eval and version commands to releases (#8758)
We also split start | daemon iex | elixir into start and start_iex, daemon and daemon_iex.
-rw-r--r--bin/elixir.bat40
-rw-r--r--lib/mix/lib/mix/tasks/release.ex156
-rw-r--r--lib/mix/test/fixtures/release_test/lib/release_test.ex9
-rw-r--r--lib/mix/test/mix/tasks/release_test.exs43
4 files changed, 171 insertions, 77 deletions
diff --git a/bin/elixir.bat b/bin/elixir.bat
index b41241779..558c6a125 100644
--- a/bin/elixir.bat
+++ b/bin/elixir.bat
@@ -117,27 +117,27 @@ if ""==!par:--rpc-eval=! (
goto startloop
)
rem ******* ELIXIR PARAMETERS **********************
-if ""==!par:-r=! (set parsElixir=!parsElixir! -r %1 && shift && goto startloop)
-if ""==!par:-pr=! (set parsElixir=!parsElixir! -pr %1 && shift && goto startloop)
-if ""==!par:-pa=! (set parsElixir=!parsElixir! -pa %1 && shift && goto startloop)
-if ""==!par:-pz=! (set parsElixir=!parsElixir! -pz %1 && shift && goto startloop)
-if ""==!par:-v=! (set parsElixir=!parsElixir! -v && goto startloop)
-if ""==!par:--app=! (set parsElixir=!parsElixir! --app %1 && shift && goto startloop)
-if ""==!par:--no-halt=! (set parsElixir=!parsElixir! --no-halt && goto startloop)
-if ""==!par:--remsh=! (set parsElixir=!parsElixir! --remsh %1 && shift && goto startloop)
-if ""==!par:--dot-iex=! (set parsElixir=!parsElixir! --dot-iex %1 && shift && goto startloop)
+if ""==!par:-r=! (set "parsElixir=!parsElixir! -r %1" && shift && goto startloop)
+if ""==!par:-pr=! (set "parsElixir=!parsElixir! -pr %1" && shift && goto startloop)
+if ""==!par:-pa=! (set "parsElixir=!parsElixir! -pa %1" && shift && goto startloop)
+if ""==!par:-pz=! (set "parsElixir=!parsElixir! -pz %1" && shift && goto startloop)
+if ""==!par:-v=! (set "parsElixir=!parsElixir! -v" && goto startloop)
+if ""==!par:--app=! (set "parsElixir=!parsElixir! --app %1" && shift && goto startloop)
+if ""==!par:--no-halt=! (set "parsElixir=!parsElixir! --no-halt" && goto startloop)
+if ""==!par:--remsh=! (set "parsElixir=!parsElixir! --remsh %1" && shift && goto startloop)
+if ""==!par:--dot-iex=! (set "parsElixir=!parsElixir! --dot-iex %1" && shift && goto startloop)
rem ******* ERLANG PARAMETERS **********************
-if ""==!par:--boot=! (set parsErlang=!parsErlang! -boot %1 && shift && goto startloop)
-if ""==!par:--boot-var=! (set parsErlang=!parsErlang! -boot_var %1 %2 && shift && shift && goto startloop)
-if ""==!par:--cookie=! (set parsErlang=!parsErlang! -setcookie %1 && shift && goto startloop)
-if ""==!par:--hidden=! (set parsErlang=!parsErlang! -hidden && goto startloop)
-if ""==!par:--detached=! (set parsErlang=!parsErlang! -detached && echo warning: the --detached option is deprecated && goto startloop)
-if ""==!par:--erl-config=! (set parsErlang=!parsErlang! -config %1 && shift && goto startloop)
-if ""==!par:--logger-otp-reports=! (set parsErlang=!parsErlang! -logger handle_otp_reports %1 && shift && goto startloop)
-if ""==!par:--logger-sasl-reports=! (set parsErlang=!parsErlang! -logger handle_sasl_reports %1 && shift && goto startloop)
-if ""==!par:--name=! (set parsErlang=!parsErlang! -name %1 && shift && goto startloop)
-if ""==!par:--sname=! (set parsErlang=!parsErlang! -sname %1 && shift && goto startloop)
-if ""==!par:--vm-args=! (set parsErlang=!parsErlang! -args_file %1 && shift && goto startloop)
+if ""==!par:--boot=! (set "parsErlang=!parsErlang! -boot %1" && shift && goto startloop)
+if ""==!par:--boot-var=! (set "parsErlang=!parsErlang! -boot_var %1 %2" && shift && shift && goto startloop)
+if ""==!par:--cookie=! (set "parsErlang=!parsErlang! -setcookie %1" && shift && goto startloop)
+if ""==!par:--hidden=! (set "parsErlang=!parsErlang! -hidden" && goto startloop)
+if ""==!par:--detached=! (set "parsErlang=!parsErlang! -detached" && echo warning: the --detached option is deprecated && goto startloop)
+if ""==!par:--erl-config=! (set "parsErlang=!parsErlang! -config %1" && shift && goto startloop)
+if ""==!par:--logger-otp-reports=! (set "parsErlang=!parsErlang! -logger handle_otp_reports %1" && shift && goto startloop)
+if ""==!par:--logger-sasl-reports=! (set "parsErlang=!parsErlang! -logger handle_sasl_reports %1" && shift && goto startloop)
+if ""==!par:--name=! (set "parsErlang=!parsErlang! -name %1" && shift && goto startloop)
+if ""==!par:--sname=! (set "parsErlang=!parsErlang! -sname %1" && shift && goto startloop)
+if ""==!par:--vm-args=! (set "parsErlang=!parsErlang! -args_file %1" && shift && goto startloop)
if ""==!par:--erl=! (set "beforeExtra=!beforeExtra! %~1" && shift && goto startloop)
if ""==!par:--pipe-to=! (echo --pipe-to : Option is not supported on Windows && goto end)
set endLoop=1
diff --git a/lib/mix/lib/mix/tasks/release.ex b/lib/mix/lib/mix/tasks/release.ex
index a167b977d..2f855f424 100644
--- a/lib/mix/lib/mix/tasks/release.ex
+++ b/lib/mix/lib/mix/tasks/release.ex
@@ -63,14 +63,14 @@ defmodule Mix.Tasks.Release do
For those looking for alternate ways of running the system, you can
run it as a daemon on Unix-like system or install it as a service on
- Windows.
+ Windows. Then we list all commands supported by `bin/RELEASE_NAME`.
### Daemon mode (Unix-like)
If you open up `bin/start`, you will also see there is an option to
run the release in daemon mode written as a comment:
- bin/RELEASE_NAME daemon iex
+ bin/RELEASE_NAME daemon_iex
In daemon mode, the system is started on the background via
[run_erl](http://erlang.org/doc/man/run_erl.html). You may also
@@ -87,9 +87,9 @@ defmodule Mix.Tasks.Release do
will actually shut down the daemon. Therefore, using
`bin/RELEASE_NAME remote` should be preferred, even in daemon mode.
- You can customize the tmp directory used both for logging and for piping
- in daemon mode by setting the `RELEASE_TMP` environment variable before
- starting the system.
+ You can customize the tmp directory used both for logging and for
+ piping in daemon mode by setting the `RELEASE_TMP` environment
+ variable before starting the system.
### Services mode
@@ -117,6 +117,23 @@ defmodule Mix.Tasks.Release do
The `install` command must be executed as an administrator.
+ ## `bin/RELEASE_NAME` commands
+
+ The following commands are supported by `bin/RELEASE_NAME`:
+
+ start Starts the system
+ start_iex Starts the system with IEx attached
+ daemon Starts the system as a daemon (Unix-like only)
+ daemon_iex Starts the system as a daemon with IEx attached (Unix-like only)
+ install Installs this system as a Windows service (Windows only)
+ eval "EXPR" Executes the given expression on a new, non-booted system
+ rpc "EXPR" Executes the given expression remotely on the running system
+ remote Connects to the running system via a remote shell
+ restart Restarts the running system via a remote command
+ stop Stops the running system via a remote command
+ pid Prints the OS PID of the running system via a remote command
+ version Prints the release name and version to be booted
+
## Deployments
### Requirements
@@ -858,8 +875,8 @@ defmodule Mix.Tasks.Release do
# export HEART_COMMAND
# export ELIXIR_ERL_OPTIONS="-heart"
- # To start your system using IEx: "$(dirname "$0")/<%= @name %>" start iex
- # To start it as a daemon using IEx: "$(dirname "$0")/<%= @name %>" daemon iex
+ # To start your system using IEx: "$(dirname "$0")/<%= @name %>" start_iex
+ # To start it as a daemon using IEx: "$(dirname "$0")/<%= @name %>" daemon_iex
"$(dirname "$0")/<%= @name %>" start
""")
@@ -884,7 +901,7 @@ defmodule Mix.Tasks.Release do
rpc () {
exec "$REL_VSN_DIR/elixir" \
--hidden --name "rpc-$(gen_id)@127.0.0.1" --cookie "$RELEASE_COOKIE" \
- --boot "${REL_VSN_DIR}/start_clean" \
+ --boot "$REL_VSN_DIR/start_clean" \
--boot-var RELEASE_LIB "$RELEASE_ROOT/lib" \
--rpc-eval "$RELEASE_NODE" "$1"
}
@@ -892,28 +909,51 @@ defmodule Mix.Tasks.Release do
start () {
REL_EXEC="$1"
shift
- exec "$REL_VSN_DIR/$REL_EXEC" --no-halt \
- --werl --name "$RELEASE_NODE" --cookie "$RELEASE_COOKIE" \
- --erl-config "${REL_VSN_DIR}/sys" \
- --boot "${REL_VSN_DIR}/start" \
+ exec "$REL_VSN_DIR/$REL_EXEC" \
+ --name "$RELEASE_NODE" --cookie "$RELEASE_COOKIE" \
+ --erl-config "$REL_VSN_DIR/sys" \
+ --boot "$REL_VSN_DIR/start" \
--boot-var RELEASE_LIB "$RELEASE_ROOT/lib" \
- --vm-args "${REL_VSN_DIR}/vm.args" "$@"
+ --vm-args "$REL_VSN_DIR/vm.args" "$@"
}
case $1 in
start)
- start "${2:-elixir}"
+ start "elixir" --no-halt
+ ;;
+
+ start_iex)
+ start "iex" --werl
;;
daemon)
export RELEASE_TMP="${RELEASE_TMP:-"$RELEASE_ROOT/tmp"}"
- start "${2:-elixir}" --pipe-to "${RELEASE_TMP}/pipe" "${RELEASE_TMP}/log"
+ start "elixir" --no-halt --pipe-to "${RELEASE_TMP}/pipe" "${RELEASE_TMP}/log"
+ ;;
+
+ daemon_iex)
+ export RELEASE_TMP="${RELEASE_TMP:-"$RELEASE_ROOT/tmp"}"
+ start "iex" --pipe-to "${RELEASE_TMP}/pipe" "${RELEASE_TMP}/log"
+ ;;
+
+ eval)
+ if [ -z "$2" ]; then
+ echo "ERROR: EVAL expects an expression as argument" >&2
+ exit 1
+ fi
+
+ exec "$REL_VSN_DIR/elixir" \
+ --cookie "$RELEASE_COOKIE" \
+ --erl-config "$REL_VSN_DIR/sys" \
+ --boot "$REL_VSN_DIR/start_clean" \
+ --boot-var RELEASE_LIB "$RELEASE_ROOT/lib" \
+ --vm-args "$REL_VSN_DIR/vm.args" --eval "$2"
;;
remote)
exec "$REL_VSN_DIR/iex" \
--werl --hidden --name "remote-$(gen_id)@127.0.0.1" --cookie "$RELEASE_COOKIE" \
- --boot "${REL_VSN_DIR}/start_clean" \
+ --boot "$REL_VSN_DIR/start_clean" \
--boot-var RELEASE_LIB "$RELEASE_ROOT/lib" \
--remsh "$RELEASE_NODE"
;;
@@ -934,18 +974,26 @@ defmodule Mix.Tasks.Release do
rpc "IO.puts System.pid"
;;
+ version)
+ echo "$RELEASE_NAME $RELEASE_VSN"
+ ;;
+
*)
echo "Usage: $(basename "$0") COMMAND [ARGS]
The known commands are:
- start [elixir | iex] Starts the system using elixir or iex
- daemon [elixir | iex] Starts the system as a daemon using elixir or iex
- remote Connects to the running system via a remote shell
- rpc \"EXPR\" Executes the given expression remotely on the running system
- restart Restarts the running system via a remote command
- stop Stops the running system via a remote command
- pid Prints the OS PID of the running system via a remote command
+ start Starts the system
+ start_iex Starts the system with IEx attached
+ daemon Starts the system as a daemon
+ daemon_iex Starts the system as a daemon with IEx attached
+ eval \"EXPR\" Executes the given expression on a new, non-booted system
+ rpc \"EXPR\" Executes the given expression remotely on the running system
+ remote Connects to the running system via a remote shell
+ restart Restarts the running system via a remote command
+ stop Stops the running system via a remote command
+ pid Prints the OS PID of the running system via a remote command
+ version Prints the release name and version to be booted
" >&2
if [ -n "$1" ]; then
@@ -959,7 +1007,7 @@ defmodule Mix.Tasks.Release do
embed_template(:start_bat, ~S"""
@echo off
rem Feel free to edit this file in anyway you want
- rem To start your system using IEx: %~dp0/<%= @name %> start iex
+ rem To start your system using IEx: %~dp0/<%= @name %> start_iex
%~dp0/<%= @name %> start
""")
@@ -978,45 +1026,67 @@ defmodule Mix.Tasks.Release do
if not defined RELEASE_NODE (set RELEASE_NODE=!RELEASE_NAME!@127.0.0.1)
set REL_VSN_DIR=!RELEASE_ROOT!/releases/!RELEASE_VSN!
- if "%~1" == "start" (goto start)
+ if "%~1" == "start" (set "REL_EXEC=elixir" && set "REL_EXTRA=--no-halt" && goto start)
+ if "%~1" == "start_iex" (set "REL_EXEC=iex" && set "REL_EXTRA=--werl" && goto start)
if "%~1" == "remote" (goto remote)
if "%~1" == "install" (goto install)
- if "%~1" == "stop" (set REL_RPC="System.stop()" && goto rpc)
- if "%~1" == "restart" (set REL_RPC="System.stop()" && goto rpc)
- if "%~1" == "pid" (set REL_RPC="IO.puts System.pid" && goto rpc)
+ if "%~1" == "version" (goto version)
+ if "%~1" == "stop" (set "REL_RPC=System.stop()" && goto rpc)
+ if "%~1" == "restart" (set "REL_RPC=System.stop()" && goto rpc)
+ if "%~1" == "pid" (set "REL_RPC=IO.puts(System.pid())" && goto rpc)
+ if "%~1" == "eval" (
+ if "%~2" == "" (
+ echo ERROR: EVAL expects an expression as argument
+ goto end
+ )
+ goto eval
+ )
if "%~1" == "rpc" (
if "%~2" == "" (
echo ERROR: RPC expects an expression as argument
- goto end
+ goto end
)
- set REL_RPC="%~2" && goto rpc
+ set "REL_RPC=%~2"
+ goto rpc
)
echo Usage: %~nx0 COMMAND [ARGS]
echo.
echo The known commands are:
echo.
- echo start [elixir ^| iex] Starts the system using elixir or iex
- echo install Installs this system as a Windows service
- echo remote Connects to the running system via a remote shell
- echo rpc "EXPR" Executes the given expression remotely on the running system
- echo restart Restarts the running system via a remote command
- echo stop Stops the running system via a remote command
- echo pid Prints the OS PID of the running system via a remote command
+ echo start Starts the system
+ echo start_iex Starts the system with IEx attached
+ echo install Installs this system as a Windows service
+ echo eval "EXPR" Executes the given expression on a new, non-booted system
+ echo rpc "EXPR" Executes the given expression remotely on the running system
+ echo remote Connects to the running system via a remote shell
+ echo restart Restarts the running system via a remote command
+ echo stop Stops the running system via a remote command
+ echo pid Prints the OS PID of the running system via a remote command
+ echo version Prints the release name and version to be booted
echo.
if not "%~1" == "" (echo ERROR: Unknown command %~1)
goto end
:start
- if not "%~2" == "" (set REL_EXEC=%~2) else (set REL_EXEC=elixir)
- "!REL_VSN_DIR!/!REL_EXEC!.bat" --no-halt ^
- --werl --name "!RELEASE_NODE!" --cookie "!RELEASE_COOKIE!" ^
+ "!REL_VSN_DIR!/!REL_EXEC!.bat" !REL_EXTRA! ^
+ --name "!RELEASE_NODE!" --cookie "!RELEASE_COOKIE!" ^
--erl-config "!REL_VSN_DIR!\sys" ^
--boot "!REL_VSN_DIR!\start" ^
--boot-var RELEASE_LIB "!RELEASE_ROOT!\lib" ^
--vm-args "!REL_VSN_DIR!\vm.args"
goto end
+ :eval
+ "!REL_VSN_DIR!/elixir.bat" ^
+ --eval "%~2" ^
+ --cookie "!RELEASE_COOKIE!" ^
+ --erl-config "!REL_VSN_DIR!\sys" ^
+ --boot "!REL_VSN_DIR!\start_clean" ^
+ --boot-var RELEASE_LIB "!RELEASE_ROOT!\lib" ^
+ --vm-args "!REL_VSN_DIR!\vm.args"
+ goto end
+
:remote
"!REL_VSN_DIR!/iex.bat" ^
--werl --hidden --name "remote-!RANDOM!@127.0.0.1" --cookie "!RELEASE_COOKIE!" ^
@@ -1030,7 +1100,11 @@ defmodule Mix.Tasks.Release do
--hidden --name "rpc-!RANDOM!@127.0.0.1" --cookie "!RELEASE_COOKIE!" ^
--boot "!REL_VSN_DIR!\start_clean" ^
--boot-var RELEASE_LIB "!RELEASE_ROOT!\lib" ^
- --rpc-eval "!RELEASE_NODE!" !REL_RPC!
+ --rpc-eval "!RELEASE_NODE!" "!REL_RPC!"
+ goto end
+
+ :version
+ echo !RELEASE_NAME! !RELEASE_VSN!
goto end
:install
diff --git a/lib/mix/test/fixtures/release_test/lib/release_test.ex b/lib/mix/test/fixtures/release_test/lib/release_test.ex
index ac8744a33..d47527c7c 100644
--- a/lib/mix/test/fixtures/release_test/lib/release_test.ex
+++ b/lib/mix/test/fixtures/release_test/lib/release_test.ex
@@ -12,7 +12,6 @@ defmodule ReleaseTest do
release_node: System.get_env("RELEASE_NODE"),
release_vsn: System.get_env("RELEASE_VSN"),
cookie_env: cookie,
- cookie_node: wait_until_connected(String.to_atom(cookie)),
node: node(),
root_dir: :code.root_dir() |> to_string(),
static_config: Application.fetch_env!(:release_test, :static)
@@ -28,14 +27,6 @@ defmodule ReleaseTest do
end
end
- def wait_until_connected(cookie) do
- if Node.get_cookie() == cookie do
- cookie
- else
- wait_until_connected(cookie)
- end
- end
-
def hello_world do
IO.puts("hello world")
end
diff --git a/lib/mix/test/mix/tasks/release_test.exs b/lib/mix/test/mix/tasks/release_test.exs
index dc9810260..27c831042 100644
--- a/lib/mix/test/mix/tasks/release_test.exs
+++ b/lib/mix/test/mix/tasks/release_test.exs
@@ -33,16 +33,14 @@ defmodule Mix.Tasks.ReleaseTest do
|> File.read_link()
|> elem(0) == :error
- cookie_string = File.read!(Path.join(root, "releases/COOKIE"))
- cookie_atom = String.to_atom(cookie_string)
+ cookie = File.read!(Path.join(root, "releases/COOKIE"))
# Assert runtime
open_port(Path.join(root, "bin/start"))
assert %{
app_dir: app_dir,
- cookie_env: ^cookie_string,
- cookie_node: ^cookie_atom,
+ cookie_env: ^cookie,
node: :"release_test@127.0.0.1",
protocols_consolidated?: true,
release_name: "release_test",
@@ -94,7 +92,6 @@ defmodule Mix.Tasks.ReleaseTest do
assert %{
app_dir: app_dir,
cookie_env: "abcdefghijk",
- cookie_node: :abcdefghijk,
node: :"demo@127.0.0.1",
protocols_consolidated?: true,
release_name: "demo",
@@ -138,6 +135,39 @@ defmodule Mix.Tasks.ReleaseTest do
end)
end
+ test "runs eval and version commands" do
+ in_fixture("release_test", fn ->
+ config = [releases: [eval: [include_erts: false, cookie: "abcdefghij"]]]
+
+ Mix.Project.in_project(:release_test, ".", config, fn _ ->
+ root = Path.absname("_build/dev/rel/eval")
+ Mix.Task.run("release")
+
+ script = Path.join(root, "bin/eval")
+ {version, 0} = System.cmd(script, ["version"])
+ assert String.trim_trailing(version) == "eval 0.1.0"
+ refute File.exists?(Path.join(root, "RELEASE_BOOTED"))
+
+ {hello_world, 0} = System.cmd(script, ["eval", ~s[IO.puts :hello_world]])
+ assert String.trim_trailing(hello_world) == "hello_world"
+ refute File.exists?(Path.join(root, "RELEASE_BOOTED"))
+
+ open_port(script, ['eval', 'Application.ensure_all_started(:release_test)'])
+
+ assert %{
+ cookie_env: "abcdefghij",
+ node: :nonode@nohost,
+ protocols_consolidated?: true,
+ release_name: "eval",
+ release_node: "eval@127.0.0.1",
+ release_root: root,
+ release_vsn: "0.1.0",
+ static_config: :was_set
+ } = wait_until_evaled(Path.join(root, "RELEASE_BOOTED"))
+ end)
+ end)
+ end
+
@tag :unix
test "runs in daemon mode" do
in_fixture("release_test", fn ->
@@ -148,12 +178,11 @@ defmodule Mix.Tasks.ReleaseTest do
Mix.Task.run("release")
script = Path.join(root, "bin/permanent2")
- open_port(script, ['daemon', 'iex'])
+ open_port(script, ['daemon_iex'])
assert wait_until_evaled(Path.join(root, "RELEASE_BOOTED")) == %{
app_dir: Path.join(root, "lib/release_test-0.1.0"),
cookie_env: "abcdefghij",
- cookie_node: :abcdefghij,
node: :"permanent2@127.0.0.1",
protocols_consolidated?: true,
release_name: "permanent2",