{"id":7155,"date":"2020-11-23T10:44:29","date_gmt":"2020-11-23T02:44:29","guid":{"rendered":"https:\/\/blog.hoyo.idv.tw\/?p=7155"},"modified":"2022-06-07T10:22:39","modified_gmt":"2022-06-07T02:22:39","slug":"mqtt-4-mqtt-broker","status":"publish","type":"post","link":"https:\/\/blog.hoyo.idv.tw\/?p=7155","title":{"rendered":"MQTT - 4. MQTT Broker"},"content":{"rendered":"<p>--<\/p>\n<h2>MQTT broker<\/h2>\n<ul>\n<li><a href=\"https:\/\/blog.autsoft.hu\/choosing-an-mqtt-broker-for-your-iot-project\/\" target=\"_blank\" rel=\"noopener\">Choosing an MQTT broker for your IoT project<\/a>\n<ul>\n<li><a href=\"https:\/\/mosquitto.org\/\" target=\"_blank\" rel=\"noopener\">Mosquitto<\/a><\/li>\n<li><a href=\"https:\/\/www.rabbitmq.com\/\" target=\"_blank\" rel=\"noopener\">RabbitMQ<\/a><\/li>\n<li><a href=\"http:\/\/emqtt.io\/\" target=\"_blank\" rel=\"noopener\">EMQ<\/a><\/li>\n<li><a href=\"https:\/\/vernemq.com\/\" target=\"_blank\" rel=\"noopener\">VerneMQ<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a class=\"\" href=\"https:\/\/github.com\/mqtt\/mqtt.github.io\" target=\"_blank\" rel=\"noopener\" data-pjax=\"#js-repo-pjax-container\">brokers \u00b7 mqtt\/mqtt.github.io Wiki \u00b7 GitHub<\/a><\/li>\n<\/ul>\n<p>Broker \u5e7e\u4e4e\u90fd\u662f Erlang \u7684\u5929\u4e0b<\/p>\n<p>\u5f8c\u7e8c\u8003\u91cf MySQL \u8eab\u4efd\u8a8d\u8b49\u3001SSL\u3001\u5e73\u53f0\u652f\u63f4\u3001ACL \u8a02\u95b1\u9650\u5236\uff0c\u6700\u5f8c\u9078\u64c7 EMQ X<\/p>\n<p>--<\/p>\n<h2>EMQ X<\/h2>\n<p>\u4e0d\u5f97\u4e0d\u8aaa\uff0c\u5927\u9678\u7684\u8edf\u9ad4\u5c31\u662f\u597d\u7528\uff0c\u8a2d\u60f3\u7684\u8f03\u70ba\u5468\u5168\uff0c\u6587\u4ef6\u4e5f\u9f4a\u5168\uff0c\u5e73\u53f0\u652f\u63f4\u6027\u4e5f\u5b8c\u6574<\/p>\n<ul>\n<li><a href=\"https:\/\/www.emqx.io\/\" target=\"_blank\" rel=\"noopener\">MQTT Broker for IoT in 5G Era | EMQ<\/a><\/li>\n<li><a href=\"https:\/\/www.emqx.io\/downloads#broker\" target=\"_blank\" rel=\"noopener\">EMQ X Broker Open source MQTT message broker<\/a><\/li>\n<\/ul>\n<p>CentOS 7<\/p>\n<pre class=\"lang:default decode:true\"># wget https:\/\/www.emqx.io\/downloads\/broker\/v4.2.3\/emqx-centos7-4.2.3-x86_64.rpm\r\n# rpm -ivh emqx-centos7-4.2.3-x86_64.rpm\r\n# emqx start<\/pre>\n<p>Ubuntu 20<\/p>\n<pre class=\"lang:default decode:true\"># wget https:\/\/www.emqx.io\/cn\/downloads\/broker\/v4.2.2\/emqx-ubuntu20.04-4.2.2-x86_64.deb\r\n# dpkg -i emqx-ubuntu20.04-4.2.2-x86_64.deb\r\n# emqx start<\/pre>\n<p>--<\/p>\n<h2>VerneMQ<\/h2>\n<p>CentOS 7<\/p>\n<div class=\"reset-3c756112--pageItemWithChildren-56f27afc\" draggable=\"true\">\n<div class=\"reset-3c756112\">\n<div class=\"reset-3c756112--pageItem-01e3f344\">\n<ul>\n<li class=\"reset-3c756112--pageComponent-7cc5301a\"><a class=\"navButton-94f2579c--navButtonClickable-161b88ca--navButtonOpened-6a88552e\" href=\"https:\/\/docs.vernemq.com\/installation\/centos_and_redhat\" target=\"_blank\" rel=\"noopener\"><span class=\"text-4505230f--UIH300-2063425d--textContentFamily-49a318e1--navButtonLabel-14a4968f\">Installing on CentOS and RHEL<\/span><\/a><\/li>\n<\/ul>\n<p>\u4e0b\u8f09\u5b89\u88dd\u5f8c\u4e0d\u8981\u50bb\u50bb\u7684\u6309\u7167\u5b98\u65b9\u7684\u8aaa\u6cd5\u76f4\u63a5\u555f\u52d5\u670d\u52d9\uff0c\u90a3\u662f\u4e0d\u6703\u6210\u529f\u7684\uff0c\u9084\u8981\u5148\u8a2d\u5b9a\u8a2d\u5b9a\u6a94\u624d\u884c<\/p>\n<\/div>\n<\/div>\n<\/div>\n<pre class=\"lang:default decode:true\">-- Unit vernemq.service has begun starting up.\r\nNov 15 14:39:18 hoyoserver vernemq[3427]: Before you can continue, the product license\r\nNov 15 14:39:18 hoyoserver vernemq[3427]: must be accepted. The license can be viewed at\r\nNov 15 14:39:18 hoyoserver vernemq[3427]: https:\/\/vernemq.com\/end-user-license-agreement\r\nNov 15 14:39:18 hoyoserver vernemq[3427]: If you do not accept this license you will\r\nNov 15 14:39:18 hoyoserver vernemq[3427]: not be able to use VerneMQ.\r\nNov 15 14:39:18 hoyoserver vernemq[3427]: Accepting the product license will modify the\r\nNov 15 14:39:18 hoyoserver vernemq[3427]: VerneMQ config file\r\nNov 15 14:39:18 hoyoserver vernemq[3427]: \/etc\/vernemq\/vernemq.conf\r\nNov 15 14:39:18 hoyoserver systemd[1]: vernemq.service: control process exited, code=exited status=2\r\nNov 15 14:39:18 hoyoserver vernemq[3427]: setting the \"accept_eula\" config to \"yes\".\r\nNov 15 14:39:18 hoyoserver vernemq[3427]: Product license not accepted. Stopping.\r\nNov 15 14:39:18 hoyoserver systemd[1]: Failed to start VerneMQ Server.<\/pre>\n<pre class=\"lang:default decode:true\"># vi \/etc\/vernemq\/vernemq.conf<\/pre>\n<pre class=\"lang:default decode:true\">accept_eula = yes\r\nlistener.tcp.default = 0.0.0.0:1883<\/pre>\n<p><strong>Ubuntu 20 - Docker<\/strong><\/p>\n<p>\u4f7f\u7528 dpkg \u5b89\u88dd deb \uff0c\u51fa\u73fe libss \u7248\u672c\u4e0d\u7b26\u932f\u8aa4\uff0c\u76ee\u524d\u627e\u4e0d\u5230\u89e3\u6c7a\u65b9\u6cd5\uff0c\u6539\u63a1 Docker \u65b9\u5f0f\u4f7f\u7528<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.vernemq.com\/installation\/docker\" target=\"_blank\" rel=\"noopener\">Running VerneMQ using Docker<\/a><\/li>\n<li><a href=\"https:\/\/hub.docker.com\/r\/erlio\/docker-vernemq\" target=\"_blank\" rel=\"noopener\">erlio\/docker-vernemq<\/a><\/li>\n<li><a class=\"question-hyperlink\" href=\"https:\/\/stackoverflow.com\/questions\/29957143\/make-docker-use-ipv4-for-port-binding\" target=\"_blank\" rel=\"noopener\">Make docker use IPv4 for port binding<\/a><\/li>\n<\/ul>\n<pre class=\"lang:default decode:true\"># docker run -p 1883:1883 -p 8888:8888 -e \"DOCKER_VERNEMQ_ACCEPT_EULA=yes\" -e \"DOCKER_VERNEMQ_ALLOW_ANONYMOUS=on\" --name vernemq1 -d vernemq\/vernemq<\/pre>\n<p>\u4f7f\u7528 netstat \u67e5\u8a62\u8f49\u5740\u7121\u6cd5\u5224\u65b7\uff0c\u76f4\u63a5\u6e2c\u8a66\u4f7f\u7528\u5373\u53ef<\/p>\n<p>\u958b\u6a5f\u555f\u52d5<\/p>\n<pre class=\"lang:default decode:true \"># docker update --restart=always &lt;CONTAINER ID&gt;<\/pre>\n<p><strong>Dockerfile<\/strong><\/p>\n<ul>\n<li><a class=\"js-navigation-open link-gray-dark\" title=\"Dockerfile\" href=\"https:\/\/github.com\/vernemq\/docker-vernemq\/blob\/master\/Dockerfile\" target=\"_blank\" rel=\"noopener\">Dockerfile<\/a><\/li>\n<\/ul>\n<pre class=\"lang:default decode:true\">FROM debian:stretch-slim\r\n\r\nRUN apt-get update &amp;&amp; \\\r\n    apt-get -y install bash procps openssl iproute2 curl jq libsnappy-dev net-tools &amp;&amp; \\\r\n    rm -rf \/var\/lib\/apt\/lists\/* &amp;&amp; \\\r\n    addgroup --gid 10000 vernemq &amp;&amp; \\\r\n    adduser --uid 10000 --system --ingroup vernemq --home \/vernemq --disabled-password vernemq\r\n\r\nWORKDIR \/vernemq\r\n\r\n# Defaults\r\nENV DOCKER_VERNEMQ_KUBERNETES_LABEL_SELECTOR=\"app=vernemq\" \\\r\n    DOCKER_VERNEMQ_LOG__CONSOLE=console \\\r\n    PATH=\"\/vernemq\/bin:$PATH\" \\\r\n    VERNEMQ_VERSION=\"1.11.0\"\r\n\r\nCOPY --chown=10000:10000 bin\/vernemq.sh \/usr\/sbin\/start_vernemq\r\nCOPY --chown=10000:10000 files\/vm.args \/vernemq\/etc\/vm.args\r\nADD https:\/\/github.com\/vernemq\/vernemq\/releases\/download\/$VERNEMQ_VERSION\/vernemq-$VERNEMQ_VERSION.stretch.tar.gz \/tmp\r\n\r\nRUN tar -xzvf \/tmp\/vernemq-$VERNEMQ_VERSION.stretch.tar.gz &amp;&amp; \\\r\n    rm \/tmp\/vernemq-$VERNEMQ_VERSION.stretch.tar.gz &amp;&amp; \\\r\n    chown -R 10000:10000 \/vernemq &amp;&amp; \\\r\n    ln -s \/vernemq\/etc \/etc\/vernemq &amp;&amp; \\\r\n    ln -s \/vernemq\/data \/var\/lib\/vernemq &amp;&amp; \\\r\n    ln -s \/vernemq\/log \/var\/log\/vernemq\r\n\r\n# Ports\r\n# 1883  MQTT\r\n# 8883  MQTT\/SSL\r\n# 8080  MQTT WebSockets\r\n# 44053 VerneMQ Message Distribution\r\n# 4369  EPMD - Erlang Port Mapper Daemon\r\n# 8888  Prometheus Metrics\r\n# 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109  Specific Distributed Erlang Port Range\r\n\r\nEXPOSE 1883 8883 8080 44053 4369 8888 \\\r\n       9100 9101 9102 9103 9104 9105 9106 9107 9108 9109\r\n\r\n\r\nVOLUME [\"\/vernemq\/log\", \"\/vernemq\/data\", \"\/vernemq\/etc\"]\r\n\r\nHEALTHCHECK CMD vernemq ping | grep -q pong\r\n\r\nUSER vernemq\r\n\r\nCMD [\"start_vernemq\"]<\/pre>\n<ul>\n<li>\u555f\u52d5\u81ea\u52d5\u57f7\u884c \/usr\/sbin\/start_vernemq<\/li>\n<\/ul>\n<p>start_vernemq<\/p>\n<pre class=\"lang:sh decode:true\">#!\/usr\/bin\/env bash\r\n\r\nNET_INTERFACE=$(route | grep '^default' | grep -o '[^ ]*$')\r\nNET_INTERFACE=${DOCKER_NET_INTERFACE:-${NET_INTERFACE}}\r\nIP_ADDRESS=$(ip -4 addr show ${NET_INTERFACE} | grep -oE '[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}' | sed -e \"s\/^[[:space:]]*\/\/\" | head -n 1)\r\nIP_ADDRESS=${DOCKER_IP_ADDRESS:-${IP_ADDRESS}}\r\n\r\n# Ensure the Erlang node name is set correctly\r\nif env | grep \"DOCKER_VERNEMQ_NODENAME\" -q; then\r\n    sed -i.bak -r \"s\/-name VerneMQ@.+\/-name VerneMQ@${DOCKER_VERNEMQ_NODENAME}\/\" \/vernemq\/etc\/vm.args\r\nelse\r\n    if [ -n \"$DOCKER_VERNEMQ_SWARM\" ]; then\r\n        NODENAME=$(hostname -i)\r\n        sed -i.bak -r \"s\/VerneMQ@.+\/VerneMQ@${NODENAME}\/\" \/etc\/vernemq\/vm.args\r\n    else\r\n        sed -i.bak -r \"s\/-name VerneMQ@.+\/-name VerneMQ@${IP_ADDRESS}\/\" \/vernemq\/etc\/vm.args\r\n    fi\r\nfi\r\n\r\nif env | grep \"DOCKER_VERNEMQ_DISCOVERY_NODE\" -q; then\r\n    discovery_node=$DOCKER_VERNEMQ_DISCOVERY_NODE\r\n    if [ -n \"$DOCKER_VERNEMQ_SWARM\" ]; then\r\n        tmp=''\r\n        while [[ -z \"$tmp\" ]]; do\r\n            tmp=$(getent hosts tasks.$discovery_node | awk '{print $1}' | head -n 1)\r\n            sleep 1\r\n        done\r\n        discovery_node=$tmp\r\n    fi\r\n    if [ -n \"$DOCKER_VERNEMQ_COMPOSE\" ]; then\r\n        tmp=''\r\n        while [[ -z \"$tmp\" ]]; do\r\n            tmp=$(getent hosts $discovery_node | awk '{print $1}' | head -n 1)\r\n            sleep 1\r\n        done\r\n        discovery_node=$tmp\r\n    fi\r\n\r\n    sed -i.bak -r \"\/-eval.+\/d\" \/vernemq\/etc\/vm.args\r\n    echo \"-eval \\\"vmq_server_cmd:node_join('VerneMQ@$discovery_node')\\\"\" &gt;&gt; \/vernemq\/etc\/vm.args\r\nfi\r\n\r\n# If you encounter \"SSL certification error (subject name does not match the host name)\", you may try to set DOCKER_VERNEMQ_KUBERNETES_INSECURE to \"1\".\r\ninsecure=\"\"\r\nif env | grep \"DOCKER_VERNEMQ_KUBERNETES_INSECURE\" -q; then\r\n    insecure=\"--insecure\"\r\nfi\r\n\r\nif env | grep \"DOCKER_VERNEMQ_DISCOVERY_KUBERNETES\" -q; then\r\n    DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME=${DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME:-cluster.local}\r\n    # Let's get the namespace if it isn't set\r\n    DOCKER_VERNEMQ_KUBERNETES_NAMESPACE=${DOCKER_VERNEMQ_KUBERNETES_NAMESPACE:-`cat \/var\/run\/secrets\/kubernetes.io\/serviceaccount\/namespace`}\r\n    # Let's set our nodename correctly\r\n    VERNEMQ_KUBERNETES_SUBDOMAIN=${DOCKER_VERNEMQ_KUBERNETES_SUBDOMAIN:-$(curl -X GET $insecure --cacert \/var\/run\/secrets\/kubernetes.io\/serviceaccount\/ca.crt https:\/\/kubernetes.default.svc.$DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME\/api\/v1\/namespaces\/$DOCKER_VERNEMQ_KUBERNETES_NAMESPACE\/pods?labelSelector=$DOCKER_VERNEMQ_KUBERNETES_LABEL_SELECTOR -H \"Authorization: Bearer $(cat \/var\/run\/secrets\/kubernetes.io\/serviceaccount\/token)\" | jq '.items[0].spec.subdomain' | sed 's\/\"\/\/g' | tr '\\n' '\\0')}\r\n    if [ $VERNEMQ_KUBERNETES_SUBDOMAIN == \"null\" ]; then\r\n        VERNEMQ_KUBERNETES_HOSTNAME=${MY_POD_NAME}.${DOCKER_VERNEMQ_KUBERNETES_NAMESPACE}.svc.${DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME}\r\n    else\r\n        VERNEMQ_KUBERNETES_HOSTNAME=${MY_POD_NAME}.${VERNEMQ_KUBERNETES_SUBDOMAIN}.${DOCKER_VERNEMQ_KUBERNETES_NAMESPACE}.svc.${DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME}\r\n    fi\r\n\r\n    sed -i.bak -r \"s\/VerneMQ@.+\/VerneMQ@${VERNEMQ_KUBERNETES_HOSTNAME}\/\" \/vernemq\/etc\/vm.args\r\n    # Hack into K8S DNS resolution (temporarily)\r\n    kube_pod_names=$(curl -X GET $insecure --cacert \/var\/run\/secrets\/kubernetes.io\/serviceaccount\/ca.crt https:\/\/kubernetes.default.svc.$DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME\/api\/v1\/namespaces\/$DOCKER_VERNEMQ_KUBERNETES_NAMESPACE\/pods?labelSelector=$DOCKER_VERNEMQ_KUBERNETES_LABEL_SELECTOR -H \"Authorization: Bearer $(cat \/var\/run\/secrets\/kubernetes.io\/serviceaccount\/token)\" | jq '.items[].spec.hostname' | sed 's\/\"\/\/g' | tr '\\n' ' ')\r\n    for kube_pod_name in $kube_pod_names;\r\n    do\r\n        if [ $kube_pod_name == \"null\" ]\r\n            then\r\n                echo \"Kubernetes discovery selected, but no pods found. Maybe we're the first?\"\r\n                echo \"Anyway, we won't attempt to join any cluster.\"\r\n                break\r\n        fi\r\n        if [ $kube_pod_name != $MY_POD_NAME ]\r\n            then\r\n                echo \"Will join an existing Kubernetes cluster with discovery node at ${kube_pod_name}.${VERNEMQ_KUBERNETES_SUBDOMAIN}.${DOCKER_VERNEMQ_KUBERNETES_NAMESPACE}.svc.${DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME}\"\r\n                echo \"-eval \\\"vmq_server_cmd:node_join('VerneMQ@${kube_pod_name}.${VERNEMQ_KUBERNETES_SUBDOMAIN}.${DOCKER_VERNEMQ_KUBERNETES_NAMESPACE}.svc.${DOCKER_VERNEMQ_KUBERNETES_CLUSTER_NAME}')\\\"\" &gt;&gt; \/vernemq\/etc\/vm.args\r\n                break\r\n        fi\r\n    done\r\nfi\r\n\r\nif [ -f \/vernemq\/etc\/vernemq.conf.local ]; then\r\n    cp \/vernemq\/etc\/vernemq.conf.local \/vernemq\/etc\/vernemq.conf\r\n    sed -i -r \"s\/###IPADDRESS###\/${IP_ADDRESS}\/\" \/vernemq\/etc\/vernemq.conf\r\nelse\r\n    sed -i '\/########## Start ##########\/,\/########## End ##########\/d' \/vernemq\/etc\/vernemq.conf\r\n\r\n    echo \"########## Start ##########\" &gt;&gt; \/vernemq\/etc\/vernemq.conf\r\n\r\n    env | grep DOCKER_VERNEMQ | grep -v 'DISCOVERY_NODE\\|KUBERNETES\\|SWARM\\|COMPOSE\\|DOCKER_VERNEMQ_USER' | cut -c 16- | awk '{match($0,\/^[A-Z0-9_]*\/)}{print tolower(substr($0,RSTART,RLENGTH)) substr($0,RLENGTH+1)}' | sed 's\/__\/.\/g' &gt;&gt; \/vernemq\/etc\/vernemq.conf\r\n\r\n    users_are_set=$(env | grep DOCKER_VERNEMQ_USER)\r\n    if [ ! -z \"$users_are_set\" ]; then\r\n        echo \"vmq_passwd.password_file = \/vernemq\/etc\/vmq.passwd\" &gt;&gt; \/vernemq\/etc\/vernemq.conf\r\n        touch \/vernemq\/etc\/vmq.passwd\r\n    fi\r\n\r\n    for vernemq_user in $(env | grep DOCKER_VERNEMQ_USER); do\r\n        username=$(echo $vernemq_user | awk -F '=' '{ print $1 }' | sed 's\/DOCKER_VERNEMQ_USER_\/\/g' | tr '[:upper:]' '[:lower:]')\r\n        password=$(echo $vernemq_user | awk -F '=' '{ print $2 }')\r\n        \/vernemq\/bin\/vmq-passwd \/vernemq\/etc\/vmq.passwd $username &lt;&lt;EOF\r\n$password\r\n$password\r\nEOF\r\n    done\r\n\r\n    if [ -z \"$DOCKER_VERNEMQ_ERLANG__DISTRIBUTION__PORT_RANGE__MINIMUM\" ]; then\r\n        echo \"erlang.distribution.port_range.minimum = 9100\" &gt;&gt; \/vernemq\/etc\/vernemq.conf\r\n    fi\r\n\r\n    if [ -z \"$DOCKER_VERNEMQ_ERLANG__DISTRIBUTION__PORT_RANGE__MAXIMUM\" ]; then\r\n        echo \"erlang.distribution.port_range.maximum = 9109\" &gt;&gt; \/vernemq\/etc\/vernemq.conf\r\n    fi\r\n\r\n    if [ -z \"$DOCKER_VERNEMQ_LISTENER__TCP__DEFAULT\" ]; then\r\n        echo \"listener.tcp.default = ${IP_ADDRESS}:1883\" &gt;&gt; \/vernemq\/etc\/vernemq.conf\r\n    fi\r\n\r\n    if [ -z \"$DOCKER_VERNEMQ_LISTENER__WS__DEFAULT\" ]; then\r\n        echo \"listener.ws.default = ${IP_ADDRESS}:8080\" &gt;&gt; \/vernemq\/etc\/vernemq.conf\r\n    fi\r\n\r\n    if [ -z \"$DOCKER_VERNEMQ_LISTENER__VMQ__CLUSTERING\" ]; then\r\n        echo \"listener.vmq.clustering = ${IP_ADDRESS}:44053\" &gt;&gt; \/vernemq\/etc\/vernemq.conf\r\n    fi\r\n\r\n    if [ -z \"$DOCKER_VERNEMQ_LISTENER__HTTP__METRICS\" ]; then\r\n        echo \"listener.http.metrics = ${IP_ADDRESS}:8888\" &gt;&gt; \/vernemq\/etc\/vernemq.conf\r\n    fi\r\n\r\n    echo \"########## End ##########\" &gt;&gt; \/vernemq\/etc\/vernemq.conf\r\nfi\r\n\r\n# Check configuration file\r\n\/vernemq\/bin\/vernemq config generate 2&gt;&amp;1 &gt; \/dev\/null | tee \/tmp\/config.out | grep error\r\n\r\nif [ $? -ne 1 ]; then\r\n    echo \"configuration error, exit\"\r\n    echo \"$(cat \/tmp\/config.out)\"\r\n    exit $?\r\nfi\r\n\r\npid=0\r\n\r\n# SIGUSR1-handler\r\nsiguser1_handler() {\r\n    echo \"stopped\"\r\n}\r\n\r\n# SIGTERM-handler\r\nsigterm_handler() {\r\n    if [ $pid -ne 0 ]; then\r\n        # this will stop the VerneMQ process, but first drain the node from all existing client sessions (-k)\r\n        if [ -n \"$VERNEMQ_KUBERNETES_HOSTNAME\" ]; then\r\n            terminating_node_name=VerneMQ@$VERNEMQ_KUBERNETES_HOSTNAME\r\n        elif [ -n \"$DOCKER_VERNEMQ_SWARM\" ]; then\r\n            terminating_node_name=VerneMQ@$(hostname -i)\r\n        else\r\n            terminating_node_name=VerneMQ@$IP_ADDRESS\r\n        fi\r\n        \/vernemq\/bin\/vmq-admin cluster leave node=$terminating_node_name -k &gt; \/dev\/null\r\n        \/vernemq\/bin\/vmq-admin node stop &gt; \/dev\/null\r\n        kill -s TERM ${pid}\r\n        exit 0\r\n    fi\r\n}\r\n\r\n# Setup OS signal handlers\r\ntrap 'siguser1_handler' SIGUSR1\r\ntrap 'sigterm_handler' SIGTERM\r\n\r\n# Start VerneMQ\r\n\/vernemq\/bin\/vernemq console -noshell -noinput $@ &amp;\r\npid=$!\r\nwait $pid<\/pre>\n<p>--<\/p>\n<h2 class=\"title\">Eclipse Mosquitto<\/h2>\n<ul>\n<li><a href=\"https:\/\/oranwind.org\/-edge-zai-ubuntu-an-zhuang-mosquitto-mqtt-broker-part-2\/\" target=\"_blank\" rel=\"noopener\">[ Broker ] \u5728 Ubuntu \u5b89\u88dd Mosquitto MQTT Broker<\/a><\/li>\n<\/ul>\n<p>Ubuntu 20<\/p>\n<pre class=\"lang:default decode:true\"># apt-get install mosquitto mosquitto-clients<\/pre>\n<p>\u9700\u8981\u91cd\u65b0\u5b89\u88dd\u8a2d\u5b9a\u6a94\u53ef\u4ee5\u4f7f\u7528<\/p>\n<pre class=\"lang:default decode:true \"># apt-get -o DPkg::options::=--force-confmiss --reinstall install mosquitto<\/pre>\n<p>--<\/p>\n<h2>RabbitMQ<\/h2>\n<p>MQTT \u5728 RabbitMQ \u53ea\u662f\u5176\u4e2d\u4e00\u500b Plugin\uff0c\u4e0d\u6703\u7528<\/p>\n<ul>\n<li><a href=\"https:\/\/www.rabbitmq.com\/install-debian.html\" target=\"_blank\" rel=\"noopener\">Installing on Debian and Ubuntu<\/a><\/li>\n<li><a href=\"https:\/\/wangxin1248.github.io\/linux\/2020\/03\/ubuntu-install-rabbitmq.html\" target=\"_blank\" rel=\"noopener\">Ubuntu 18.04 \u5b89\u88c5 RabbitMQ<\/a><\/li>\n<\/ul>\n<p>Ubuntu 20<\/p>\n<pre class=\"lang:default decode:true \"># apt-get install erlang-base erlang-asn1 erlang-crypto erlang-eldap erlang-ftp erlang-inets erlang-mnesia erlang-os-mon erlang-parsetools erlang-public-key erlang-runtime-tools erlang-snmp erlang-ssl erlang-syntax-tools erlang-tftp erlang-tools erlang-xmerl<\/pre>\n<pre class=\"lang:default decode:true\"># apt-get install rabbitmq-server<\/pre>\n<pre class=\"lang:default decode:true\"># rabbitmq-plugins enable rabbitmq_mqtt<\/pre>\n<p>--<\/p>\n<h2>Mosquitto MySQL plugin \u5b89\u88dd<\/h2>\n<pre class=\"lang:default decode:true\"># apt-get install libssl-dev mosquitto-dev libmysqlclient-dev<\/pre>\n<p>\u6700\u5f8c\u7de8\u8b6f\u5931\u6557\uff0c\u4e0d\u6703\u7528<\/p>\n<p><span style=\"font-weight: 300;\">--<\/span><\/p>\n<div class=\"pvc_clear\"><\/div>\n<p class=\"pvc_stats all \" data-element-id=\"7155\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> &nbsp;7,243&nbsp;total views, &nbsp;1&nbsp;views today<\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>-- MQTT broker ...<\/p>\n<div class=\"pvc_clear\"><\/div>\n<p class=\"pvc_stats all \" data-element-id=\"7155\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> &nbsp;7,243&nbsp;total views, &nbsp;1&nbsp;views today<\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[319],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.hoyo.idv.tw\/index.php?rest_route=\/wp\/v2\/posts\/7155"}],"collection":[{"href":"https:\/\/blog.hoyo.idv.tw\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.hoyo.idv.tw\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.hoyo.idv.tw\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.hoyo.idv.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7155"}],"version-history":[{"count":44,"href":"https:\/\/blog.hoyo.idv.tw\/index.php?rest_route=\/wp\/v2\/posts\/7155\/revisions"}],"predecessor-version":[{"id":7696,"href":"https:\/\/blog.hoyo.idv.tw\/index.php?rest_route=\/wp\/v2\/posts\/7155\/revisions\/7696"}],"wp:attachment":[{"href":"https:\/\/blog.hoyo.idv.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7155"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.hoyo.idv.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7155"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.hoyo.idv.tw\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7155"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}