2021/12/27

Multiple erlang OTP versions in CentOS7

第一種方式是增加 --libdir

會讓 erlang 24 安裝到 /usr/lib/erlang24/erlang 這個路徑

./configure --prefix=/usr --libdir=/usr/lib/erlang24

另一種方式,還是使用 /usr/lib/erlang,但是在安裝後,將整個目錄複製為獨立的 OTP 目錄,例如安裝了 OTP 24 後,就複製一份為 /usr/lib/erlang24

cp -R /usr/lib/erlang /usr/lib/erlang24

在安裝新的 OTP 前,都先將 /usr/lib/erlang 刪除,安裝後,就可以複製一份該版本的 erlang

otp 20.3

# otp 20 只能使用 wxWidget 3.0
rm -f /usr/local/include/wx
ln -s /usr/local/include/wx-3.0/ /usr/local/include/wx

# 因編譯 wx 會發生錯誤
# 重新安裝 wxWidgets 3.0.3
tar -jxvf wxWidgets-3.0.3.tar.bz2
cd wxWidgets-3.0.3
./configure --with-opengl --enable-debug --enable-unicode --enable-graphics_ctx
make
make install

# 刪除舊的 erlang
rm -rf /usr/lib/erlang

tar zxvf otp_src_20.3.tar.gz
cd otp_src_20.3
./configure --prefix=/usr
make
make install
cd ..

# 備份 otp20.3
cp -R /usr/lib/erlang /usr/lib/erlang20.3

otp 23.3

wxWidget 3.1

## 要先安裝 webkitgtk
# 安裝 nux repo
yum -y install epel-release
rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm

yum -y install webkitgtk webkitgtk-devel

###
rm -f /usr/local/include/wx

cd wxWidgets-3.1.5
./configure --with-gtk --with-opengl --enable-debug --enable-unicode --enable-compat28 --enable-webview

make
make install
cd ..

ln -s /usr/local/include/wx-3.1/ /usr/local/include/wx
############################
# otp 23 使用 wxWidget 3.1
# 刪除舊的 erlang
rm -rf /usr/lib/erlang

tar zxvf otp_src_23.3.tar.gz
cd otp_src_23.3
./configure --prefix=/usr
make
make install
cd ..

# 備份 otp23.3
cp -R /usr/lib/erlang /usr/lib/erlang23.3

otp 24.0


############################
# otp 24 使用 wxWidget 3.1

# 刪除舊的 erlang
rm -rf /usr/lib/erlang

# SCL 提供安裝多個 gcc 版本的方法
yum -y install centos-release-scl

# 安裝 devtoolset-7
yum -y install devtoolset-7

# 啟動 devtoolset-7
scl enable devtoolset-7 bash

# version check
gcc --version
# gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5)


tar zxvf otp_src_24.0.tar.gz
cd otp_src_24.0

./configure --prefix=/usr
make
make install
cd ..

# 備份 otp24.0
cp -R /usr/lib/erlang /usr/lib/erlang24.0

select script

以連結的方式處理不同版本 erlang otp

# otp 20.3
rm -f /usr/lib/erlang
ln -s /usr/lib/erlang20.3 /usr/lib/erlang

# otp 23.3
rm -f /usr/lib/erlang
ln -s /usr/lib/erlang23.3 /usr/lib/erlang

# otp 24.0
rm -f /usr/lib/erlang
ln -s /usr/lib/erlang24.0 /usr/lib/erlang

otp_select.sh

#!/bin/bash

otp20() {
    echo "using erlang 20"
    # otp 20.3
    ln -s /usr/lib/erlang20.3 /usr/lib/erlang
}

otp23() {
    echo "using erlang 23"
    # otp 23.3
    ln -s /usr/lib/erlang23.3 /usr/lib/erlang
}

otp24() {
    echo "using erlang 24"
    # otp 24.0
    ln -s /usr/lib/erlang24.0 /usr/lib/erlang
}

clear() {
    rm -f /usr/lib/erlang
}

status() {
    # https://stackoverflow.com/questions/9560815/how-to-get-erlangs-release-version-number-from-a-shell
    erl -eval '{ok, Version} = file:read_file(filename:join([code:root_dir(), "releases", erlang:system_info(otp_release), "OTP_VERSION"])), io:fwrite(Version), halt().' -noshell
}

case "$1" in
20)
    clear
    otp20
;;
23)
    clear
    otp23
;;
24)
    clear
    otp24
;;
clear)
    clear
;;
status)
    status
;;
*)
    echo "Usage: $0 {20|23|24|clear|status}"
    esac
    exit 0

2021/12/20

OTP 23 in CentOS7

啟動 docket image for testing

#docker run -d --sysctl net.ipv6.conf.all.disable_ipv6=1 --name test -p 20022:22 centos7ssh /usr/sbin/sshd -D
#docker run -d --name test -p 20022:22 centos7ssh /usr/sbin/sshd -D
docker run -d -p 10022:22 -e "container=docker" --privileged=true -v /sys/fs/cgroup:/sys/fs/cgroup --name test centosssh /usr/sbin/init

docker exec -it test /bin/bash

Preparation

安裝 libraries

# wxWidget library
yum -y install gtk2-devel binutils-devel

yum -y install gcc gcc-c++ glibc-devel make ncurses-devel openssl-devel autoconf git bzip2

# 先裝 OpenGL 相關函式庫,FOP是用來產生文件
yum -y install mesa* fop unixODBC*

download OTP, wxWidget source

wget https://erlang.org/download/otp_src_23.3.tar.gz
#wget https://erlang.org/download/otp_src_24.0.tar.gz

wget https://github.com/wxWidgets/wxWidgets/releases/download/v3.1.5/wxWidgets-3.1.5.tar.bz2

wxWidgets

yum remove wx*

設定 lib path,新增檔案並填寫一行 /usr/local/lib

vi /etc/ld.so.conf.d/locallib.conf
# 內容為
/usr/local/lib
ldconfig

note: 後面有因為一些狀況,重新編譯 wxWidgets

tar -jxvf wxWidgets-3.1.5.tar.bz2
cd wxWidgets-3.1.5
./configure --with-gtk --with-opengl --enable-debug --enable-unicode --enable-compat28
make
make install


ln -s /usr/local/include/wx-3.1/ /usr/local/include/wx

cd ..

openjdk

# 1.8
#yum -y install java-1.8.0-openjdk  java-1.8.0-openjdk-devel

# 11
yum -y install java-11-openjdk java-11-openjdk-devel

以 alternatives 調整執行檔的目標

alternatives --config java
alternatives --config javac
alternatives --config javadoc
alternatives --config javah
alternatives --config javap

設定環境變數

vi /etc/profile

export JAVA_HOME=/usr/lib/jvm/java-openjdk
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin


source /etc/profile

erlang OTP 23

如果不指定 --libdir 會造成 /usr/lib/erlang/lib 裡面的 library 混雜了不同版本的 erlang library,使用時,有可能會發生 ebeam 版本檢查錯誤,因為使用 otp 23 的 erl,但是引用了 otp 24 的 library

tar zxvf otp_src_23.3.tar.gz
cd otp_src_23.3

# 先將 /usr/lib/erlang 目錄,修改為原本的 erlang otp 的獨立資料夾
mv /usr/lib/erlang /usr/lib/erlang20.3

# 增加 --libdir,會讓 erlang 23 安裝到 /usr/lib/erlang23/erlang 這個路徑
#./configure --prefix=/usr --libdir=/usr/lib/erlang23
./configure --prefix=/usr
make
make install
cd ..

erlang OTP 24

tar zxvf otp_src_24.0.tar.gz
cd otp_src_24.0

# 先將 /usr/lib/erlang 目錄,修改為原本的 erlang otp 的獨立資料夾
mv /usr/lib/erlang /usr/lib/erlang23.3

# 增加 --libdir,會讓 erlang 24 安裝到 /usr/lib/erlang24/erlang 這個路徑
#./configure --prefix=/usr --libdir=/usr/lib/erlang24
./configure --prefix=/usr
make
make install
cd ..

編譯 OTP 24 會出現 error

wx             : wxWidgets was not compiled with --enable-webview or wxWebView developer package is not installed, wxWebView will NOT be available
erts           :
                 JIT disabled due to lack of compiler with C++17 support

Patch1: 要重編譯 wxWidget,且要先安裝 webkitgtk

nux webkitgtk

# 安裝 nux repo
yum -y install epel-release
rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm

yum -y install webkitgtk webkitgtk-devel
# --enable-webview
cd wxWidgets-3.1.5
./configure --with-gtk --with-opengl --enable-debug --enable-unicode --enable-compat28 --enable-webview

