优化安装脚本逻辑

This commit is contained in:
CN-JS-HuiBai
2026-04-06 15:14:49 +08:00
parent 96de50285f
commit 1d728d991e
3 changed files with 168 additions and 239 deletions

116
README.md
View File

@@ -1,100 +1,70 @@
# 数据可视化展示大屏 # PromdataPanel
多源 Prometheus 服务器监控展示大屏支持对接多个 Prometheus 实例,实时展示所有服务器的 CPU、内存、磁盘、网络等关键指标。 多源 Prometheus 服务器监控展示大屏支持对接多个 Prometheus 实例,实时聚合展示所有服务器的 CPU、内存、磁盘、带宽等关键指标,并提供可视化节点分布图
## 功能特性 ## 功能特性
- 🔌 **多数据源管理** - MySQL 存储配置,支持对接多个 Prometheus 实例 - 🔌 **多数据源管理** - 支持对接多个 Prometheus 实例Node_Exporter / BlackboxExporter
- 📊 **NodeExporter 数据查询** - 自动聚合所有 Prometheus 中的 NodeExporter 数据 - 📊 **指标自动聚合** - 自动汇总所有数据源的 NodeExporter 指标,实时计算全网负载
- 🌐 **网络流量统计** - 24 小时网络流量趋势图,总流量统计 - 🌐 **网络流量统计** - 24 小时流量趋势图,实时带宽Rx/Tx求和显示
- **实时带宽监控** - 所有服务器网络带宽求和,实时显示 - 🗺️ **节点分布可视化** - 自动识别服务器地理位置,并在全球地图上展示实时连接状态与延迟
- 💻 **资源使用概览** - CPU、内存、磁盘的总使用率和详细统计 - **毫秒级实时性** - 深度优化查询逻辑,支持 5s 采集频率的实时动态展示
- 🖥️ **服务器列表** - 所有服务器的详细指标一览表 - 📱 **响应式与美学设计** - 现代 UI/UX 体验,支持暗色模式,极致性能优化
## 快速开始 ## 快速安装
### 1. 环境要求 ### 方式一:一键脚本安装 (推荐)
- Node.js >= 16 在 Linux 服务器上,您可以使用以下脚本一键完成下载、环境检测、依赖安装并将其注册为 Systemd 系统服务:
- MySQL >= 5.7
- Valkey >= 7.0 (或 Redis >= 6.0)
### 2. 配置
复制环境变量文件并修改:
```bash ```bash
cp .env.example .env # 下载安装最新版本 (默认 v0.1.0)
VERSION=v0.1.0 curl -sSL https://git.littlediary.cn/CN-JS-HuiBai/PromdataPanel/raw/branch/master/install.sh | bash
``` ```
编辑 `.env` 文件,配置 MySQL 和 Valkey 连接信息: ### 方式二:手动安装
```env #### 1. 环境要求
# MySQL 配置 - **Node.js** >= 18
MYSQL_HOST=localhost - **MySQL** >= 8.0
MYSQL_PORT=3306 - **Valkey** >= 7.0 (或 Redis >= 6.0)
MYSQL_USER=root
MYSQL_PASSWORD=your_password
MYSQL_DATABASE=display_wall
# Valkey/Redis 缓存配置 (可选) #### 2. 配置与启动
VALKEY_HOST=localhost 1. 克隆代码库:`git clone https://git.littlediary.cn/CN-JS-HuiBai/PromdataPanel.git`
VALKEY_PORT=6379 2. 复制配置文件:`cp .env.example .env`
VALKEY_PASSWORD= 3. 安装依赖:`npm install --production`
VALKEY_TTL=30 4. 启动服务:`npm start`
PORT=3000 #### 3. 系统初始化
``` 首次运行后,访问 `http://your-ip:3000/init.html`,按照引导完成 MySQL 数据库和 Valkey 缓存的连接。
### 3. 系统初始化 ## 使用指引
访问 `http://localhost:3000/init.html`,按照引导完成数据库和缓存的初始化。 ### 1. 添加 Prometheus 数据源
点击页面右上角的 ⚙️ 按钮进入设置,添加并测试您的 Prometheus HTTP 地址。
### 4. 安装依赖并启动 ### 2. Prometheus 采集配置
建议在 `prometheus.yml` 中设置采集周期为 `5s` 以实现平滑的实时动态效果:
```bash
npm install
npm run dev
```
访问 `http://localhost:3000` 即可看到展示大屏。
### 5. 配置 Prometheus 数据源
点击右上角的 ⚙️ 按钮,添加你的 Prometheus 地址(如 `http://prometheus.example.com:9090`)。
### 6. Prometheus 配置参考 (Example)
在您的 Prometheus 配置文件 `prometheus.yml` 中,建议执行以下配置(`scrape_interval` 建议设为 `5s` 以获取最佳实时展示效果):
```yaml ```yaml
global: global:
scrape_interval: 5s scrape_interval: 5s
scrape_configs:
- job_name: '机器名称'
static_configs:
- targets: ['IP:Port']
```
scrape_configs:
- job_name: 'nodes'
static_configs:
- targets: ['your-server-ip:9100']
```
## 技术栈 ## 技术栈
- **后端**: Node.js + Express - **Runtime**: Node.js
- **数据库**: MySQL (存储配置数据) - **Framework**: Express.js
- **缓存**: Valkey / Redis (用于加速流量计算结果读取) - **Database**: MySQL 8.0+
- **数据源**: Prometheus HTTP API - **Caching**: Valkey / Redis
- **前端**: 原生 HTML/CSS/JavaScript - **Visualization**: ECharts / Canvas
- **图表**: 自定义 Canvas 渲染 - **Frontend**: Vanilla JS / CSS3
## API 接口 ## LICENSE
| 方法 | 路径 | 说明 | MIT License
|------|------|------|
| GET | `/api/sources` | 获取所有数据源 |
| POST | `/api/sources` | 添加数据源 |
| PUT | `/api/sources/:id` | 更新数据源 |
| DELETE | `/api/sources/:id` | 删除数据源 |
| POST | `/api/sources/test` | 测试数据源连接 |
| GET | `/api/metrics/overview` | 获取聚合指标概览 |
| GET | `/api/metrics/network-history` | 获取24h网络流量历史 |
| GET | `/api/metrics/cpu-history` | 获取CPU使用率历史 |

