diff --git a/bin/emqx b/bin/emqx index ff12afcac..0662d4a46 100755 --- a/bin/emqx +++ b/bin/emqx @@ -20,6 +20,41 @@ mkdir -p "$RUNNER_LOG_DIR" # Make sure data directory exists mkdir -p "$RUNNER_DATA_DIR" +export ROOTDIR="$RUNNER_ROOT_DIR" +export ERTS_DIR="$ROOTDIR/erts-$ERTS_VSN" +export BINDIR="$ERTS_DIR/bin" +export EMU="beam" +export PROGNAME="erl" +DYNLIBS_DIR="$RUNNER_ROOT_DIR/dynlibs" +ERTS_LIB_DIR="$ERTS_DIR/../lib" +MNESIA_DATA_DIR="$RUNNER_DATA_DIR/mnesia/$NAME" + +# Echo to stderr on errors +echoerr() { echo "$*" 1>&2; } + +check_eralng_start() { + "$BINDIR/$PROGNAME" -noshell -boot "$REL_DIR/start_clean" -s crypto start -s init stop +} + +if ! check_eralng_start >/dev/null 2>&1; then + BUILT_ON="$(head -1 "${REL_DIR}/BUILT_ON")" + ## failed to start, might be due to missing libs, try to be portable + export LD_LIBRARY_PATH="$DYNLIBS_DIR:$LD_LIBRARY_PATH" + if ! check_eralng_start; then + ## it's hopeless + echoerr "FATAL: Unable to start Erlang (with libcrypto)." + echoerr "Please make sure it's running on the correct platform with all required dependencies." + echoerr "This EMQ X release is built for $BUILT_ON" + exit 1 + fi + echoerr "WARNING: There seem to be missing dynamic libs from the OS. Using libs from ${DYNLIBS_DIR}" +fi + +## backward compatible +if [ -d "$ERTS_DIR/lib" ]; then + export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH" +fi + # cuttlefish try to read environment variables starting with "EMQX_" export CUTTLEFISH_ENV_OVERRIDE_PREFIX='EMQX_' @@ -120,9 +155,6 @@ if [ "$ULIMIT_F" -lt 1024 ]; then echo "!!!!" fi -# Echo to stderr on errors -echoerr() { echo "$@" 1>&2; } - # By default, use cuttlefish to generate app.config and vm.args CUTTLEFISH="${USE_CUTTLEFISH:-yes}" @@ -364,15 +396,6 @@ else PROTO_DIST_ARG="-proto_dist $PROTO_DIST" fi -export ROOTDIR="$RUNNER_ROOT_DIR" -export ERTS_DIR="$ROOTDIR/erts-$ERTS_VSN" -export BINDIR="$ERTS_DIR/bin" -export EMU="beam" -export PROGNAME="erl" -export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH" -ERTS_LIB_DIR="$ERTS_DIR/../lib" -MNESIA_DATA_DIR="$RUNNER_DATA_DIR/mnesia/$NAME" - cd "$ROOTDIR" # User can specify an sname without @hostname diff --git a/build b/build index be7813e66..be4f88672 100755 --- a/build +++ b/build @@ -15,18 +15,7 @@ cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" PKG_VSN="${PKG_VSN:-$(./pkg-vsn.sh)}" export PKG_VSN -if [ "$(uname -s)" = 'Darwin' ]; then - SYSTEM=macos -elif [ "$(uname -s)" = 'Linux' ]; then - if grep -q -i 'centos' /etc/*-release; then - DIST='centos' - VERSION_ID="$(rpm --eval '%{centos_ver}')" - else - DIST="$(sed -n '/^ID=/p' /etc/os-release | sed -r 's/ID=(.*)/\1/g' | sed 's/"//g')" - VERSION_ID="$(sed -n '/^VERSION_ID=/p' /etc/os-release | sed -r 's/VERSION_ID=(.*)/\1/g' | sed 's/"//g')" - fi - SYSTEM="$(echo "${DIST}${VERSION_ID}" | sed -r 's/([a-zA-Z]*)-.*/\1/g')" -fi +SYSTEM="$(./scripts/get-distro.sh)" ARCH="$(uname -m)" case "$ARCH" in @@ -46,8 +35,8 @@ export ARCH ## Support RPM and Debian based linux systems ## if [ "$(uname -s)" = 'Linux' ]; then - case "${DIST:-}" in - ubuntu|debian|raspbian) + case "${SYSTEM:-}" in + ubuntu*|debian*|raspbian*) PKGERDIR='deb' ;; *) @@ -98,6 +87,18 @@ make_relup() { ./rebar3 as "$PROFILE" relup --relname emqx --relvsn "${PKG_VSN}" } +cp_dyn_libs() { + local rel_dir="$1" + local target_dir="${rel_dir}/dynlibs" + if ! [ "$(uname -s)" = 'Linux' ]; then + return 0; + fi + mkdir -p "$target_dir" + while read -r so_file; do + cp -L "$so_file" "$target_dir/" + done < <(find "$rel_dir" -type f \( -name "*.so*" -o -name "beam.smp" \) -print0 | xargs -0 ldd | grep -E '^\s+.*=>\s(/lib|/usr)' | awk '{print $3}') +} + ## make_zip turns .tar.gz into a .zip with a slightly different name. ## It assumes the .tar.gz has been built -- relies on Makefile dependency make_zip() { @@ -117,6 +118,9 @@ make_zip() { local zipball zipball="${pkgpath}/${PROFILE}-${SYSTEM}-${PKG_VSN}-${ARCH}.zip" tar zxf "${tarball}" -C "${tard}/emqx" + ## try to be portable for zip packages. + ## for DEB and RPM packages the dependencies are resoved by yum and apt + cp_dyn_libs "${tard}/emqx" (cd "${tard}" && zip -qr - emqx) > "${zipball}" } diff --git a/etc/BUILT_ON b/etc/BUILT_ON index 2997223fa..43a77ec87 100644 --- a/etc/BUILT_ON +++ b/etc/BUILT_ON @@ -1 +1 @@ -{{built_on_arch}} +{{built_on_platform}} diff --git a/rebar.config.erl b/rebar.config.erl index 901027d2d..1000a2c92 100644 --- a/rebar.config.erl +++ b/rebar.config.erl @@ -173,11 +173,24 @@ relx(Vsn, RelType, PkgType) -> , {vm_args,false} , {release, {emqx, Vsn}, relx_apps(RelType)} , {overlay, relx_overlay(RelType)} - , {overlay_vars, [ {built_on_arch, rebar_utils:get_arch()} + , {overlay_vars, [ {built_on_platform, built_on()} , {emqx_description, emqx_description(RelType, IsEnterprise)} | overlay_vars(RelType, PkgType, IsEnterprise)]} ]. +built_on() -> + On = rebar_utils:get_arch(), + case distro() of + false -> On; + Distro -> On ++ "-" ++ Distro + end. + +distro() -> + case os:type() of + {unix, _} -> string:strip(os:cmd("scripts/get-distro.sh"), both, $\n); + _ -> false + end. + emqx_description(cloud, true) -> "EMQ X Enterprise"; emqx_description(cloud, false) -> "EMQ X Broker"; emqx_description(edge, _) -> "EMQ X Edge". diff --git a/scripts/get-distro.sh b/scripts/get-distro.sh new file mode 100755 index 000000000..ae52abba3 --- /dev/null +++ b/scripts/get-distro.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +## This script prints Linux distro name and its version number +## e.g. macos, centos8, ubuntu20.04 + +set -euo pipefail + +if [ "$(uname -s)" = 'Darwin' ]; then + echo 'macos' +elif [ "$(uname -s)" = 'Linux' ]; then + if grep -q -i 'centos' /etc/*-release; then + DIST='centos' + VERSION_ID="$(rpm --eval '%{centos_ver}')" + else + DIST="$(sed -n '/^ID=/p' /etc/os-release | sed -r 's/ID=(.*)/\1/g' | sed 's/"//g')" + VERSION_ID="$(sed -n '/^VERSION_ID=/p' /etc/os-release | sed -r 's/VERSION_ID=(.*)/\1/g' | sed 's/"//g')" + fi + echo "${DIST}${VERSION_ID}" | sed -r 's/([a-zA-Z]*)-.*/\1/g' +fi