make
make install
cd ..

Patch2: JIT 支援問題,要安裝 GCC 7.3 支援 C++17

可不管 JIT disabled due to lack of compiler with C++17 support warning,直接 make

Centos 7 GCC 7.3 compiler installation method and C++17 standard test example

How to Install GCC Compiler on CentOS 7

CentOS 7 預設為 gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)

Software Collections SCL 提供安裝多個 gcc 版本的方法

yum -y install centos-release-scl

目前有兩個 Developer Toolset collections

  • Developer Toolset 7
  • Developer Toolset 6
# 安裝
yum -y install devtoolset-7

# 啟動 devtoolset-7
scl enable devtoolset-7 bash

# version check
gcc --version
# gcc (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5)

RabbitMQ

如果要安裝 RabbitMQ,要先參考

Signatures

RabbitMQ Erlang Version Requirements 確認 Erlang 跟 RabbitMQ 的版本匹配

Downloading and Installing RabbitMQ

yum install socat

rpm --import https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc

wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.19/rabbitmq-server-3.8.19-1.el7.noarch.rpm
rpm --nodeps -Uvh rabbitmq-server-3.8.19-1.el7.noarch.rpm
rabbitmq-plugins enable rabbitmq_management
http://localhost:15672/
#新增一個帳號

rabbitmqctl add_user admin password
rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
rabbitmqctl set_user_tags admin administrator

rabbitmqctl delete_user guest
rabbitmqctl list_users
systemctl start rabbitmq-server
systemctl status rabbitmq-server
systemctl enable rabbitmq-server

References

CentOS builds wxWidgets, erlang, RabbitMQ (stand-alone version) from scratch (super detailed and absolute build from scratch)

2021/12/13

rebar3 release

rebar3

Commands

  • as

後面接 profile name,就是以該 profile 運作

  • compile

在確認所有 dependencies 都存在時,可編譯所有 dependencies, 專案的 .app.src 及 .erl

Option Type Description
-d/--deps_only none Only compile dependencies
  • clean

移除 beam files

rebar3 clean 只會清除 default profile

rebar3 as test clean 會清除 test profile

Option Type Description
--all/-a none Clean all apps, including the dependencies
--apps Comma separated list of strings Clean a specific list of apps or dependencies
--profile/-p string Specify a profile (alternative to rebar3 as clean)
  • ct

執行 test/ 目錄下面的 common tests

options 裡面有全部 ct_run 的 options

Option Type Description
--dir Comma separated list of strings 編譯/執行某目錄的 all test suites
--suite Comma separated list of strings 編譯/執行特定 test suites,可用絕對/相對路徑
--group Comma separated list of strings Test groups to run. See the Common Test Documentation.
--case Comma separated list of strings List of test cases to run. See the Common Test Documentation.
--spec Comma separated list of strings List of Test Specifications
--join_specs Comma separated list of strings 類似 --spec 但把所有 spec 整合成一個
--repeat Integer 多久重複 tests 一次
--duration String (format: HHMMSS) 可容許 test 運作最長的時間
--until String (format: HHMMSS) 執行 test 到什麼時間
--force_stop `true false
--multiply_timetraps Integer 以特定乘數擴充test 的 timeout values
--scale_timetraps Boolean 在 code coverage/tracing 時,使用automatic timeout value scaling
--abort_if_missing_suites Boolean 如果 test suite 不存在,要不要放棄(Default: true)
--sys_config String 執行 test 時要使用的 config file list (like sys.config)
--config Comma separated list of strings 執行 test 使用的 config files,ref: Common Test Documentation
--allow_user_terms Boolean 可自訂 config values in config files ref: Common Test Documentation.
--decrypt_key String 設定解密的 key
--decrypt_file String 設定解密的 key file
--logdir String 寫入 test logs 的目錄 ref: Common Test Documentation. Default: _build/test/logs
--logopts Comma separated list of strings 設定 common test logging options. ref: Common Test Documentation. Default: _build/test/logs
--readable Boolean 在 report 增加 test names, Default: true
--verbose, -v Boolean 啟用 verbose output Default: false
--verbosity Integer 設定 log verbosity level
--cover, -c Boolean 產生 cover data
--cover_export_name String 修改 code coverage filename
--label String Set a test label
--basic_html Boolean show basic HTML
--stylesheet String CSS stylesheet to apply to HTML output
--create_priv_dir `auto_per_run auto_per_tc
--include String 設定 include files 的目錄
--name, --sname String 以某個名稱啟動 a distributed node
--setcookie String 設定 cookie
--compile_only Boolean 以特定 test config 編譯專案,但不執行 test
  • cover

