Files
argus/src/metric/client-plugins/all-in-one-full/plugins/node-exporter/install.sh
yuyr 59a38513a4 完成a6000测试系统构建、部署、测试整合 (#35)
测试方案:

- lm2机器端口映射到本机:18080, 18081, 8082-8085
- 访问URL: http://localhost:18080/dashboard

![image.png](/attachments/30ed6e20-697a-4d3b-a6d3-6acccd2e9922)

![image.png](/attachments/38ef1751-0f3b-49c6-9100-f70d15617acc)

![image.png](/attachments/3be45005-9b9e-4165-8ef6-1d27405800f1)

![image.png](/attachments/eb916192-edc1-4096-8f9f-9769ab6d9039)

![image.png](/attachments/620e6efc-bd02-45ae-bba1-99a95a1b4c02)

![image.png](/attachments/986e77e7-c687-405f-a760-93282249f72f)

端到端测试通过:

![image.png](/attachments/c6e29875-4a16-4718-8b2f-368f64eb545e)

Co-authored-by: sundapeng.sdp <sundapeng@hashdata.cn>
Reviewed-on: #35
Reviewed-by: xuxt <xuxt@zgclab.edu.cn>
Reviewed-by: sundapeng <sundp@mail.zgclab.edu.cn>
Reviewed-by: huhy <husteryezi@163.com>
2025-10-29 10:04:27 +08:00

344 lines
9.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 更新安装记录
update_install_record() {
local pid="$1"
# 使用传入的安装目录参数,如果没有则使用默认值
local install_base_dir="${2:-/opt/argus-metric/current}"
local install_record="$install_base_dir/.install_record"
# 如果安装记录文件不存在,说明是首次安装,由主安装脚本统一创建
if [[ ! -f "$install_record" ]]; then
log_info "安装记录文件不存在,将由主安装脚本创建"
return 0
fi
# 如果文件存在,说明是重启场景,只更新 PID 字段
if command -v jq &> /dev/null; then
# 读取当前 PID
local current_pid=$(jq -r '.components."node-exporter".pid // ""' "$install_record" 2>/dev/null)
if [[ -z "$current_pid" ]]; then
log_warning "无法读取当前 PID,跳过更新"
return 1
fi
# 使用 jq 只更新 pid 字段,保持字符串类型,保留其他字段
jq --arg new_pid "$pid" '.components."node-exporter".pid = $new_pid' "$install_record" > "$install_record.tmp" && mv "$install_record.tmp" "$install_record"
log_info "PID 已更新: $current_pid -> $pid"
else
log_warning "jq 命令不可用,无法更新安装记录文件"
fi
}
# 显示帮助信息
show_help() {
echo "Node Exporter 安装脚本"
echo
echo "用法: $0 [选项]"
echo
echo "选项:"
echo " --help 显示此帮助信息"
echo
echo "示例:"
echo " $0 # 安装 Node Exporter"
echo
}
# 解析命令行参数
INSTALL_DIR=""
for arg in "$@"; do
case $arg in
--help|-h)
show_help
exit 0
;;
*)
# 如果参数不是以--开头,则认为是安装目录
if [[ ! "$arg" =~ ^-- ]]; then
INSTALL_DIR="$arg"
else
log_error "未知参数: $arg"
show_help
exit 1
fi
;;
esac
done
# 检查是否为 root 用户
check_root() {
if [[ $EUID -ne 0 ]]; then
log_error "此脚本需要 root 权限运行"
log_info "请使用: sudo $0"
exit 1
fi
}
# 检查系统要求
check_system() {
log_info "检查系统要求..."
# 检查操作系统
if [[ ! -f /etc/os-release ]]; then
log_error "无法检测操作系统版本"
exit 1
fi
source /etc/os-release
log_info "检测到操作系统: $NAME $VERSION"
# 检查是否为 Linux 系统
if [[ "$ID" != "ubuntu" && "$ID" != "debian" && "$ID" != "centos" && "$ID" != "rhel" && "$ID" != "fedora" ]]; then
log_warning "此脚本主要针对常见 Linux 发行版,其他系统可能需要调整"
fi
# 检查系统架构
local arch=$(uname -m)
log_info "系统架构: $arch"
if [[ "$arch" != "x86_64" && "$arch" != "amd64" ]]; then
log_warning "当前架构为 $arch,node_exporter 主要支持 x86_64/amd64"
fi
}
stop_existing_service() {
log_info "检查并停止可能运行的 Node Exporter 服务..."
# 当前脚本 PID,防止误杀
SELF_PID=$$
# 1. 停止 systemd 服务(如果存在)
if systemctl list-units --full -all | grep -q "node_exporter.service"; then
log_info "检测到 systemd 服务 node_exporter,正在停止..."
systemctl stop node_exporter || true
systemctl disable node_exporter || true
fi
# 2. 清理可能存在的 PID 文件
for pid_file in /var/run/node-exporter.pid /var/run/node_exporter.pid /tmp/node_exporter.pid; do
if [[ -f "$pid_file" ]]; then
local pid=$(cat "$pid_file")
if kill -0 "$pid" 2>/dev/null; then
log_info "发现 Node Exporter (PID: $pid),正在停止..."
kill "$pid"
sleep 2
kill -0 "$pid" 2>/dev/null && kill -9 "$pid"
fi
rm -f "$pid_file"
fi
done
# 3. 用 pgrep 查找进程,排除当前脚本
local pids=$(pgrep -f "node_exporter|node-exporter|/usr/local/bin/node-exporter" | grep -vw "$SELF_PID" || true)
if [[ -n "$pids" ]]; then
log_info "发现 Node Exporter 进程 (PID: $pids),正在停止..."
for pid in $pids; do
if kill -0 "$pid" 2>/dev/null; then
kill "$pid" 2>/dev/null || true
sleep 1
kill -0 "$pid" 2>/dev/null && kill -9 "$pid" 2>/dev/null || true
fi
done
fi
# 4. 兜底:检查是否有进程占用 9100 端口
local listen_pids=$(lsof -ti:9100 2>/dev/null || true)
if [[ -n "$listen_pids" ]]; then
log_warning "发现占用 9100 端口的进程 (PID: $listen_pids),强制终止..."
for pid in $listen_pids; do
kill -9 "$pid" 2>/dev/null || true
done
sleep 1
fi
# 5. 最终验证
if netstat -tuln 2>/dev/null | grep -q ":9100 "; then
log_error "端口 9100 仍被占用,请手动检查"
return 1
else
log_success "旧的 Node Exporter 已完全停止"
fi
}
# 安装 Node Exporter 二进制文件
install_node_exporter() {
log_info "安装 Node Exporter..."
local binary_file="bin/node_exporter"
local install_dir="/usr/local/bin"
if [[ ! -f "$binary_file" ]]; then
log_error "找不到 Node Exporter 二进制文件: $binary_file"
exit 1
fi
# 停止可能运行的服务
stop_existing_service
# 复制二进制文件并重命名为统一格式
cp "$binary_file" "$install_dir/node-exporter"
chmod +x "$install_dir/node-exporter"
log_success "Node Exporter 二进制文件安装完成"
}
# 创建用户和组
create_user() {
log_info "创建 node_exporter 用户..."
# 检查用户是否已存在
if id "node_exporter" &>/dev/null; then
log_info "用户 node_exporter 已存在"
else
useradd --no-create-home --shell /bin/false node_exporter
log_success "用户 node_exporter 创建完成"
fi
}
# 安装配置文件
install_config() {
log_info "安装配置文件..."
local config_dir="/etc/node_exporter"
# 创建配置目录
mkdir -p "$config_dir"
# 创建文本文件收集器目录
mkdir -p "/var/lib/node_exporter/textfile_collector"
chown node_exporter:node_exporter "/var/lib/node_exporter/textfile_collector"
}
# 启动 Node Exporter 服务
start_node_exporter() {
log_info "启动 Node Exporter 服务..."
local binary_path="/usr/local/bin/node-exporter"
local log_file="/var/log/node-exporter.log"
local pid_file="/var/run/node-exporter.pid"
# 检查服务是否已经在运行
if [[ -f "$pid_file" ]]; then
local pid=$(cat "$pid_file")
if kill -0 "$pid" 2>/dev/null; then
log_info "Node Exporter 服务已在运行 (PID: $pid)"
return 0
else
log_warning "发现过期的 PID 文件,正在清理..."
rm -f "$pid_file"
fi
fi
# 检查端口是否被占用
if netstat -tuln 2>/dev/null | grep -q ":9100 "; then
log_warning "端口 9100 已被占用,请检查是否有其他服务在运行"
return 1
fi
# 启动服务
log_info "正在启动 Node Exporter..."
nohup "$binary_path" --web.listen-address=:9100 > "$log_file" 2>&1 &
local pid=$!
# 保存 PID
echo "$pid" > "$pid_file"
# 等待服务启动
sleep 2
# 检查服务是否成功启动
if kill -0 "$pid" 2>/dev/null; then
log_success "Node Exporter 服务启动成功 (PID: $pid)"
log_info "日志文件: $log_file"
log_info "PID 文件: $pid_file"
# 更新安装记录
update_install_record "$pid" "$INSTALL_DIR"
else
log_error "Node Exporter 服务启动失败"
rm -f "$pid_file"
return 1
fi
}
# 显示安装信息
show_install_info() {
log_success "Node Exporter 安装完成!"
echo
echo "安装信息:"
echo " 二进制文件: /usr/local/bin/node-exporter"
echo " 运行用户: node_exporter"
echo " 配置目录: /etc/node_exporter/"
echo " 默认端口: 9100"
echo
echo "使用方法:"
echo " 手动启动: /usr/local/bin/node-exporter --web.listen-address=:9100"
echo " 后台启动: nohup /usr/local/bin/node-exporter --web.listen-address=:9100 &"
echo
echo "测试连接:"
echo " curl http://localhost:9100/metrics"
echo " curl http://localhost:9100"
echo
echo "Prometheus 配置示例:"
echo " - job_name: 'node_exporter'"
echo " static_configs:"
echo " - targets: ['localhost:9100']"
echo
}
# 主函数
main() {
echo "=========================================="
echo " Node Exporter 安装脚本 v1.0"
echo "=========================================="
echo
check_root
check_system
log_info "开始安装 Node Exporter..."
install_node_exporter
create_user
install_config
start_node_exporter
show_install_info
}
# 脚本入口
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi