linux 用脚本启动rocketmq控制台会被卡住

#!/bin/bash

# 基础配置
SRC_DIR=/data/HH-Cloud  # 源码路径
WORK_DIR=/data/jar      # 工作目录
LOG_DIR=/data/logs      # 日志目录

# 服务脚本列表
SERVICE_SCRIPTS=(
    "hh-gateway"
    "hh-auth"
    "hh-xxl-job-admin"
    "hh-trade"
    "hh-system"
    "hh-site"
    "hh-sign"
    "hh-sentinel-dashboard"
    "hh-resource"
    "hh-monitor"
    "hh-mall"
    "hh-job"
    "hh-im"
    "hh-finance"
)

# Nacos、RocketMQ 和 Seata 启动和停止脚本
NACOS_START_CMD="bash /data/nacos/bin/startup.sh -m standalone"
NACOS_STOP_CMD="bash /data/nacos/bin/shutdown.sh"
ROCKETMQ_START_CMD="nohup sh /data/rocketmq-5.2.0/bin/mqnamesrv > /data/logs/rocketmq_namesrv.log 2>&1 &"
ROCKETMQ_BROKER_CMD="nohup sh /data/rocketmq-5.2.0/bin/mqbroker -n 127.0.0.1:9876 > /data/logs/rocketmq_broker.log 2>&1 &"
ROCKETMQ_STOP_CMD="sh /data/rocketmq-5.2.0/bin/mqshutdown namesrv && sh /data/rocketmq-5.2.0/bin/mqshutdown broker"
SEATA_START_CMD=" bash /data/seata-server-1.6.0/bin/seata-server.sh &"
SEATA_STOP_CMD="bash /data/seata-server-1.6.0/bin/seata-server.sh stop"

OPTIONS="-Xms512m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"

# 确保目录存在
mkdir -p $WORK_DIR
mkdir -p $LOG_DIR

# 启动单个服务
start_service() {
    local SERVICE=$1
    local JAR_PATH=""
    local LOG_FILE=$LOG_DIR/$SERVICE.log
    local PID_FILE=/var/run/$SERVICE.pid

    echo "Starting $SERVICE..."

    # 查找 JAR 文件
    for DIR in "$SRC_DIR/hh-gateway/target" "$SRC_DIR/hh-modules/$SERVICE/target" "$SRC_DIR/hh-visual/$SERVICE/target" "$SRC_DIR/hh-auth/target"; do
        if [ -f "$DIR/$SERVICE.jar" ]; then
            JAR_PATH="$DIR/$SERVICE.jar"
            break
        fi
    done

    if [ -z "$JAR_PATH" ]; then
        echo "Error: JAR file for $SERVICE not found!"
        return
    fi

    # 检查是否已在运行
    if [ -f $PID_FILE ]; then
        PID=$(cat $PID_FILE)
        if kill -0 $PID 2>/dev/null; then
            echo "$SERVICE is already running (PID: $PID)"
            return
        else
            echo "Stale PID file found for $SERVICE. Removing it."
            rm -f $PID_FILE
        fi
    fi

    # 停止旧进程(如果未正确停止)
    OLD_PID=$(ps -ef | grep "$SERVICE".jar | grep -v grep | awk '{print $2}')
    if [ -n "$OLD_PID" ]; then
        echo "Stopping old instance of $SERVICE (PID: $OLD_PID)..."
        kill -9 $OLD_PID
        echo "Old instance stopped."
    fi

    # 启动新服务
    nohup java $OPTIONS -jar $JAR_PATH --spring.profiles.active=stage > $LOG_FILE 2>&1 &
    NEW_PID=$!
    echo $NEW_PID > $PID_FILE
    echo "$SERVICE started (PID: $NEW_PID)"
}

# 停止单个服务
stop_service() {
    local SERVICE=$1
    local PID_FILE=/var/run/$SERVICE.pid

    echo "Stopping $SERVICE..."

    if [ -f $PID_FILE ]; then
        PID=$(cat $PID_FILE)
        if kill -0 $PID 2>/dev/null; then
            kill -9 $PID
            rm -f $PID_FILE
            echo "$SERVICE stopped."
        else
            echo "PID $PID not valid. Removing stale PID file."
            rm -f $PID_FILE
        fi
    else
        echo "$SERVICE is not running."
    fi
}