由 Common Test/Enuit test suite 產生 coverage analysis

rebar3 do ct, cover

rebar3 do eunit, cover

rebar3 do eunit, ct, cover

其中 rebar.config 有設定 {cover_enabled, true},會產生 html report

Option Type Description
-m, --min_coverage Integer Mandate a coverage percentage required to succeed (0..100)
--reset, -r none Resets all cover data
--verbose, -v none Prints coverage analysis in the terminal.

可用 {cover_excl_mods, [Modules]}{cover_excl_apps, [AppNames]} 做 blacklist

  • deps

列出 dependencies,以及是否有 locked

  • do

依序執行 tasks

rebar3 do a,b,c
  • dialyzer

產生 suitable PLT (Persistent Lookup Table)

檔名 <prefix>_<otp_release>_plt

Option Type Description Default
--update-plt, -u boolean Enable updating the PLT. true
--succ-typings, -s boolean Enable success typing analysis. true
  • edoc

  • escriptize

產生 escript beam files

example from relx

{escript_emu_args, "%%! +sbtu +A0 -noinput\n"}.
{escript_incl_apps, [getopt, erlware_commons, bbmustache, providers, relx]}.
  • eunit

在 test profile 運作

Config Option Type Description
--cover, -c Boolean Generate cover data
--verbose, -v Boolean Verbose output
--app Comma separated list of strings List of applications to run tests for. Equivalent to EUnit’s [{application, App}].
--suite Comma separated list of strings List of test suites to run. Equivalent to EUnit’s [{module, Suite}].
--file, -f Comma separated list of strings List of files to run (such as test/my_tests.beam), equivalent to Eunit’s [{file, File}].
  • get-deps

取 dependencies

  • help

  • new

new project from templates

  • path

列印目前 profile 的 dirs

Option Type Description
--app Comma separated list of strings Comma separated list of applications to return paths for.
--base none Return the base path of the current profile.
--bin none Return the bin path of the current profile.
--ebin none Return all ebin paths of the current profile’s applications.
--lib none Return the lib path of the current profile.
--priv none Return the priv path of the current profile.
--separator, -s string In case of multiple return paths, the separator character to use to join them.
--src none Return the src path of the current profile’s applications.
--rel none Return the rel path of the current profile.
  • release

build release of project

  • relup

產生 relup

  • report

產生 bug report

  • shell

啟動包含 app, deps 的 shell

Option Type Description
--config string Allows to load a config file, if any. Defaults to the sys_config entry defined for relx if present.
--name, --sname atom Starts the node in network mode. Equivalent to erl’s -name and -sname options.
--setcookie string Sets the cookie for a distributed node. Equivalent to erl’s -setcookie option
--script string path to an escript to be evaluated before applications are started
--apps string Comma-separated list of application names to be booted. Defaults to the apps in the relx release if present.
--start-clean When specified, no apps are booted by the shell; useful to override release or shell tuple configurations in rebar.config
--relname, -r atom If multiple releases are present, specify which one to pick
--relvsn, -v string If multiple releases are present, specify which version to use
--env-file string Path to file of os environment variables to setup before expanding vars in config files
--user_drv_args string Arguments passed to user_drv start function for creating custom shells

可呼叫 r3:compile() r3:upgrade() 自動編譯, 更新 reload new modules

  • tar

產生 release 的 tar archive

  • tree

tree of dependencies

Option Type Description
-v, --verbose none Print repo and branch/tag/ref for git and hg deps
  • lock

將 unbuilt dependencies 新增到 rebar.lock

  • unlock

  • update

更新 package index

  • upgrade

更新 dependenies libraries

  • version

  • xref

cross reference analysis

Releases

release 就是 a set of applications for booting Erlang VM and start project

.erl 檔案描述,會產生 .script.boot

boot file 是 script 的 binary form,給 Erlang Run-Time System (ERTS) 使用

target system 是可在另一台機器啟動的 Erlang system,通常會包裝 ERTS 進去

  • relx

在 rebar.config 增加 relx 段落

