440 lines
15 KiB
Bash
Executable File
440 lines
15 KiB
Bash
Executable File
#!/bin/bash
|
||
# RK3588 Media Server + Agent 统一管理脚本
|
||
# 用法: sudo ./install.sh [install|status|uninstall]
|
||
|
||
set -e
|
||
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m'
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||
BUILD_DIR="$PROJECT_DIR/build"
|
||
INSTALL_DIR="/opt/rk3588-media-server"
|
||
AGENT_INSTALL_DIR="/opt/rk3588-agent"
|
||
SERVICE_DIR="/etc/systemd/system"
|
||
|
||
# ==================== 功能函数 ====================
|
||
|
||
cmd_install() {
|
||
echo -e "${BLUE}╔════════════════════════════════════════════════════════════╗${NC}"
|
||
echo -e "${BLUE}║ RK3588 Media Server + Agent 安装脚本 ║${NC}"
|
||
echo -e "${BLUE}╚════════════════════════════════════════════════════════════╝${NC}"
|
||
echo ""
|
||
|
||
if [ "$EUID" -ne 0 ]; then
|
||
echo -e "${RED}错误: 请使用 sudo 运行此脚本${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
echo "项目目录: $PROJECT_DIR"
|
||
echo "Media Server 安装目录: $INSTALL_DIR"
|
||
echo "Agent 安装目录: $AGENT_INSTALL_DIR"
|
||
echo ""
|
||
|
||
# 检查编译产物
|
||
if [ ! -f "$BUILD_DIR/media-server" ]; then
|
||
echo -e "${RED}错误: 未找到编译好的 media-server${NC}"
|
||
echo "请先编译项目:"
|
||
echo " cd $PROJECT_DIR"
|
||
echo " cmake -S . -B build -DCMAKE_BUILD_TYPE=Release ..."
|
||
echo " cmake --build build -j\$(nproc)"
|
||
exit 1
|
||
fi
|
||
|
||
# 检查插件
|
||
if [ ! -d "$BUILD_DIR/plugins" ] || [ -z "$(ls -A $BUILD_DIR/plugins/*.so 2>/dev/null)" ]; then
|
||
echo -e "${YELLOW}警告: 未找到插件目录或插件为空${NC}"
|
||
read -p "是否继续? (y/N): " -n 1 -r
|
||
echo
|
||
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
|
||
fi
|
||
|
||
# 检查 agent
|
||
AGENT_SOURCE=""
|
||
if [ -f "$PROJECT_DIR/agent/rk3588-agent_linux_arm64" ]; then
|
||
AGENT_SOURCE="$PROJECT_DIR/agent/rk3588-agent_linux_arm64"
|
||
elif [ -f "$PROJECT_DIR/agent/cmd/rk3588-agent" ]; then
|
||
AGENT_SOURCE="$PROJECT_DIR/agent/cmd/rk3588-agent"
|
||
fi
|
||
|
||
if [ -z "$AGENT_SOURCE" ]; then
|
||
echo -e "${YELLOW}警告: 未找到编译好的 rk3588-agent${NC}"
|
||
echo " 如需 Agent 功能,请先编译:"
|
||
echo " cd $PROJECT_DIR/agent"
|
||
echo " GOOS=linux GOARCH=arm64 go build -o rk3588-agent_linux_arm64 ./cmd"
|
||
fi
|
||
|
||
echo -e "${GREEN}✓${NC} 编译产物检查通过"
|
||
echo ""
|
||
|
||
# 选择模式
|
||
echo "请选择运行模式:"
|
||
echo " 1) 独立模式 - Media Server 由 systemd 直接管理 (简单)"
|
||
echo " 2) Agent 模式 - Media Server 由 Agent 管理 (推荐,支持 Web 管理)"
|
||
echo ""
|
||
read -p "请输入选项 [1-2,默认2]: " mode_choice
|
||
mode_choice=${mode_choice:-2}
|
||
|
||
USE_AGENT=false
|
||
if [ "$mode_choice" = "2" ] && [ -n "$AGENT_SOURCE" ]; then
|
||
USE_AGENT=true
|
||
elif [ "$mode_choice" = "2" ] && [ -z "$AGENT_SOURCE" ]; then
|
||
echo -e "${YELLOW}Agent 未编译,使用独立模式${NC}"
|
||
fi
|
||
echo ""
|
||
|
||
# 选择配置文件
|
||
echo "请选择配置文件:"
|
||
echo " 1) test_cam1_face_det_rtsp_server.json (人脸检测)"
|
||
echo " 2) sample_cam1_native_rtsp_face.json (完整功能)"
|
||
echo " 3) test_cam1_face_det_recog_rtsp_server.json (人脸识别)"
|
||
echo " 4) sample_cam1.json (完整功能,需手动修复)"
|
||
echo ""
|
||
read -p "请输入选项 [1-4,默认1]: " choice
|
||
choice=${choice:-1}
|
||
|
||
case $choice in
|
||
1) CONFIG_FILE="$PROJECT_DIR/configs/test_cam1_face_det_rtsp_server.json" ;;
|
||
2) CONFIG_FILE="$PROJECT_DIR/configs/sample_cam1_native_rtsp_face.json" ;;
|
||
3) CONFIG_FILE="$PROJECT_DIR/configs/test_cam1_face_det_recog_rtsp_server.json" ;;
|
||
4) CONFIG_FILE="$PROJECT_DIR/configs/sample_cam1.json" ;;
|
||
*) CONFIG_FILE="$PROJECT_DIR/configs/test_cam1_face_det_rtsp_server.json" ;;
|
||
esac
|
||
|
||
echo ""
|
||
echo -e "运行模式: ${GREEN}$([ "$USE_AGENT" = true ] && echo "Agent 模式" || echo "独立模式")${NC}"
|
||
echo ""
|
||
|
||
# 安装 Media Server
|
||
echo -e "${YELLOW}[1/4] 安装 Media Server...${NC}"
|
||
rm -rf "$INSTALL_DIR"
|
||
mkdir -p "$INSTALL_DIR"/{bin/plugins,lib,etc,logs,models,web/hls}
|
||
|
||
cp "$BUILD_DIR/media-server" "$INSTALL_DIR/bin/"
|
||
chmod +x "$INSTALL_DIR/bin/media-server"
|
||
|
||
if [ -d "$BUILD_DIR/plugins" ]; then
|
||
cp "$BUILD_DIR"/plugins/*.so "$INSTALL_DIR/bin/plugins/" 2>/dev/null || true
|
||
fi
|
||
|
||
if ls "$BUILD_DIR"/*.so 1> /dev/null 2>&1; then
|
||
cp "$BUILD_DIR"/*.so "$INSTALL_DIR/lib/" 2>/dev/null || true
|
||
fi
|
||
|
||
# 复制模型
|
||
if [ -d "$PROJECT_DIR/third_party/rknpu2/examples/rknn_yolov5_demo/model/RK3588" ]; then
|
||
cp "$PROJECT_DIR/third_party/rknpu2/examples/rknn_yolov5_demo/model/RK3588"/*.rknn "$INSTALL_DIR/models/" 2>/dev/null || true
|
||
fi
|
||
if [ -d "$PROJECT_DIR/models" ]; then
|
||
cp -r "$PROJECT_DIR/models"/* "$INSTALL_DIR/models/" 2>/dev/null || true
|
||
fi
|
||
|
||
# 处理配置
|
||
cp "$CONFIG_FILE" "$INSTALL_DIR/etc/media-server.json"
|
||
python3 << EOF
|
||
import json, os
|
||
config_file = "$INSTALL_DIR/etc/media-server.json"
|
||
install_dir = "$INSTALL_DIR"
|
||
project_dir = "$PROJECT_DIR"
|
||
|
||
def fix_path(path):
|
||
if not path or not isinstance(path, str):
|
||
return path
|
||
if path.startswith('./'):
|
||
if path.startswith('./web/'):
|
||
return os.path.join(install_dir, path[2:])
|
||
elif path.startswith('./models/'):
|
||
return os.path.join(install_dir, path[2:])
|
||
else:
|
||
abs_path = os.path.join(project_dir, path)
|
||
if os.path.exists(abs_path):
|
||
return abs_path
|
||
return os.path.join(install_dir, path[2:])
|
||
return path
|
||
|
||
try:
|
||
with open(config_file, 'r') as f:
|
||
config = json.load(f)
|
||
for graph in config.get('graphs', []):
|
||
nodes = graph.get('nodes', [])
|
||
edges = graph.get('edges', [])
|
||
node_ids = {node['id'] for node in nodes}
|
||
nodes_with_input = set()
|
||
for edge in edges:
|
||
if isinstance(edge, list) and len(edge) >= 2:
|
||
nodes_with_input.add(edge[1])
|
||
for node in nodes:
|
||
if node.get('role') in ['filter', 'sink'] and node['id'] not in nodes_with_input:
|
||
if node.get('enable', True):
|
||
node['enable'] = False
|
||
if 'model_path' in node:
|
||
node['model_path'] = fix_path(node['model_path'])
|
||
if 'gallery' in node and 'path' in node['gallery']:
|
||
node['gallery']['path'] = fix_path(node['gallery']['path'])
|
||
if 'outputs' in node:
|
||
for output in node['outputs']:
|
||
if 'path' in output:
|
||
output['path'] = fix_path(output['path'])
|
||
with open(config_file, 'w') as f:
|
||
json.dump(config, f, indent=2)
|
||
print("配置处理完成")
|
||
except Exception as e:
|
||
print(f"配置处理出错: {e}")
|
||
EOF
|
||
echo -e "${GREEN}✓${NC} Media Server 安装完成"
|
||
|
||
# 安装 Agent
|
||
if [ "$USE_AGENT" = true ] && [ -n "$AGENT_SOURCE" ]; then
|
||
echo -e "${YELLOW}[2/4] 安装 Agent...${NC}"
|
||
rm -rf "$AGENT_INSTALL_DIR"
|
||
mkdir -p "$AGENT_INSTALL_DIR"
|
||
mkdir -p "/var/lib/rk3588-agent"
|
||
|
||
cp "$AGENT_SOURCE" "$AGENT_INSTALL_DIR/rk3588-agent"
|
||
chmod +x "$AGENT_INSTALL_DIR/rk3588-agent"
|
||
|
||
cat > "$AGENT_INSTALL_DIR/agent.config.json" << 'AGENT_CONFIG'
|
||
{
|
||
"agent": {
|
||
"listen": "0.0.0.0:9100",
|
||
"token": "CHANGE_ME",
|
||
"require_token_for_read": false,
|
||
"discovery_enable": true,
|
||
"discovery_port": 35688,
|
||
"device_name": "rk3588_cam1",
|
||
"device_id_path": "/var/lib/rk3588-agent/device_id",
|
||
"models_dir": "/opt/rk3588-media-server/models",
|
||
"max_upload_mb": 200,
|
||
"config_path": "/opt/rk3588-media-server/etc/media-server.json",
|
||
"media_server_process": {
|
||
"enable": true,
|
||
"exec_path": "/opt/rk3588-media-server/bin/media-server",
|
||
"work_dir": "/opt/rk3588-media-server",
|
||
"configs_dir": "/opt/rk3588-media-server/etc",
|
||
"pid_file": "/var/run/rk3588sys-media-server.pid",
|
||
"graceful_timeout_ms": 5000
|
||
},
|
||
"media_server_base_url": "http://127.0.0.1:9000",
|
||
"media_server_timeout_ms": 3000,
|
||
"media_server_retry": { "max_attempts": 3, "backoff_ms": [200, 500] }
|
||
}
|
||
}
|
||
AGENT_CONFIG
|
||
chown -R orangepi:orangepi "/var/lib/rk3588-agent"
|
||
chmod 755 "$AGENT_INSTALL_DIR"
|
||
echo -e "${GREEN}✓${NC} Agent 安装完成"
|
||
fi
|
||
|
||
# 安装服务
|
||
echo -e "${YELLOW}[3/4] 安装 Systemd 服务...${NC}"
|
||
|
||
cat > "$SERVICE_DIR/media-server.service" << 'EOF'
|
||
[Unit]
|
||
Description=RK3588 Media Server
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=root
|
||
WorkingDirectory=/opt/rk3588-media-server
|
||
ExecStart=/opt/rk3588-media-server/bin/media-server --config /opt/rk3588-media-server/etc/media-server.json
|
||
Restart=always
|
||
RestartSec=5
|
||
StandardOutput=journal
|
||
StandardError=journal
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
|
||
if [ "$USE_AGENT" = true ] && [ -n "$AGENT_SOURCE" ]; then
|
||
cat > "$SERVICE_DIR/rk3588-agent.service" << 'EOF'
|
||
[Unit]
|
||
Description=RK3588 Agent Service
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=root
|
||
WorkingDirectory=/opt/rk3588-agent
|
||
ExecStart=/opt/rk3588-agent/rk3588-agent --config /opt/rk3588-agent/agent.config.json
|
||
Restart=always
|
||
RestartSec=5
|
||
StandardOutput=journal
|
||
StandardError=journal
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
EOF
|
||
fi
|
||
|
||
systemctl daemon-reload
|
||
touch /var/run/rk3588sys-media-server.pid
|
||
chmod 666 /var/run/rk3588sys-media-server.pid
|
||
echo -e "${GREEN}✓${NC} 服务安装完成"
|
||
|
||
# 启动服务
|
||
echo -e "${YELLOW}[4/4] 启动服务...${NC}"
|
||
if [ "$USE_AGENT" = true ] && [ -n "$AGENT_SOURCE" ]; then
|
||
systemctl disable media-server 2>/dev/null || true
|
||
systemctl stop media-server 2>/dev/null || true
|
||
systemctl enable rk3588-agent
|
||
systemctl start rk3588-agent
|
||
else
|
||
systemctl enable media-server
|
||
systemctl start media-server
|
||
fi
|
||
echo -e "${GREEN}✓${NC} 服务已启动"
|
||
|
||
# 完成
|
||
echo ""
|
||
echo -e "${GREEN}╔════════════════════════════════════════════════════════════╗${NC}"
|
||
echo -e "${GREEN}║ 安装完成! ║${NC}"
|
||
echo -e "${GREEN}╚════════════════════════════════════════════════════════════╝${NC}"
|
||
echo ""
|
||
if [ "$USE_AGENT" = true ] && [ -n "$AGENT_SOURCE" ]; then
|
||
echo "管理命令:"
|
||
echo " 状态: sudo $0 status"
|
||
echo " 日志: sudo journalctl -u rk3588-agent -f"
|
||
echo " 界面: http://<设备IP>:9100"
|
||
else
|
||
echo "管理命令:"
|
||
echo " 状态: sudo $0 status"
|
||
echo " 日志: sudo journalctl -u media-server -f"
|
||
fi
|
||
}
|
||
|
||
cmd_status() {
|
||
echo -e "${BLUE}========== RK3588 Media Server 状态 ==========${NC}"
|
||
echo ""
|
||
|
||
echo -e "${YELLOW}[系统信息]${NC}"
|
||
echo " 时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
||
echo " 运行时间: $(uptime -p 2>/dev/null || uptime | awk -F',' '{print $1}')"
|
||
echo ""
|
||
|
||
echo -e "${YELLOW}[NPU 负载]${NC}"
|
||
if [ -f /sys/kernel/debug/rknpu/load ]; then
|
||
cat /sys/kernel/debug/rknpu/load | sed 's/^/ /'
|
||
else
|
||
echo " NPU 信息不可用"
|
||
fi
|
||
echo ""
|
||
|
||
echo -e "${YELLOW}[Media Server]${NC}"
|
||
if systemctl is-active --quiet media-server 2>/dev/null; then
|
||
echo -e " 状态: ${GREEN}● 运行中${NC}"
|
||
PID=$(systemctl show --property=MainPID --value media-server 2>/dev/null)
|
||
echo " PID: $PID"
|
||
if [ -n "$PID" ] && [ "$PID" != "0" ]; then
|
||
CPU_MEM=$(ps -p $PID -o %cpu,%mem --no-headers 2>/dev/null || echo "N/A")
|
||
echo " CPU/MEM: $CPU_MEM"
|
||
fi
|
||
echo " 端口:"
|
||
ss -tlnp 2>/dev/null | grep -E "(9000|8554|8555)" | head -3 | sed 's/^/ /'
|
||
else
|
||
echo -e " 状态: ${RED}○ 停止${NC}"
|
||
fi
|
||
echo ""
|
||
|
||
if systemctl list-unit-files 2>/dev/null | grep -q rk3588-agent; then
|
||
echo -e "${YELLOW}[RK3588 Agent]${NC}"
|
||
if systemctl is-active --quiet rk3588-agent 2>/dev/null; then
|
||
echo -e " 状态: ${GREEN}● 运行中${NC}"
|
||
PID=$(systemctl show --property=MainPID --value rk3588-agent 2>/dev/null)
|
||
if [ -n "$PID" ] && [ "$PID" != "0" ]; then
|
||
CPU_MEM=$(ps -p $PID -o %cpu,%mem --no-headers 2>/dev/null || echo "N/A")
|
||
echo " CPU/MEM: $CPU_MEM"
|
||
fi
|
||
echo " 管理界面: http://$(hostname -I | awk '{print $1}'):9100"
|
||
else
|
||
echo -e " 状态: ${RED}○ 停止${NC}"
|
||
fi
|
||
echo ""
|
||
fi
|
||
|
||
echo -e "${YELLOW}[最近日志]${NC}"
|
||
if systemctl is-active --quiet rk3588-agent 2>/dev/null; then
|
||
journalctl -u rk3588-agent --no-pager -n 5 2>/dev/null | tail -5 || echo " 无日志"
|
||
else
|
||
journalctl -u media-server --no-pager -n 5 2>/dev/null | tail -5 || echo " 无日志"
|
||
fi
|
||
echo ""
|
||
|
||
echo "常用命令:"
|
||
echo " 重启: sudo systemctl restart media-server|rk3588-agent"
|
||
echo " 日志: sudo journalctl -u media-server|rk3588-agent -f"
|
||
echo " 配置: sudo nano /opt/rk3588-media-server/etc/media-server.json"
|
||
}
|
||
|
||
cmd_uninstall() {
|
||
echo -e "${YELLOW}========== RK3588 Media Server 卸载 ==========${NC}"
|
||
echo ""
|
||
|
||
if [ "$EUID" -ne 0 ]; then
|
||
echo -e "${RED}错误: 请使用 sudo 运行${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
read -p "确定要卸载并停止所有服务? (y/N): " -n 1 -r
|
||
echo
|
||
[[ ! $REPLY =~ ^[Yy]$ ]] && echo "已取消" && exit 0
|
||
|
||
echo "[1/3] 停止服务..."
|
||
systemctl stop media-server rk3588-agent 2>/dev/null || true
|
||
systemctl disable media-server rk3588-agent 2>/dev/null || true
|
||
echo -e "${GREEN}✓${NC} 服务已停止"
|
||
|
||
echo "[2/3] 删除服务文件..."
|
||
rm -f "$SERVICE_DIR/media-server.service"
|
||
rm -f "$SERVICE_DIR/rk3588-agent.service"
|
||
systemctl daemon-reload
|
||
echo -e "${GREEN}✓${NC} 服务文件已删除"
|
||
|
||
echo "[3/3] 备份并清理..."
|
||
BACKUP_DIR="/root/rk3588-backup-$(date +%Y%m%d%H%M%S)"
|
||
mkdir -p "$BACKUP_DIR"
|
||
[ -f "$INSTALL_DIR/etc/media-server.json" ] && cp "$INSTALL_DIR/etc/media-server.json" "$BACKUP_DIR/"
|
||
[ -d "$INSTALL_DIR/models" ] && cp -r "$INSTALL_DIR/models" "$BACKUP_DIR/" 2>/dev/null || true
|
||
echo -e "${GREEN}✓${NC} 配置已备份到: $BACKUP_DIR"
|
||
|
||
read -p "是否删除安装目录? (y/N): " -n 1 -r
|
||
echo
|
||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||
rm -rf "$INSTALL_DIR" "$AGENT_INSTALL_DIR"
|
||
echo -e "${GREEN}✓${NC} 目录已删除"
|
||
else
|
||
echo "保留目录,手动删除: sudo rm -rf $INSTALL_DIR $AGENT_INSTALL_DIR"
|
||
fi
|
||
|
||
echo ""
|
||
echo -e "${GREEN}卸载完成${NC}"
|
||
}
|
||
|
||
# ==================== 主入口 ====================
|
||
|
||
case "${1:-install}" in
|
||
install)
|
||
cmd_install
|
||
;;
|
||
status)
|
||
cmd_status
|
||
;;
|
||
uninstall)
|
||
cmd_uninstall
|
||
;;
|
||
*)
|
||
echo "用法: sudo ./manage.sh [install|status|uninstall]"
|
||
echo ""
|
||
echo "命令:"
|
||
echo " install - 安装/更新 Media Server 和 Agent (默认)"
|
||
echo " status - 查看运行状态"
|
||
echo " uninstall - 卸载服务"
|
||
exit 1
|
||
;;
|
||
esac
|