# 查询单个服务状态
status_service() {
    local SERVICE=$1
    local PID_FILE=/var/run/$SERVICE.pid

    if [ -f $PID_FILE ] && kill -0 $(cat $PID_FILE) 2>/dev/null; then
        echo "$SERVICE is running (PID: $(cat $PID_FILE))"
    else
        echo "$SERVICE is not running."
    fi
}

# 启动 Nacos、RocketMQ、Seata 服务
start_nacos() {
    echo "Starting Nacos..."
    $NACOS_START_CMD &
    echo "Nacos started."
}

start_rocketmq() {
 echo "Starting RocketMQ..."

    # 启动 NameServer
    eval $ROCKETMQ_START_CMD
    sleep 2  # 稍等一下,确保 NameServer 启动

    # 启动 Broker
    eval $ROCKETMQ_BROKER_CMD
    sleep 2  # 稍等一下,确保 Broker 启动

    # 使用 disown 完全将进程与终端分离
    disown

    echo "RocketMQ started. Logs are available in /data/logs/rocketmq_namesrv.log and /data/logs/rocketmq_broker.log"
}

start_seata() {
    echo "Starting Seata..."
    $SEATA_START_CMD
    sleep 3  # 给 Seata 一些时间启动
    echo "Seata started."
}

# 停止 Nacos、RocketMQ、Seata 服务
stop_nacos() {
    echo "Stopping Nacos..."
    $NACOS_STOP_CMD
    echo "Nacos stopped."
}

stop_rocketmq() {
    echo "Stopping RocketMQ..."
    $ROCKETMQ_STOP_CMD
    echo "RocketMQ stopped."
}

stop_seata() {
    echo "Stopping Seata..."
    $SEATA_STOP_CMD
    echo "Seata stopped."
}

# 检查参数
if [ $# -ne 1 ]; then
    echo "Usage: $0 <start|stop|status>"
    exit 1
fi

ACTION=$1

# 根据参数执行操作
case $ACTION in
    start)
        # 启动所有服务
        start_nacos
        start_rocketmq
        start_seata
        for SERVICE in "${SERVICE_SCRIPTS[@]}"; do
            start_service $SERVICE
            sleep 2  # 确保每个服务有足够时间启动
        done
        echo "All services started."
        ;;
    stop)
        # 停止所有服务
        stop_nacos
        stop_rocketmq
        stop_seata
        for SERVICE in "${SERVICE_SCRIPTS[@]}"; do
            stop_service $SERVICE
        done
        echo "All services stopped."
        ;;
    status)
        # 检查所有服务状态
        echo "Checking Nacos status..."
        status_service nacos
        echo "Checking RocketMQ status..."
        status_service rocketmq
        echo "Checking Seata status..."
        status_service seata
        for SERVICE in "${SERVICE_SCRIPTS[@]}"; do
            status_service $SERVICE
        done
        ;;
    *)
        echo "Invalid action: $ACTION. Use 'start', 'stop', or 'status'."
        exit 1
        ;;
esac

微信小程序和H5端对接dify ai接口

微信小程序和H5端对接dify ai接口

用的uniapp开发的

H5端是基于SSE协议开发的

要安装

    import {
        fetchEventSource
    } from '@microsoft/fetch-event-source';