{relx, [{release, {<release name>, "0.0.1"},
         [<app>]},
        {release, {<other release name>, "0.1.0"},
         [<app>]},

        {dev_mode, true},
        {include_erts, false},

        {extended_start_script, true}]}.

執行 rebar3 release 就會產生 release package 到 _build/<profile>/rel/<release name>/bin/<release name>

可指定多個 release name

可對 release 設定不同 options

{relx, [{release, {<release name>, "0.0.1"},
         [<app>],
         [{dev_mode, false},
          {include_erts, true}]},
        {release, {<release name>, "0.1.0"},
         [<app>],
         [{dev_mode, true}]}
       ]}.

build release

rebar3 release -n <release_name>
  • Build Configuration

包含 source code

{include_src, false}

排除 application

{exclude_apps, [app1, app2]}

排除 module

{exclude_modules, [
    {app1, [app1_mod1, app1_mod2]},
    {app2, [app2_mod1, app2_mod2]}
]}.

Modes

{relx, [...
        {mode, <mode>},
        ...
       ]
}.
Mode Expanded Options
dev [{dev_mode, true}, {include_src, true}, {debug_info, keep}, {include_erts, false}]
prod [{include_src, false}, {debug_info, strip}, {include_erts, true}, {dev_mode, false}]
minimal [{include_src, false}, {debug_info, strip}, {include_erts, false}, {dev_mode, false}]

minimal 沒有 erlang runtime,其他跟 prod 一樣

可覆寫 option

[
  {mode, prod},
  {debug_info, keep}
]

Verification Checks

relx 預設會檢查module 使用的 external functions,因此會出現 warning

這可協助避免沒有在 .app.src 宣告 applications

可移除這個檢查

{check_for_undefined_functions, false}

如果 source code 遺失,會產生 warning

{src_tests, true}

Runtime Configuration

relx 會提供預設的 vm.args,裡面有 node name 及 cookie

## Name of the node
-name {{release_name}}@127.0.0.1

## Cookie for distributed Erlang
-setcookie {{release_name}}

如要使用自訂的 vm.args 或 vm.args.src

{vm_args, "config/vm_prod.args"}

{vm_args_src, "config/vm_prod.args.src"}

Application Configuration

config/sys.config.src or config/sys.config

[
  {<app_name>, [{<key>, <val>}, ...]}
].

可修改設定位置

{sys_config, "config/sys_prod.config"}

{sys_config_src, "config/sys_prod.config.src"}

Environment Variable Replacement

OTP-21+ & rebar3 3.6+

可設定 sys_config_src vm_args_src 設定檔名

設定裡面可用 ${VARIABLE} 取得環境變數

rebar3 v3.14.0 以後,會自動 include config/sys.config.srcconfig/vm.args.src

%% sys.config.src
[
  {appname, [{port, ${PORT}}]}
].
# vm.args.src
-name ${NODE_NAME}
%% rebar.config
{relx, [{release, {<release name>, "0.0.1"},
         [<app>]},

        {mode, dev}]}.

OTP-21 and Rebar3 3.6 以前

要設定 RELX_REPLACE_OS_VARS=true

# vm.args
-name ${NODE_NAME}
%% sys.config
[
 {appname, [{port, "${PORT}"}]}
].

可透過環境變數啟動不同的 node name

#!/bin/bash

export RELX_REPLACE_OS_VARS=true

for i in `seq 1 10`;
do
    NODE_NAME=node_$i PORT=808$i _build/default/rel/<release>/bin/<release> foreground &
    sleep 1
done

Overlays: Build-Time Configuration

example:

{relx, [
    ...
    {overlay_vars, "vars.config"},
    {overlay, [{mkdir, "log/sasl"},
               {template, "priv/app.config", "etc/app.config"},
               {copy, "Procfile", "Procfile"}]}
]}.

template 類似 copy,但有支援變數擴展

內建的變數

Name Description
log The current log level in the format of (<logname>:<loglevel>)
output_dir The current output directory for the built release
target_dir The same as output_dir; exists for backwards compatibility
overridden The current list of overridden apps (a list of app names)
goals The list of user-specified goals in the system
lib_dirs The list of library directories, both user-specified and derived
config_file The list of config file used in the system
providers The list of provider names used for this run of relx
sys_config The location of the sys.config file
root_dir The root dir of the current project
default_release_name The current default release name for the relx run
default_release_version The current default release version for the relx run
default_release The current default release for the relx run
release_erts_version The version of the Erlang Run-Time System in use
erts_vsn The same as release_erts_version (for backwards compatibility)
release_name The currently executing release
release_version The currently executing version
rel_vsn Same as release_version. Exists for backwards compatibility
release_applications A list of applications included in the release
%% base.config
{data_dir, "/data/yolo_app"}.
{version, "1.0.0"}.
{run_user, "root"}.


