├── rebar
├── .gitignore
├── src
├── erws.app.src
├── erws_app.erl
├── erws_sup.erl
└── erws_handler.erl
├── rebar.config
├── README
├── Makefile
├── rel
├── files
│ ├── vm.args
│ ├── sys.config
│ ├── erl
│ ├── start_erl.cmd
│ ├── erws.cmd
│ ├── nodetool
│ └── erws
└── reltool.config
└── priv
└── index.html
/rebar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcelog/erws/HEAD/rebar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | deps/
2 | ebin/
3 | rel/erl_crash.dump
4 | rel/erws/
5 | .rebar
6 | *.swp
7 |
8 |
--------------------------------------------------------------------------------
/src/erws.app.src:
--------------------------------------------------------------------------------
1 | {application, erws, [
2 | {description, ""},
3 | {vsn, "1"},
4 | {registered, []},
5 | {applications, [kernel,stdlib,crypto,cowboy,compiler,lager,syntax_tools]},
6 | {mod, { erws_app, []}},
7 | {env, []}
8 | ]}.
9 |
--------------------------------------------------------------------------------
/rebar.config:
--------------------------------------------------------------------------------
1 | {erl_opts, [{parse_transform, lager_transform}]}.
2 | {lib_dirs,["deps"]}.
3 |
4 | {deps, [
5 | {'lager', ".*", {
6 | git, "git://github.com/basho/lager.git", "master"}
7 | },
8 | {'cowboy', ".*", {
9 | git, "git://github.com/extend/cowboy.git", {tag, "0.9.0"}}
10 | }
11 | ]}.
12 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | erws
2 | ====
3 |
4 | Example of using cowboy to handle websocket connections. This is the
5 | sourcecode for this article: http://erlang.org.ar/WebsocketsConCowboy
6 |
7 | You can find the english version here:
8 | http://marcelog.github.com/articles/erlang_websocket_server_cowboy_tutorial.html
9 |
10 | Thanks
11 | ======
12 | McClain Looney: @mlooney for updating the code to cowboy 0.9
13 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | NAME=erws
2 |
3 | all: compile release
4 | ./rebar compile
5 |
6 | compile:
7 | ./rebar compile
8 |
9 | release:
10 | cd rel && ../rebar generate && cd -
11 |
12 | node:
13 | (cd rel && ../rebar create-node nodeid=${NAME} && cd -)
14 |
15 | clean:
16 | ./rebar clean
17 | rm -rf rel/${NAME}
18 |
19 | run:
20 | rel/${NAME}/bin/${NAME} start
21 |
22 | stop:
23 | rel/${NAME}/bin/${NAME} stop
24 |
25 | runconsole:
26 | rel/${NAME}/bin/${NAME} console
27 |
28 | alldev: clean all runconsole
29 |
--------------------------------------------------------------------------------
/rel/files/vm.args:
--------------------------------------------------------------------------------
1 | ## Name of the node
2 | -name erws@127.0.0.1
3 |
4 | ## Cookie for distributed erlang
5 | -setcookie erws
6 |
7 | ## Heartbeat management; auto-restarts VM if it dies or becomes unresponsive
8 | ## (Disabled by default..use with caution!)
9 | ##-heart
10 |
11 | ## Enable kernel poll and a few async threads
12 | ##+K true
13 | ##+A 5
14 |
15 | ## Increase number of concurrent ports/sockets
16 | ##-env ERL_MAX_PORTS 4096
17 |
18 | ## Tweak GC to run more often
19 | ##-env ERL_FULLSWEEP_AFTER 10
20 |
--------------------------------------------------------------------------------
/rel/files/sys.config:
--------------------------------------------------------------------------------
1 | [
2 | {sasl, [
3 | {sasl_error_logger, {file, "log/sasl-error.log"}},
4 | {errlog_type, error},
5 | {error_logger_mf_dir, "log/sasl"}, % Log directory
6 | {error_logger_mf_maxbytes, 10485760}, % 10 MB max file size
7 | {error_logger_mf_maxfiles, 5} % 5 files max
8 | ]},
9 | {lager, [
10 | {handlers, [
11 | {lager_console_backend, debug},
12 | {lager_file_backend, [{file, "error.log"}, {level, error}]},
13 | {lager_file_backend, [{file, "console.log"}, {level, info}]}
14 | ]}
15 | ]}
16 | ].
17 |
18 |
--------------------------------------------------------------------------------
/src/erws_app.erl:
--------------------------------------------------------------------------------
1 | -module(erws_app).
2 |
3 | -behaviour(application).
4 |
5 | %% Application callbacks
6 | -export([start/2, stop/1]).
7 |
8 | %% ===================================================================
9 | %% Application callbacks
10 | %% ===================================================================
11 |
12 | start(_StartType, _StartArgs) ->
13 | Dispatch = cowboy_router:compile([
14 | {'_', [
15 | {"/", cowboy_static, {priv_file, erws, "index.html"}},
16 | {"/websocket", erws_handler, []}
17 | ]}
18 | ]),
19 | {ok, _} = cowboy:start_http(http, 100, [{port, 10100}],
20 | [{env, [{dispatch, Dispatch}]}]),
21 | erws_sup:start_link().
22 |
23 | stop(_State) ->
24 | ok.
25 |
--------------------------------------------------------------------------------
/src/erws_sup.erl:
--------------------------------------------------------------------------------
1 |
2 | -module(erws_sup).
3 |
4 | -behaviour(supervisor).
5 |
6 | %% API
7 | -export([start_link/0]).
8 |
9 | %% Supervisor callbacks
10 | -export([init/1]).
11 |
12 | %% Helper macro for declaring children of supervisor
13 | -define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
14 |
15 | %% ===================================================================
16 | %% API functions
17 | %% ===================================================================
18 |
19 | start_link() ->
20 | supervisor:start_link({local, ?MODULE}, ?MODULE, []).
21 |
22 | %% ===================================================================
23 | %% Supervisor callbacks
24 | %% ===================================================================
25 |
26 | init([]) ->
27 | {ok, { {one_for_one, 5, 10}, []} }.
28 |
29 |
--------------------------------------------------------------------------------
/priv/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
38 |
39 |
40 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/rel/files/erl:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | ## This script replaces the default "erl" in erts-VSN/bin. This is necessary
4 | ## as escript depends on erl and in turn, erl depends on having access to a
5 | ## bootscript (start.boot). Note that this script is ONLY invoked as a side-effect
6 | ## of running escript -- the embedded node bypasses erl and uses erlexec directly
7 | ## (as it should).
8 | ##
9 | ## Note that this script makes the assumption that there is a start_clean.boot
10 | ## file available in $ROOTDIR/release/VSN.
11 |
12 | # Determine the abspath of where this script is executing from.
13 | ERTS_BIN_DIR=$(cd ${0%/*} && pwd)
14 |
15 | # Now determine the root directory -- this script runs from erts-VSN/bin,
16 | # so we simply need to strip off two dirs from the end of the ERTS_BIN_DIR
17 | # path.
18 | ROOTDIR=${ERTS_BIN_DIR%/*/*}
19 |
20 | # Parse out release and erts info
21 | START_ERL=`cat $ROOTDIR/releases/start_erl.data`
22 | ERTS_VSN=${START_ERL% *}
23 | APP_VSN=${START_ERL#* }
24 |
25 | BINDIR=$ROOTDIR/erts-$ERTS_VSN/bin
26 | EMU=beam
27 | PROGNAME=`echo $0 | sed 's/.*\\///'`
28 | CMD="$BINDIR/erlexec"
29 | export EMU
30 | export ROOTDIR
31 | export BINDIR
32 | export PROGNAME
33 |
34 | exec $CMD -boot $ROOTDIR/releases/$APP_VSN/start_clean ${1+"$@"}
35 |
--------------------------------------------------------------------------------
/rel/files/start_erl.cmd:
--------------------------------------------------------------------------------
1 | @setlocal
2 |
3 | @rem Parse arguments. erlsrv.exe prepends erl arguments prior to first ++.
4 | @rem Other args are position dependent.
5 | @set args="%*"
6 | @for /F "delims=++ tokens=1,2,3" %%I in (%args%) do @(
7 | @set erl_args=%%I
8 | @call :set_trim node_name %%J
9 | @call :set_trim node_root %%K
10 | )
11 |
12 | @set releases_dir=%node_root%\releases
13 |
14 | @rem parse ERTS version and release version from start_erl.dat
15 | @for /F "tokens=1,2" %%I in (%releases_dir%\start_erl.data) do @(
16 | @call :set_trim erts_version %%I
17 | @call :set_trim release_version %%J
18 | )
19 |
20 | @set erl_exe=%node_root%\erts-%erts_version%\bin\erl.exe
21 | @set boot_file=%releases_dir%\%release_version%\%node_name%
22 |
23 | @if exist %releases_dir%\%release_version%\sys.config (
24 | @set app_config=%releases_dir%\%release_version%\sys.config
25 | ) else (
26 | @set app_config=%node_root%\etc\app.config
27 | )
28 |
29 | @if exist %releases_dir%\%release_version%\vm.args (
30 | @set vm_args=%releases_dir%\%release_version%\vm.args
31 | ) else (
32 | @set vm_args=%node_root%\etc\vm.args
33 | )
34 |
35 | @%erl_exe% %erl_args% -boot %boot_file% -config %app_config% -args_file %vm_args%
36 |
37 | :set_trim
38 | @set %1=%2
39 | @goto :EOF
40 |
--------------------------------------------------------------------------------
/src/erws_handler.erl:
--------------------------------------------------------------------------------
1 | -module(erws_handler).
2 | -behaviour(cowboy_http_handler).
3 | -behaviour(cowboy_websocket_handler).
4 | -export([init/3, handle/2, terminate/3]).
5 | -export([
6 | websocket_init/3, websocket_handle/3,
7 | websocket_info/3, websocket_terminate/3
8 | ]).
9 |
10 | init({tcp, http}, _Req, _Opts) ->
11 | {upgrade, protocol, cowboy_websocket}.
12 |
13 |
14 | handle(Req, State) ->
15 | lager:debug("Request not expected: ~p", [Req]),
16 | {ok, Req2} = cowboy_http_req:reply(404, [{'Content-Type', <<"text/html">>}]),
17 | {ok, Req2, State}.
18 |
19 |
20 | websocket_init(_TransportName, Req, _Opts) ->
21 | lager:debug("init websocket"),
22 | {ok, Req, undefined_state}.
23 |
24 | websocket_handle({text, Msg}, Req, State) ->
25 | lager:debug("Got Data: ~p", [Msg]),
26 | {reply, {text, << "responding to ", Msg/binary >>}, Req, State, hibernate };
27 |
28 |
29 | websocket_handle(_Any, Req, State) ->
30 | {reply, {text, << "whut?">>}, Req, State, hibernate }.
31 |
32 | websocket_info({timeout, _Ref, Msg}, Req, State) ->
33 | {reply, {text, Msg}, Req, State};
34 |
35 | websocket_info(_Info, Req, State) ->
36 | lager:debug("websocket info"),
37 | {ok, Req, State, hibernate}.
38 |
39 | websocket_terminate(_Reason, _Req, _State) ->
40 | ok.
41 |
42 | terminate(_Reason, _Req, _State) ->
43 | ok.
44 |
--------------------------------------------------------------------------------
/rel/files/erws.cmd:
--------------------------------------------------------------------------------
1 | @setlocal
2 |
3 | @set node_name=erws
4 |
5 | @rem Get the abolute path to the parent directory,
6 | @rem which is assumed to be the node root.
7 | @for /F "delims=" %%I in ("%~dp0..") do @set node_root=%%~fI
8 |
9 | @set releases_dir=%node_root%\releases
10 |
11 | @rem Parse ERTS version and release version from start_erl.data
12 | @for /F "tokens=1,2" %%I in (%releases_dir%\start_erl.data) do @(
13 | @call :set_trim erts_version %%I
14 | @call :set_trim release_version %%J
15 | )
16 |
17 | @set erts_bin=%node_root%\erts-%erts_version%\bin
18 |
19 | @set service_name=%node_name%_%release_version%
20 |
21 | @if "%1"=="install" @goto install
22 | @if "%1"=="uninstall" @goto uninstall
23 | @if "%1"=="start" @goto start
24 | @if "%1"=="stop" @goto stop
25 | @if "%1"=="restart" @call :stop && @goto start
26 | @if "%1"=="console" @goto console
27 | @rem TODO: attach, ping, restart and reboot
28 |
29 | :usage
30 | @echo Usage: %0 {install|uninstall|start|stop|restart|console}
31 | @goto :EOF
32 |
33 | :install
34 | @%erts_bin%\erlsrv.exe add %service_name% -c "Erlang node %node_name% in %node_root%" -sname %node_name% -w %node_root% -m %node_root%\bin\start_erl.cmd -args " ++ %node_name% ++ %node_root%" -stopaction "init:stop()."
35 | @goto :EOF
36 |
37 | :uninstall
38 | @%erts_bin%\erlsrv.exe remove %service_name%
39 | @%erts_bin%\epmd.exe -kill
40 | @goto :EOF
41 |
42 | :start
43 | @%erts_bin%\erlsrv.exe start %service_name%
44 | @goto :EOF
45 |
46 | :stop
47 | @%erts_bin%\erlsrv.exe stop %service_name%
48 | @goto :EOF
49 |
50 | :console
51 | @start %erts_bin%\werl.exe -boot %releases_dir%\%release_version%\%node_name%
52 | @goto :EOF
53 |
54 | :set_trim
55 | @set %1=%2
56 | @goto :EOF
57 |
--------------------------------------------------------------------------------
/rel/reltool.config:
--------------------------------------------------------------------------------
1 | {sys, [
2 | {lib_dirs, ["..", "../deps", "../.."]},
3 | {erts, [{mod_cond, derived}, {app_file, strip}]},
4 | {app_file, strip},
5 | {rel, "erws", "1", [
6 | kernel,stdlib,sasl,crypto,cowboy,lager,syntax_tools,erws
7 | ]},
8 | {rel, "start_clean", "", [
9 | kernel,stdlib,sasl,crypto,cowboy,lager,syntax_tools,erws
10 | ]},
11 | {boot_rel, "erws"},
12 | {profile, embedded},
13 | {incl_cond, exclude},
14 | {excl_archive_filters, [".*"]}, %% Do not archive built libs
15 | {excl_sys_filters, [
16 | "^bin/.*", "^erts.*/bin/(dialyzer|typer)",
17 | "^erts.*/(doc|info|include|lib|man|src)"
18 | ]},
19 | {excl_app_filters, ["\.gitignore"]},
20 | {app, sasl, [{incl_cond, include}]},
21 | {app, stdlib, [{incl_cond, include}]},
22 | {app, crypto, [{incl_cond, include}]},
23 | {app, kernel, [{incl_cond, include}]},
24 | {app, goldrush, [{incl_cond, include}]},
25 | {app, ranch, [{incl_cond, include}]},
26 | {app, cowlib, [{incl_cond, include}]},
27 | {app, cowboy, [{incl_cond, include}]},
28 | {app, compiler, [{incl_cond, include}]},
29 | {app, syntax_tools, [{incl_cond, include}]},
30 | {app, lager, [{incl_cond, include}]},
31 | {app, erws, [{incl_cond, include}]}
32 | ]}.
33 |
34 | {target_dir, "erws"}.
35 |
36 | {overlay, [
37 | {mkdir, "log/sasl"},
38 | {copy, "files/erl", "\{\{erts_vsn\}\}/bin/erl"},
39 | {copy, "files/nodetool", "\{\{erts_vsn\}\}/bin/nodetool"},
40 | {copy, "files/erws", "bin/erws"},
41 | {copy, "files/sys.config", "releases/\{\{rel_vsn\}\}/sys.config"},
42 | {copy, "files/erws.cmd", "bin/erws.cmd"},
43 | {copy, "files/start_erl.cmd", "bin/start_erl.cmd"},
44 | {copy, "files/vm.args", "releases/\{\{rel_vsn\}\}/vm.args"}
45 | ]}.
46 |
--------------------------------------------------------------------------------
/rel/files/nodetool:
--------------------------------------------------------------------------------
1 | %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
2 | %% ex: ft=erlang ts=4 sw=4 et
3 | %% -------------------------------------------------------------------
4 | %%
5 | %% nodetool: Helper Script for interacting with live nodes
6 | %%
7 | %% -------------------------------------------------------------------
8 |
9 | main(Args) ->
10 | ok = start_epmd(),
11 | %% Extract the args
12 | {RestArgs, TargetNode} = process_args(Args, [], undefined),
13 |
14 | %% See if the node is currently running -- if it's not, we'll bail
15 | case {net_kernel:hidden_connect_node(TargetNode), net_adm:ping(TargetNode)} of
16 | {true, pong} ->
17 | ok;
18 | {_, pang} ->
19 | io:format("Node ~p not responding to pings.\n", [TargetNode]),
20 | halt(1)
21 | end,
22 |
23 | case RestArgs of
24 | ["ping"] ->
25 | %% If we got this far, the node already responsed to a ping, so just dump
26 | %% a "pong"
27 | io:format("pong\n");
28 | ["stop"] ->
29 | io:format("~p\n", [rpc:call(TargetNode, init, stop, [], 60000)]);
30 | ["restart"] ->
31 | io:format("~p\n", [rpc:call(TargetNode, init, restart, [], 60000)]);
32 | ["reboot"] ->
33 | io:format("~p\n", [rpc:call(TargetNode, init, reboot, [], 60000)]);
34 | ["rpc", Module, Function | RpcArgs] ->
35 | case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function),
36 | [RpcArgs], 60000) of
37 | ok ->
38 | ok;
39 | {badrpc, Reason} ->
40 | io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]),
41 | halt(1);
42 | _ ->
43 | halt(1)
44 | end;
45 | ["rpcterms", Module, Function, ArgsAsString] ->
46 | case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function),
47 | consult(ArgsAsString), 60000) of
48 | {badrpc, Reason} ->
49 | io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]),
50 | halt(1);
51 | Other ->
52 | io:format("~p\n", [Other])
53 | end;
54 | Other ->
55 | io:format("Other: ~p\n", [Other]),
56 | io:format("Usage: nodetool {ping|stop|restart|reboot}\n")
57 | end,
58 | net_kernel:stop().
59 |
60 | process_args([], Acc, TargetNode) ->
61 | {lists:reverse(Acc), TargetNode};
62 | process_args(["-setcookie", Cookie | Rest], Acc, TargetNode) ->
63 | erlang:set_cookie(node(), list_to_atom(Cookie)),
64 | process_args(Rest, Acc, TargetNode);
65 | process_args(["-name", TargetName | Rest], Acc, _) ->
66 | ThisNode = append_node_suffix(TargetName, "_maint_"),
67 | {ok, _} = net_kernel:start([ThisNode, longnames]),
68 | process_args(Rest, Acc, nodename(TargetName));
69 | process_args(["-sname", TargetName | Rest], Acc, _) ->
70 | ThisNode = append_node_suffix(TargetName, "_maint_"),
71 | {ok, _} = net_kernel:start([ThisNode, shortnames]),
72 | process_args(Rest, Acc, nodename(TargetName));
73 | process_args([Arg | Rest], Acc, Opts) ->
74 | process_args(Rest, [Arg | Acc], Opts).
75 |
76 |
77 | start_epmd() ->
78 | [] = os:cmd(epmd_path() ++ " -daemon"),
79 | ok.
80 |
81 | epmd_path() ->
82 | ErtsBinDir = filename:dirname(escript:script_name()),
83 | Name = "epmd",
84 | case os:find_executable(Name, ErtsBinDir) of
85 | false ->
86 | case os:find_executable(Name) of
87 | false ->
88 | io:format("Could not find epmd.~n"),
89 | halt(1);
90 | GlobalEpmd ->
91 | GlobalEpmd
92 | end;
93 | Epmd ->
94 | Epmd
95 | end.
96 |
97 |
98 | nodename(Name) ->
99 | case string:tokens(Name, "@") of
100 | [_Node, _Host] ->
101 | list_to_atom(Name);
102 | [Node] ->
103 | [_, Host] = string:tokens(atom_to_list(node()), "@"),
104 | list_to_atom(lists:concat([Node, "@", Host]))
105 | end.
106 |
107 | append_node_suffix(Name, Suffix) ->
108 | case string:tokens(Name, "@") of
109 | [Node, Host] ->
110 | list_to_atom(lists:concat([Node, Suffix, os:getpid(), "@", Host]));
111 | [Node] ->
112 | list_to_atom(lists:concat([Node, Suffix, os:getpid()]))
113 | end.
114 |
115 |
116 | %%
117 | %% Given a string or binary, parse it into a list of terms, ala file:consult/0
118 | %%
119 | consult(Str) when is_list(Str) ->
120 | consult([], Str, []);
121 | consult(Bin) when is_binary(Bin)->
122 | consult([], binary_to_list(Bin), []).
123 |
124 | consult(Cont, Str, Acc) ->
125 | case erl_scan:tokens(Cont, Str, 0) of
126 | {done, Result, Remaining} ->
127 | case Result of
128 | {ok, Tokens, _} ->
129 | {ok, Term} = erl_parse:parse_term(Tokens),
130 | consult([], Remaining, [Term | Acc]);
131 | {eof, _Other} ->
132 | lists:reverse(Acc);
133 | {error, Info, _} ->
134 | {error, Info}
135 | end;
136 | {more, Cont1} ->
137 | consult(Cont1, eof, Acc)
138 | end.
139 |
--------------------------------------------------------------------------------
/rel/files/erws:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # -*- tab-width:4;indent-tabs-mode:nil -*-
3 | # ex: ts=4 sw=4 et
4 |
5 | RUNNER_SCRIPT_DIR=$(cd ${0%/*} && pwd)
6 |
7 | RUNNER_BASE_DIR=${RUNNER_SCRIPT_DIR%/*}
8 | RUNNER_ETC_DIR=$RUNNER_BASE_DIR/etc
9 | RUNNER_LOG_DIR=$RUNNER_BASE_DIR/log
10 | # Note the trailing slash on $PIPE_DIR/
11 | PIPE_DIR=/tmp/$RUNNER_BASE_DIR/
12 | RUNNER_USER=
13 |
14 | # Make sure this script is running as the appropriate user
15 | if [ ! -z "$RUNNER_USER" ] && [ `whoami` != "$RUNNER_USER" ]; then
16 | exec sudo -u $RUNNER_USER -i $0 $@
17 | fi
18 |
19 | # Make sure CWD is set to runner base dir
20 | cd $RUNNER_BASE_DIR
21 |
22 | # Make sure log directory exists
23 | mkdir -p $RUNNER_LOG_DIR
24 | # Identify the script name
25 | SCRIPT=`basename $0`
26 |
27 | # Parse out release and erts info
28 | START_ERL=`cat $RUNNER_BASE_DIR/releases/start_erl.data`
29 | ERTS_VSN=${START_ERL% *}
30 | APP_VSN=${START_ERL#* }
31 |
32 | # Use releases/VSN/vm.args if it exists otherwise use etc/vm.args
33 | if [ -e "$RUNNER_BASE_DIR/releases/$APP_VSN/vm.args" ]; then
34 | VMARGS_PATH="$RUNNER_BASE_DIR/releases/$APP_VSN/vm.args"
35 | else
36 | VMARGS_PATH="$RUNNER_ETC_DIR/vm.args"
37 | fi
38 |
39 | # Use releases/VSN/sys.config if it exists otherwise use etc/app.config
40 | if [ -e "$RUNNER_BASE_DIR/releases/$APP_VSN/sys.config" ]; then
41 | CONFIG_PATH="$RUNNER_BASE_DIR/releases/$APP_VSN/sys.config"
42 | else
43 | CONFIG_PATH="$RUNNER_ETC_DIR/app.config"
44 | fi
45 |
46 | # Extract the target node name from node.args
47 | NAME_ARG=`egrep '^-s?name' $VMARGS_PATH`
48 | if [ -z "$NAME_ARG" ]; then
49 | echo "vm.args needs to have either -name or -sname parameter."
50 | exit 1
51 | fi
52 |
53 | # Extract the target cookie
54 | COOKIE_ARG=`grep '^-setcookie' $VMARGS_PATH`
55 | if [ -z "$COOKIE_ARG" ]; then
56 | echo "vm.args needs to have a -setcookie parameter."
57 | exit 1
58 | fi
59 |
60 | # Add ERTS bin dir to our path
61 | ERTS_PATH=$RUNNER_BASE_DIR/erts-$ERTS_VSN/bin
62 |
63 | # Setup command to control the node
64 | NODETOOL="$ERTS_PATH/escript $ERTS_PATH/nodetool $NAME_ARG $COOKIE_ARG"
65 |
66 | # Check the first argument for instructions
67 | case "$1" in
68 | start)
69 | # Make sure there is not already a node running
70 | RES=`$NODETOOL ping`
71 | if [ "$RES" = "pong" ]; then
72 | echo "Node is already running!"
73 | exit 1
74 | fi
75 | HEART_COMMAND="$RUNNER_BASE_DIR/bin/$SCRIPT start"
76 | export HEART_COMMAND
77 | mkdir -p $PIPE_DIR
78 | shift # remove $1
79 | $ERTS_PATH/run_erl -daemon $PIPE_DIR $RUNNER_LOG_DIR "exec $RUNNER_BASE_DIR/bin/$SCRIPT console $@" 2>&1
80 | ;;
81 |
82 | stop)
83 | # Wait for the node to completely stop...
84 | case `uname -s` in
85 | Linux|Darwin|FreeBSD|DragonFly|NetBSD|OpenBSD)
86 | # PID COMMAND
87 | PID=`ps ax -o pid= -o command=|\
88 | grep "$RUNNER_BASE_DIR/.*/[b]eam"|awk '{print $1}'`
89 | ;;
90 | SunOS)
91 | # PID COMMAND
92 | PID=`ps -ef -o pid= -o args=|\
93 | grep "$RUNNER_BASE_DIR/.*/[b]eam"|awk '{print $1}'`
94 | ;;
95 | CYGWIN*)
96 | # UID PID PPID TTY STIME COMMAND
97 | PID=`ps -efW|grep "$RUNNER_BASE_DIR/.*/[b]eam"|awk '{print $2}'`
98 | ;;
99 | esac
100 | $NODETOOL stop
101 | ES=$?
102 | if [ "$ES" -ne 0 ]; then
103 | exit $ES
104 | fi
105 | while `kill -0 $PID 2>/dev/null`;
106 | do
107 | sleep 1
108 | done
109 | ;;
110 |
111 | restart)
112 | ## Restart the VM without exiting the process
113 | $NODETOOL restart
114 | ES=$?
115 | if [ "$ES" -ne 0 ]; then
116 | exit $ES
117 | fi
118 | ;;
119 |
120 | reboot)
121 | ## Restart the VM completely (uses heart to restart it)
122 | $NODETOOL reboot
123 | ES=$?
124 | if [ "$ES" -ne 0 ]; then
125 | exit $ES
126 | fi
127 | ;;
128 |
129 | ping)
130 | ## See if the VM is alive
131 | $NODETOOL ping
132 | ES=$?
133 | if [ "$ES" -ne 0 ]; then
134 | exit $ES
135 | fi
136 | ;;
137 |
138 | attach)
139 | # Make sure a node IS running
140 | RES=`$NODETOOL ping`
141 | ES=$?
142 | if [ "$ES" -ne 0 ]; then
143 | echo "Node is not running!"
144 | exit $ES
145 | fi
146 |
147 | shift
148 | exec $ERTS_PATH/to_erl $PIPE_DIR
149 | ;;
150 |
151 | console|console_clean)
152 | # .boot file typically just $SCRIPT (ie, the app name)
153 | # however, for debugging, sometimes start_clean.boot is useful:
154 | case "$1" in
155 | console) BOOTFILE=$SCRIPT ;;
156 | console_clean) BOOTFILE=start_clean ;;
157 | esac
158 | # Setup beam-required vars
159 | ROOTDIR=$RUNNER_BASE_DIR
160 | BINDIR=$ROOTDIR/erts-$ERTS_VSN/bin
161 | EMU=beam
162 | PROGNAME=`echo $0 | sed 's/.*\\///'`
163 | CMD="$BINDIR/erlexec -boot $RUNNER_BASE_DIR/releases/$APP_VSN/$BOOTFILE -mode embedded -config $CONFIG_PATH -args_file $VMARGS_PATH -- ${1+"$@"}"
164 | export EMU
165 | export ROOTDIR
166 | export BINDIR
167 | export PROGNAME
168 |
169 | # Dump environment info for logging purposes
170 | echo "Exec: $CMD"
171 | echo "Root: $ROOTDIR"
172 |
173 | # Log the startup
174 | logger -t "$SCRIPT[$$]" "Starting up"
175 |
176 | # Start the VM
177 | exec $CMD
178 | ;;
179 |
180 | *)
181 | echo "Usage: $SCRIPT {start|stop|restart|reboot|ping|console|console_clean|attach}"
182 | exit 1
183 | ;;
184 | esac
185 |
186 | exit 0
187 |
--------------------------------------------------------------------------------