View File

@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# Data Visualization Display Wall - Systemd Installer # PromdataPanel - Multi-Prometheus Monitoring Dashboard Installer
# Requirements: Node.js, NPM, Systemd (Linux) # This script handles OS detection, Node.js installation, project setup, and Systemd configuration.
# Colors for output # Colors for output
RED='\033[0;31m' RED='\033[0;31m'
@@ -10,69 +10,148 @@ YELLOW='\033[1;33m'
BLUE='\033[0;34m' BLUE='\033[0;34m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
echo -e "${BLUE}=== Data Visualization Display Wall Installer ===${NC}" # 0. Configuration
VERSION=${VERSION:-"v0.1.0"}
DOWNLOAD_URL="https://git.littlediary.cn/CN-JS-HuiBai/PromdataPanel/archive/${VERSION}.zip"
MIN_NODE_VERSION=18
# 1. Permission check (no longer mandatory) echo -e "${BLUE}================================================${NC}"
echo -e "${BLUE} PromdataPanel Auto-Installer ${NC}"
echo -e "${BLUE} Version: ${VERSION} ${NC}"
echo -e "${BLUE}================================================${NC}"
# 1. OS Detection
detect_os() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS_ID=$ID
OS_VER=$VERSION_ID
else
echo -e "${RED}Error: Cannot detect operating system type (/etc/os-release missing).${NC}"
exit 1
fi
echo -e "Detected OS: ${GREEN}${OS_ID} ${OS_VER}${NC}"
}
# 2. Node.js Installation/Verification
install_node() {
echo -e "${BLUE}Verifying Node.js environment...${NC}"
NODE_INSTALLED=false
if command -v node &> /dev/null; then
CURRENT_NODE_VER=$(node -v | cut -d'v' -f2 | cut -d'.' -f1)
if [ "$CURRENT_NODE_VER" -ge "$MIN_NODE_VERSION" ]; then
echo -e "${GREEN}Node.js v$(node -v) is already installed.${NC}"
NODE_INSTALLED=true
else
echo -e "${YELLOW}Existing Node.js version (v$(node -v)) is too old (Requires >= $MIN_NODE_VERSION).${NC}"
fi
fi
if [ "$NODE_INSTALLED" = false ]; then
echo -e "${BLUE}Installing Node.js 20.x...${NC}"
case "$OS_ID" in
ubuntu|debian|raspbian)
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
;;
centos|rhel|almalinux|rocky)
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo yum install -y nodejs
;;
fedora)
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -
sudo dnf install -y nodejs
;;
*)
echo -e "${RED}Unsupported OS for automatic Node.js installation: $OS_ID${NC}"
echo -e "Please install Node.js >= 18 manually.${NC}"
exit 1
;;
esac
fi
}
# 3. Download and Extract (If needed)
if [ ! -f "server/index.js" ]; then
echo -e "${YELLOW}Project files not found. Starting download...${NC}"
if ! command -v curl &> /dev/null; then
echo -e "${BLUE}Installing curl...${NC}"
[ "$OS_ID" = "ubuntu" ] || [ "$OS_ID" = "debian" ] && sudo apt-get install -y curl
[ "$OS_ID" = "centos" ] || [ "$OS_ID" = "rhel" ] && sudo yum install -y curl
fi
if ! command -v unzip &> /dev/null; then
echo -e "${BLUE}Installing unzip...${NC}"
[ "$OS_ID" = "ubuntu" ] || [ "$OS_ID" = "debian" ] && sudo apt-get install -y unzip
[ "$OS_ID" = "centos" ] || [ "$OS_ID" = "rhel" ] && sudo yum install -y unzip
fi
TEMP_ZIP="promdatapanel_${VERSION}.zip"
echo -e "${BLUE}Downloading ${DOWNLOAD_URL}...${NC}"
curl -L "$DOWNLOAD_URL" -o "$TEMP_ZIP"
if [ $? -ne 0 ]; then
echo -e "${RED}Download failed.${NC}"
exit 1
fi
echo -e "${BLUE}Extracting files...${NC}"
unzip -q "$TEMP_ZIP"
EXTRACTED_DIR=$(ls -d */ | grep -E "^PromdataPanel" | head -n 1)
if [ -d "$EXTRACTED_DIR" ]; then
cd "$EXTRACTED_DIR" || exit 1
else
EXTRACTED_DIR=$(ls -d */ | head -n 1)
[ -d "$EXTRACTED_DIR" ] && cd "$EXTRACTED_DIR" || exit 1
fi
rm "../$TEMP_ZIP" 2>/dev/null || rm "$TEMP_ZIP" 2>/dev/null
fi
# 4. Initialize Setup
# Permission check
if [ "$EUID" -eq 0 ]; then if [ "$EUID" -eq 0 ]; then
# If run as sudo, get the real user that called it
REAL_USER=${SUDO_USER:-$USER} REAL_USER=${SUDO_USER:-$USER}
else else
REAL_USER=$USER REAL_USER=$USER
fi fi
# 2. Get current directory and user detect_os
PROJECT_DIR=$(pwd) install_node
USER_HOME=$(getent passwd "$REAL_USER" | cut -d: -f6)
PROJECT_DIR=$(pwd)
echo -e "Project Directory: ${GREEN}$PROJECT_DIR${NC}" echo -e "Project Directory: ${GREEN}$PROJECT_DIR${NC}"
echo -e "Running User: ${GREEN}$REAL_USER${NC}" echo -e "Running User: ${GREEN}$REAL_USER${NC}"
# 3. Check for mandatory files # Check for .env file
if [ ! -f "server/index.js" ]; then
echo -e "${RED}Error: server/index.js not found. Please run this script from the project root.${NC}"
exit 1
fi
# 4. Check for dependencies
echo -e "${BLUE}Checking dependencies...${NC}"
check_dep() {
if ! command -v "$1" &> /dev/null; then
echo -e "${RED}$1 is not installed. Please install $1 first.${NC}"
exit 1
fi
}
check_dep node
check_dep npm
# 5. Check for .env file
if [ ! -f ".env" ]; then if [ ! -f ".env" ]; then
echo -e "${YELLOW}Warning: .env file not found.${NC}"
if [ -f ".env.example" ]; then if [ -f ".env.example" ]; then
echo -e "Creating .env from .env.example..." echo -e "${BLUE}Creating .env from .env.example...${NC}"
cp .env.example .env cp .env.example .env
echo -e "${GREEN}Created .env file. Please ensure values are correct.${NC}"
else
echo -e "${RED}Error: .env.example not found. Configuration missing.${NC}"
fi fi
fi fi
# 6. Install NPM dependencies # 5. Install Dependencies
echo -e "${BLUE}Installing dependencies...${NC}" echo -e "${BLUE}Installing NPM dependencies...${NC}"
npm install npm install --production
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo -e "${RED}NPM install failed.${NC}" echo -e "${RED}NPM install failed.${NC}"
exit 1 exit 1
fi fi
# 7. Create Systemd Service File # 6. Create Systemd Service File
SERVICE_FILE="/etc/systemd/system/promdatapanel.service" SERVICE_FILE="/etc/systemd/system/promdatapanel.service"
NODE_PATH=$(command -v node) NODE_PATH=$(command -v node)
echo -e "${BLUE}Creating systemd service at $SERVICE_FILE... (May require password)${NC}" echo -e "${BLUE}Creating systemd service at $SERVICE_FILE...${NC}"
sudo bash -c "cat <<EOF > '$SERVICE_FILE' sudo bash -c "cat <<EOF > '$SERVICE_FILE'
[Unit] [Unit]
Description=Data Visualization Display Wall Description=PromdataPanel Monitoring Dashboard
After=network.target mysql.service redis-server.service valkey-server.service After=network.target mysql.service redis-server.service valkey-server.service
Wants=mysql.service Wants=mysql.service
@@ -86,153 +165,33 @@ RestartSec=10
StandardOutput=syslog StandardOutput=syslog
StandardError=syslog StandardError=syslog
SyslogIdentifier=promdatapanel SyslogIdentifier=promdatapanel
# Pass environment via .env file injection
EnvironmentFile=-$PROJECT_DIR/.env EnvironmentFile=-$PROJECT_DIR/.env
Environment=NODE_ENV=production Environment=NODE_ENV=production
# Security Hardening
CapabilityBoundingSet=
NoNewPrivileges=true
LimitNOFILE=65535
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
EOF" EOF"
# 8. Reload Systemd and Start # 7. Reload and Start
echo -e "${BLUE}Reloading systemd and restarting service... (May require password)${NC}" echo -e "${BLUE}Reloading systemd and restarting service...${NC}"
sudo systemctl daemon-reload sudo systemctl daemon-reload
sudo systemctl enable promdatapanel sudo systemctl enable promdatapanel
sudo systemctl restart promdatapanel sudo systemctl restart promdatapanel
# 9. Check Status # 8. Check Status
echo -e "${BLUE}Checking service status...${NC}" echo -e "${BLUE}Checking service status...${NC}"
sleep 2 sleep 2
if sudo systemctl is-active --quiet promdatapanel; then if sudo systemctl is-active --quiet promdatapanel; then
echo -e "${GREEN}SUCCESS: Service is now running.${NC}" echo -e "${GREEN}SUCCESS: PromdataPanel is now running.${NC}"
PORT=$(grep "^PORT=" .env | cut -d'=' -f2) PORT=$(grep "^PORT=" .env | cut -d'=' -f2)
PORT=${PORT:-3000} PORT=${PORT:-3000}
echo -e "Dashboard URL: ${YELLOW}http://localhost:${PORT}${NC}" IP_ADDR=$(hostname -I | awk '{print $1}')
echo -e "View logs: ${BLUE}journalctl -u promdatapanel -f${NC}" echo -e "Dashboard URL: ${YELLOW}http://${IP_ADDR}:${PORT}${NC}"
else else
echo -e "${RED}FAILED: Service failed to start.${NC}" echo -e "${RED}FAILED: Service failed to start.${NC}"
echo -e "Check logs with: ${BLUE}journalctl -u promdatapanel -xe${NC}" echo -e "Check logs with: ${BLUE}journalctl -u promdatapanel -xe${NC}"
fi fi
# 10. Reverse Proxy Configuration
echo -ne "${YELLOW}Do you want to configure a reverse proxy (Nginx/Caddy)? (y/n): ${NC}"
read -r CONF_PROXY
if [[ "$CONF_PROXY" =~ ^[Yy]$ ]]; then
echo -e "${BLUE}=== Reverse Proxy Configuration ===${NC}"
# Get Domain
echo -ne "Enter your domain name (e.g., monitor.example.com): "
read -r DOMAIN
if [ -z "$DOMAIN" ]; then
echo -e "${RED}Error: Domain cannot be empty. Skipping proxy configuration.${NC}"
else
# Get Port from .env
PORT=$(grep "^PORT=" .env | cut -d'=' -f2)
PORT=${PORT:-3000}
# Choose Proxy
echo -e "Select Proxy Type:"
echo -e " 1) Caddy (Automatic SSL, easy to use)"
echo -e " 2) Nginx (Advanced, manual SSL)"
echo -ne "Choose (1/2): "
read -r PROXY_TYPE
# Enable HTTPS?
echo -ne "Enable HTTPS (SSL)? (y/n): "
read -r ENABLE_HTTPS
if [ "$PROXY_TYPE" == "1" ]; then
# Caddy Config
CADDY_FILE="Caddyfile"
echo -e "${BLUE}Generating Caddyfile...${NC}"
if [[ "$ENABLE_HTTPS" =~ ^[Yy]$ ]]; then
cat <<EOF > "$CADDY_FILE"
$DOMAIN {
reverse_proxy localhost:$PORT
}
EOF
else
cat <<EOF > "$CADDY_FILE"
http://$DOMAIN {
reverse_proxy localhost:$PORT
}
EOF
fi
echo -e "${GREEN}Caddyfile generated at $PROJECT_DIR/$CADDY_FILE${NC}"
echo -e "${YELLOW}Tip: Ensure Caddy is installed and pointing to this file.${NC}"
elif [ "$PROXY_TYPE" == "2" ]; then
# Nginx Config
echo -ne "Enter Nginx configuration export path (default: ./${DOMAIN}.conf): "
read -r NGINX_PATH
NGINX_PATH=${NGINX_PATH:-"./${DOMAIN}.conf"}
echo -e "${BLUE}Generating Nginx configuration...${NC}"
if [[ "$ENABLE_HTTPS" =~ ^[Yy]$ ]]; then
echo -ne "Enter SSL Certificate Path: "
read -r SSL_CERT
echo -ne "Enter SSL Key Path: "
read -r SSL_KEY
cat <<EOF > "$NGINX_PATH"
server {
listen 80;
server_name $DOMAIN;
return 301 https://\$host\$request_uri;
}
server {
listen 443 ssl http2;
server_name $DOMAIN;
ssl_certificate $SSL_CERT;
ssl_certificate_key $SSL_KEY;
location / {
proxy_pass http://localhost:$PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF
else
cat <<EOF > "$NGINX_PATH"
server {
listen 80;
server_name $DOMAIN;
location / {
proxy_pass http://localhost:$PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
}
EOF
fi
echo -e "${GREEN}Nginx config generated at $NGINX_PATH${NC}"
echo -e "${YELLOW}Tip: You can symlink this to /etc/nginx/sites-enabled/ to activate.${NC}"
else
echo -e "${YELLOW}Unknown proxy type selected. Skipping.${NC}"
fi
fi
fi
echo -e "${BLUE}================================================${NC}" echo -e "${BLUE}================================================${NC}"
echo -e "${GREEN}Setup completed successfully!${NC}" echo -e "${GREEN}Installation completed!${NC}"
echo -e "${BLUE}================================================${NC}"

View File

@@ -1,5 +1,5 @@
{ {
"name": "data-visualization-display-wall", "name": "promdatapanel",
"version": "1.0.0", "version": "1.0.0",
"description": "Data Visualization Display Wall - Multi-Prometheus Monitoring Dashboard", "description": "Data Visualization Display Wall - Multi-Prometheus Monitoring Dashboard",
"main": "server/index.js", "main": "server/index.js",