%% dev.config
%% Include the base config
"./base.config".
%% The build we have
{build, "dev"}.


%% prod.config
%% Include the base config
"./base.config".
%% The build we have
{build, "prod"}.

Deployable Tarball

With ERTS

rebar3 as prod tar

會產生 myrel-0.1.0.tar.gz

可在另一台機器上

$ mkdir myrel
$ mv myrel-0.1.0.tar.gz myrel/
$ cd myrel
$ tar -zxvf myrel-0.1.0.tar.gz
$ bin/myrel console

Without ERTS

{profiles, [{prod, [{relx, [{mode, minimal},
                            {system_libs, false}]}]}]}.

%% 或自行設定 include_erts
{profiles, [{prod, [{relx, [{include_erts, false},
                            {system_libs, false}]}]}]}

tar.gz 裡面就不會包含 kernel 與 stdlib

With ERTS Built for Another System

{include_erts, "/path/to/erlang"},
{system_libs, "/path/to/erlang"},

Extended Start Script

Command Description
foreground Start release with output to stdout
remote Connect remote shell to running node
console Start the release with an interactive shell
console_clean Start an interactive shell without the release’s applications
rpc [Mod [Fun [Args]]]] Run apply(Mod, Fun, Args) on running node
eval [Exprs] Run expressions on running node
status Verify node is running and then run status hook scripts
restart Restart the applications but not the VM
reboot Reboot the entire VM
stop Stop the running node
pid Print the PID of the OS process
ping Print pong if the node is alive
daemon Start release in the background with run_erl (named pipes)
daemon_attach Connect to node started as daemon with to_erl (named pipes)

Release Handling: Install, Upgrade

Command Description
unpack [Version] Unpack a release tarball
install [Version] Install a release
uninstall [Version] Uninstall a release
upgrade [Version] Upgrade the running release to a new version
downgrade [Version] Downgrade the running release to a new version
versions Print versions of the release available
  1. Installing

    bin/myrel install 0.0.1
  2. Listing

    bin/myrel versions
  3. Upgrading

    bin/myrel upgrade 0.0.2
  4. Downgrading

    bin/myrel downgrade 0.0.1

Hooks

可在 start, stop, install_upgrade 的 pre, post 擴充 hooks

功能

  1. pid 可將 BEAM pid 寫入某設定位置 預設為 /var/run/<rel_name>.pid
  2. wait_for_vm_start 等待 vm 啟動 (可被 ping)
  3. wait_for_process 等待某個 configurable name 在 process registry 中出現
{extended_start_script_hooks, [
  {pre_start, [{custom, "hooks/pre_start"}]},
  {post_start, [
    {pid, "/tmp/foo.pid"},
    {wait_for_process, some_process},
    {custom, "hooks/post_start"}
  ]},
  {pre_stop, [
    {custom, "hooks/pre_stop"}]},
    {post_stop, [{custom, "hooks/post_stop"}]},
  ]},
  {post_stop, [{custom, "hooks/post_stop"}]}
]}.

Extensions

可管理 releases: foreground, stop, restart

擴充指令,增加 status,實際上呼叫 extensions/status shell script

%% start script extensions
{extended_start_script_extensions, [
   {status, "extensions/status"}
]}.

%% 因為是相對路徑,可能需要複製
{copy, "scripts/extensions/status", "bin/extensions/status"},

example of status

#!/bin/bash

case $1 in
    help)
        echo "bin/gameserver status"
        ;;
    *)
        ;;
esac

# get the status tuple from gameserver
Status=$(relx_nodetool eval "pool_debug:status(json).")

# now print it out
code="Json = binary_to_list($Status),
      io:format(\"~p~n\", [Json]),
      halt()."
echo $(erl -boot no_dot_erlang -sasl errlog_type error -noshell -eval "$code")

References

rebar3 docs

eeeggghit rebar3

Erlang:Rebar3的简单使用

Automatic release upgrades in Erlang

relx