/*#ifdef H5*/
                const eventSource = new fetchEventSource('/v1/chat-messages', {
                    method: 'POST',
                    headers: {
                        'Authorization': 'Bearer app-xxx',
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        inputs: {},
                        query: message, // 替换为实际的查询内容
                        response_mode: 'streaming', // 启用流式响应
                        conversation_id: that.conversationId,
                        user: "abc-123"
                    }),
                    onopen(response) {
                        // 建立连接
                        console.log(response, "open");
                        if (response.ok) {
                            console.log("成功建立连接");
                        } else {
                            throw new Error(JSON.stringify(response));
                        }
                    },
                    onmessage(event) {
                        try {
                            const jsonData = JSON.parse(event.data);
                            if (jsonData.event === "message") {
                                //that.loading = false; // 隐藏加载图标
                                that.conversationId = jsonData.conversation_id;
                                // 如果返回的答案中有新的文字,逐字显示
                                if (jsonData.answer) {
                                    // 追加接收到的新文字
                                    that.displayedText += jsonData.answer;
                                    // 继续显示新的文字
                                    //that.startTyping(jsonData.message_id);
                                }
                            }
                            console.log("that.displayedText", that.displayedText);

                            if (jsonData.event === "message_end") {
                                that.loading = false; // 隐藏加载图标
                                that.arr.push({
                                    answer: that.displayedText,
                                    message_id: jsonData.message_id,
                                });
                                that.displayedText = "";
                                console.log("that.arr", that.arr);
                            }
                        } catch (error) {
                            console.error("数据解析错误:", error);
                        }
                    },
                    onclose() {
                        console.log("关闭链接");
                    },
                    onerror(err) {
                        console.error("发生错误", err);
                        throw err;
                    },
                    openWhenHidden: true, // 实时通知
                });
                /*#endif*/

                /*#ifdef MP-WEIXIN*/
                // 微信小程序端执行的逻辑

                const requestTask = uni.request({
                    url: '/v1/chat-messages',
                    timeout: 15000,
                    responseType: 'text',
                    method: 'POST',
                    header: {
                        'Authorization': 'Bearer app-xxx',
                        'Content-Type': 'application/json',
                    },
                    enableChunked: true, //配置这里
                    data: JSON.stringify({
                        inputs: {},
                        query: message, // 替换为实际的查询内容
                        response_mode: 'streaming', // 启用流式响应
                        conversation_id: that.conversationId,
                        user: "abc-123"
                    }),
                    success: response => {
                        console.log(response)
                    },
                    fail: error => {}
                })
                requestTask.onHeadersReceived(function(res) {
                    console.log(res.header);
                });
                // 这里监听消息
                requestTask.onChunkReceived(function(res) {
                    let decoder = new TextDecoder('utf-8')
                    let text = decoder.decode(new Uint8Array(res.data))
                    console.log(text)
                    try {
                        // 使用正则表达式去除前缀 "data: "
                        const jsonString = text.replace(/^data:\s*/, '');
                        const jsonData = JSON.parse(jsonString);
                        if (jsonData.event === "message") {
                            //that.loading = false; // 隐藏加载图标
                            that.conversationId = jsonData.conversation_id;
                            // 如果返回的答案中有新的文字,逐字显示
                            if (jsonData.answer) {
                                // 追加接收到的新文字
                                that.displayedText += jsonData.answer;
                                // 继续显示新的文字
                                //that.startTyping(jsonData.message_id);
                            }
                        }
                        console.log("that.displayedText", that.displayedText);

                        if (jsonData.event === "message_end") {
                            that.loading = false; // 隐藏加载图标
                            that.arr.push({
                                answer: that.displayedText,
                                message_id: jsonData.message_id,
                            });
                            that.displayedText = "";
                            console.log("that.arr", that.arr);
                        }
                    } catch (error) {
                        console.error("数据解析错误:", error);
                    }

                })
                /*#endif*/

基于Docker安装minio【保姆级教程、内含图解】

目录

  1. 拉取镜像
  2. 创建挂载点目录
  3. 创建minio容器
  4. 启动minio容器
  5. 测试minio是否安装成功

    minio官网:MinIO | High Performance, Kubernetes Native Object Storage

  6. 拉取镜像

    代码:

    docker pull minio/minio

    实例:

     [root@localhost howlong]# docker pull minio/minio
     Using default tag: latest
     latest: Pulling from minio/minio
     5329d7039f25: Pull complete 
     2b3707fd3b24: Pull complete 
     5206d1e7147f: Pull complete 
     33feab5fa1c5: Pull complete 
     5cd9e0eb62e5: Pull complete 
     34f92c74bdaf: Pull complete 
     Digest: sha256:15d762671436cf383f9cc6667260e6c1298c25c8d7009576f709c3823e4a494d
     Status: Downloaded newer image for minio/minio:latest
     docker.io/minio/minio:latest
     [root@localhost howlong]# 
    
  7. 创建挂载点目录

    代码:

     mkdir -p /usr/local/minio/config
     mkdir -p /usr/local/minio/data
    
  8. 创建minio容器

         注意:这里设置了minio客户端的账号和密码,其密码不可少于8位
    
         账号:admin
    
         密码:admin123
    

    代码:

     docker run -d \
     --name minio \
     -p 9000:9000 \
     -p 9001:9001 \
     --privileged=true \
     -e "MINIO_ROOT_USER=admin" \
     -e "MINIO_ROOT_PASSWORD=admin123" \
     -v /usr/local/minion/data:/data \
     -v /usr/local/minio/config:/root/.minio \
     minio/minio server \
     --console-address ":9000" \
     --address ":9001" /data
    

    实例:

     [root@localhost howlong]# docker run -d \
     --name minio \
     -p 9000:9000 \
     -p 9001:9001 \
     --privileged=true \
     -e "MINIO_ROOT_USER=admin" \
     -e "MINIO_ROOT_PASSWORD=admin123" \
     -v /usr/local/minion/data:/data \
     -v /usr/local/minio/config:/root/.minio \
     minio/minio server \
     --console-address ":9000" \
     --address ":9001" /data
     93c98998d5cbc51c6f208cfe676adf495d4931469aad1d9756e19dca3fd4b66a
    
  9. 启动minio容器

    代码:

    docker start minio

    实例:

     [root@localhost howlong]# docker start minio
     minio
     [root@localhost howlong]#
    
  10. 测试minio是否安装成功

          访问虚拟机地址+端口号,前面配置minio 的端口号为:9000
    

    例如:

    http://192.168.27.129:9000

         账号:admin
    
         密码:admin123
    

Docker 安装 Nginx 容器 (完整详细版)

1、寻找Nginx镜像

2、下载Nginx镜像
命令 描述
docker pull nginx 下载最新版Nginx镜像 (其实此命令就等同于 : docker pull nginx:latest )
docker pull nginx:xxx 下载指定版本的Nginx镜像 (xxx指具体版本号)

 检查当前所有Docker下载的镜像

docker images

3、创建Nginx配置文件

启动前需要先创建Nginx外部挂载的配置文件( /home/nginx/conf/nginx.conf)
之所以要先创建 , 是因为Nginx本身容器只存在/etc/nginx 目录 , 本身就不创建 nginx.conf 文件
当服务器和容器都不存在 nginx.conf 文件时, 执行启动命令的时候 docker会将nginx.conf 作为目录创建 , 这并不是我们想要的结果 。

# 创建挂载目录
mkdir -p /home/nginx/conf
mkdir -p /home/nginx/log
mkdir -p /home/nginx/html

容器中的nginx.conf文件和conf.d文件夹复制到宿主机

# 生成容器
docker run --name nginx -p 9001:80 -d nginx
# 将容器nginx.conf文件复制到宿主机
docker cp nginx:/etc/nginx/nginx.conf /home/nginx/conf/nginx.conf
# 将容器conf.d文件夹下内容复制到宿主机
docker cp nginx:/etc/nginx/conf.d /home/nginx/conf/conf.d
# 将容器中的html文件夹复制到宿主机
docker cp nginx:/usr/share/nginx/html /home/nginx/

4、创建Nginx容器并运行

Docker 创建Nginx容器

# 直接执行docker rm nginx或者以容器id方式关闭容器
# 找到nginx对应的容器id
docker ps -a
# 关闭该容器
docker stop nginx
# 删除该容器
docker rm nginx
 
# 删除正在运行的nginx容器
docker rm -f nginx

docker run \
-p 9002:80 \
--name nginx \
-v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /home/nginx/conf/conf.d:/etc/nginx/conf.d \
-v /home/nginx/log:/var/log/nginx \
-v /home/nginx/html:/usr/share/nginx/html \
-d nginx:latest

命令 描述
–name nginx 启动容器的名字
-d 后台运行
-p 9002:80 将容器的 9002(后面那个) 端口映射到主机的 80(前面那个) 端口
-v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf 挂载nginx.conf配置文件
-v /home/nginx/conf/conf.d:/etc/nginx/conf.d 挂载nginx配置文件
-v /home/nginx/log:/var/log/nginx 挂载nginx日志文件
-v /home/nginx/html:/usr/share/nginx/html 挂载nginx内容
nginx:latest 本地运行的版本
\ shell 命令换行

单行模式

docker run -p 9002:80 --name nginx -v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -v /home/nginx/conf/conf.d:/etc/nginx/conf.d -v /home/nginx/log:/var/log/nginx -v /home/nginx/html:/usr/share/nginx/html -d nginx:latest

5、结果检测

6、修改内容进行展示

# 重启容器
docker restart nginx