提交
This commit is contained in:
311
install.sh
311
install.sh
@@ -48,14 +48,30 @@ fi
|
||||
|
||||
# 检测系统类型和架构
|
||||
detect_system() {
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS=$ID
|
||||
OS_VERSION=$VERSION_ID
|
||||
else
|
||||
echo -e "${RED}无法检测系统类型${NC}"
|
||||
exit 1
|
||||
fi
|
||||
# 检测操作系统类型(linux/darwin/windows)
|
||||
OS_TYPE=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
case $OS_TYPE in
|
||||
linux)
|
||||
OS_TYPE="linux"
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS=$ID
|
||||
OS_VERSION=$VERSION_ID
|
||||
else
|
||||
OS="linux"
|
||||
OS_VERSION=""
|
||||
fi
|
||||
;;
|
||||
darwin)
|
||||
OS_TYPE="darwin"
|
||||
OS="darwin"
|
||||
OS_VERSION=$(sw_vers -productVersion 2>/dev/null || echo "")
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}不支持的操作系统: $OS_TYPE${NC}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
ARCH=$(uname -m)
|
||||
case $ARCH in
|
||||
@@ -71,7 +87,7 @@ detect_system() {
|
||||
;;
|
||||
esac
|
||||
|
||||
echo -e "${BLUE}检测到系统: $OS $OS_VERSION ($ARCH)${NC}"
|
||||
echo -e "${BLUE}检测到系统: $OS_TYPE $OS_VERSION ($ARCH)${NC}"
|
||||
}
|
||||
|
||||
# 检测并选择最快的镜像源
|
||||
@@ -628,6 +644,256 @@ uninstall_service() {
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 尝试从 Releases 下载二进制文件
|
||||
download_binary_from_releases() {
|
||||
echo -e "${BLUE}尝试从 Releases 下载预编译二进制文件...${NC}"
|
||||
|
||||
# Gitea API 地址
|
||||
local api_base="https://gitee.nas.cpolar.cn/api/v1"
|
||||
local repo_api="${api_base}/repos/${GITHUB_REPO}"
|
||||
|
||||
# 获取所有 releases(按创建时间排序,最新的在前)
|
||||
echo -e "${BLUE}获取最新 release 信息...${NC}"
|
||||
local releases_response=$(curl -s -X GET "${repo_api}/releases?limit=10" 2>/dev/null)
|
||||
|
||||
if [ $? -ne 0 ] || [ -z "$releases_response" ]; then
|
||||
echo -e "${YELLOW}⚠ 无法获取 releases 信息,将使用源码编译${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 解析所有 releases,找到最新的(按创建时间或版本号)
|
||||
# Gitea API 返回的 releases 通常已经按创建时间倒序排列
|
||||
# 但我们还是需要解析并验证
|
||||
|
||||
# 提取所有 tag 和对应的 release_id、创建时间
|
||||
local latest_tag=""
|
||||
local latest_release_id=""
|
||||
local latest_created_at=""
|
||||
|
||||
# 使用更健壮的方式解析 JSON(虽然简单,但能工作)
|
||||
# 查找第一个有效的 release(非 draft,非 prerelease)
|
||||
local tag_line=$(echo "$releases_response" | grep -o '"tag_name":"[^"]*"' | head -1)
|
||||
local id_line=$(echo "$releases_response" | grep -o '"id":[0-9]*' | head -1)
|
||||
local created_line=$(echo "$releases_response" | grep -o '"created_at":"[^"]*"' | head -1)
|
||||
local draft_line=$(echo "$releases_response" | grep -o '"draft":[^,}]*' | head -1)
|
||||
local prerelease_line=$(echo "$releases_response" | grep -o '"prerelease":[^,}]*' | head -1)
|
||||
|
||||
# 检查是否是 draft 或 prerelease
|
||||
if echo "$draft_line" | grep -q "true" || echo "$prerelease_line" | grep -q "true"; then
|
||||
# 如果是 draft 或 prerelease,尝试找下一个
|
||||
echo -e "${YELLOW}⚠ 第一个 release 是草稿或预发布版本,查找正式版本...${NC}"
|
||||
# 简化处理:如果第一个是预发布,仍然使用它(因为可能是最新的)
|
||||
fi
|
||||
|
||||
latest_tag=$(echo "$tag_line" | cut -d'"' -f4)
|
||||
latest_release_id=$(echo "$id_line" | cut -d':' -f2)
|
||||
latest_created_at=$(echo "$created_line" | cut -d'"' -f4)
|
||||
|
||||
if [ -z "$latest_tag" ] || [ -z "$latest_release_id" ]; then
|
||||
echo -e "${YELLOW}⚠ 无法解析 release 信息,将使用源码编译${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 显示找到的版本信息
|
||||
echo -e "${GREEN}✓ 找到最新版本: ${latest_tag}${NC}"
|
||||
if [ -n "$latest_created_at" ]; then
|
||||
echo -e "${BLUE} 发布日期: ${latest_created_at}${NC}"
|
||||
fi
|
||||
|
||||
# 构建文件名(根据系统类型)
|
||||
local file_name="agent-${OS_TYPE}-${ARCH}-${latest_tag}"
|
||||
local file_ext="tar.gz"
|
||||
if [ "$OS_TYPE" = "windows" ]; then
|
||||
file_ext="zip"
|
||||
fi
|
||||
local full_file_name="${file_name}.${file_ext}"
|
||||
|
||||
# 获取 release 的详细信息(包含 commit hash)
|
||||
local release_detail=$(curl -s -X GET "${repo_api}/releases/${latest_release_id}" 2>/dev/null)
|
||||
|
||||
if [ $? -ne 0 ] || [ -z "$release_detail" ]; then
|
||||
echo -e "${YELLOW}⚠ 无法获取 release 详细信息,将使用源码编译${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 解析 release 对应的 commit hash(target_commitish)
|
||||
local release_commit=$(echo "$release_detail" | grep -o '"target_commitish":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||||
|
||||
# 如果 release_detail 中没有 target_commitish,尝试通过 tag 获取 commit hash
|
||||
if [ -z "$release_commit" ]; then
|
||||
# 通过 tag API 获取 commit hash
|
||||
local tag_info=$(curl -s -X GET "${repo_api}/git/tags/${latest_tag}" 2>/dev/null)
|
||||
if [ $? -eq 0 ] && [ -n "$tag_info" ]; then
|
||||
release_commit=$(echo "$tag_info" | grep -o '"sha":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||||
fi
|
||||
fi
|
||||
|
||||
# 如果还是无法获取 commit hash,使用 assets_response 继续(不强制要求 commit)
|
||||
local assets_response="$release_detail"
|
||||
|
||||
# 查找匹配的二进制文件
|
||||
local download_url=$(echo "$assets_response" | grep -o "\"browser_download_url\":\"[^\"]*${full_file_name}[^\"]*\"" | head -1 | cut -d'"' -f4)
|
||||
|
||||
if [ -z "$download_url" ]; then
|
||||
echo -e "${YELLOW}⚠ 未找到匹配的二进制文件: ${full_file_name}${NC}"
|
||||
echo -e "${YELLOW} 将使用源码编译${NC}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}下载二进制文件: ${full_file_name}...${NC}"
|
||||
|
||||
# 创建临时目录
|
||||
local temp_dir=$(mktemp -d)
|
||||
local download_file="${temp_dir}/${full_file_name}"
|
||||
|
||||
# 下载文件
|
||||
if ! curl -fsSL -o "$download_file" "$download_url" 2>/dev/null; then
|
||||
echo -e "${YELLOW}⚠ 下载失败,将使用源码编译${NC}"
|
||||
rm -rf "$temp_dir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 检查文件大小(至少应该大于 1MB)
|
||||
local file_size=$(stat -f%z "$download_file" 2>/dev/null || stat -c%s "$download_file" 2>/dev/null || echo "0")
|
||||
if [ "$file_size" -lt 1048576 ]; then
|
||||
echo -e "${YELLOW}⚠ 下载的文件大小异常,将使用源码编译${NC}"
|
||||
rm -rf "$temp_dir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 解压文件
|
||||
echo -e "${BLUE}解压二进制文件...${NC}"
|
||||
cd "$temp_dir"
|
||||
|
||||
if [ "$file_ext" = "tar.gz" ]; then
|
||||
if ! tar -xzf "$download_file" 2>/dev/null; then
|
||||
echo -e "${YELLOW}⚠ 解压失败,将使用源码编译${NC}"
|
||||
rm -rf "$temp_dir"
|
||||
return 1
|
||||
fi
|
||||
# 查找解压后的二进制文件(优先查找 agent,然后是 agent-*)
|
||||
local binary_file=""
|
||||
if [ -f "./agent" ] && [ -x "./agent" ]; then
|
||||
binary_file="./agent"
|
||||
else
|
||||
binary_file=$(find . -maxdepth 1 -type f \( -name "agent" -o -name "agent-*" -o -name "Agent" -o -name "Agent-*" \) ! -name "*.tar.gz" ! -name "*.zip" 2>/dev/null | head -1)
|
||||
fi
|
||||
else
|
||||
# Windows zip 文件(虽然脚本主要在 Linux 上运行,但保留兼容性)
|
||||
if ! unzip -q "$download_file" 2>/dev/null; then
|
||||
echo -e "${YELLOW}⚠ 解压失败,将使用源码编译${NC}"
|
||||
rm -rf "$temp_dir"
|
||||
return 1
|
||||
fi
|
||||
local binary_file=$(find . -maxdepth 1 -type f \( -name "agent*.exe" -o -name "Agent*.exe" \) 2>/dev/null | head -1)
|
||||
fi
|
||||
|
||||
if [ -z "$binary_file" ] || [ ! -f "$binary_file" ]; then
|
||||
echo -e "${YELLOW}⚠ 未找到解压后的二进制文件,将使用源码编译${NC}"
|
||||
echo -e "${YELLOW} 解压目录内容:${NC}"
|
||||
ls -la "$temp_dir" 2>/dev/null || true
|
||||
rm -rf "$temp_dir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 验证二进制文件是否可执行
|
||||
if [ ! -x "$binary_file" ]; then
|
||||
chmod +x "$binary_file" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 验证二进制文件类型(Linux 应该是 ELF 文件)
|
||||
if [ "$OS_TYPE" = "linux" ]; then
|
||||
if command -v file > /dev/null 2>&1; then
|
||||
local file_type=$(file "$binary_file" 2>/dev/null || echo "")
|
||||
if [ -n "$file_type" ] && ! echo "$file_type" | grep -qi "ELF"; then
|
||||
echo -e "${YELLOW}⚠ 二进制文件类型异常: ${file_type}${NC}"
|
||||
echo -e "${YELLOW} 将使用源码编译${NC}"
|
||||
rm -rf "$temp_dir"
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# 保存下载的二进制文件到临时位置
|
||||
local downloaded_binary="${temp_dir}/downloaded_agent"
|
||||
sudo cp "$binary_file" "$downloaded_binary"
|
||||
sudo chmod +x "$downloaded_binary"
|
||||
|
||||
# 验证复制后的文件
|
||||
if [ ! -f "$downloaded_binary" ] || [ ! -x "$downloaded_binary" ]; then
|
||||
echo -e "${YELLOW}⚠ 二进制文件验证失败,将使用源码编译${NC}"
|
||||
rm -rf "$temp_dir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 清理临时下载文件
|
||||
rm -f "$download_file"
|
||||
|
||||
# 克隆仓库(用于获取 run.sh 和 start-systemd.sh 等脚本)
|
||||
echo -e "${BLUE}克隆仓库以获取启动脚本...${NC}"
|
||||
if [ -d "$SOURCE_DIR" ]; then
|
||||
sudo rm -rf "$SOURCE_DIR"
|
||||
fi
|
||||
|
||||
if ! sudo git clone --branch "${GITHUB_BRANCH}" "https://gitee.nas.cpolar.cn/${GITHUB_REPO}.git" "$SOURCE_DIR" 2>&1; then
|
||||
echo -e "${YELLOW}⚠ 克隆仓库失败,将使用源码编译${NC}"
|
||||
rm -rf "$temp_dir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 对比 Git commit hash
|
||||
if [ -n "$release_commit" ]; then
|
||||
echo -e "${BLUE}验证 Git commit 版本...${NC}"
|
||||
cd "$SOURCE_DIR"
|
||||
|
||||
# 获取当前分支的最新 commit hash
|
||||
local current_commit=$(git rev-parse HEAD 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$current_commit" ]; then
|
||||
# 截取短 commit hash 用于显示(前7位)
|
||||
local release_commit_short=$(echo "$release_commit" | cut -c1-7)
|
||||
local current_commit_short=$(echo "$current_commit" | cut -c1-7)
|
||||
|
||||
echo -e "${BLUE} Release commit: ${release_commit_short}${NC}"
|
||||
echo -e "${BLUE} 当前代码 commit: ${current_commit_short}${NC}"
|
||||
|
||||
# 对比 commit hash
|
||||
if [ "$release_commit" != "$current_commit" ]; then
|
||||
echo -e "${YELLOW}⚠ Commit hash 不匹配,二进制文件可能不是最新代码编译的${NC}"
|
||||
echo -e "${YELLOW} Release 基于较旧的代码,将使用源码编译最新版本${NC}"
|
||||
rm -rf "$temp_dir"
|
||||
return 1
|
||||
else
|
||||
echo -e "${GREEN}✓ Commit hash 匹配,二进制文件是最新代码编译的${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}⚠ 无法获取当前代码的 commit hash,跳过验证${NC}"
|
||||
fi
|
||||
else
|
||||
echo -e "${YELLOW}⚠ 无法获取 release 的 commit hash,跳过验证${NC}"
|
||||
fi
|
||||
|
||||
# 用下载的二进制文件覆盖克隆目录中的文件
|
||||
sudo cp "$downloaded_binary" "$SOURCE_DIR/agent"
|
||||
sudo chmod +x "$SOURCE_DIR/agent"
|
||||
|
||||
# 复制到安装目录
|
||||
sudo mkdir -p "$INSTALL_DIR"
|
||||
sudo cp "$SOURCE_DIR/agent" "$INSTALL_DIR/$BINARY_NAME"
|
||||
sudo chmod +x "$INSTALL_DIR/$BINARY_NAME"
|
||||
|
||||
# 清理临时文件
|
||||
rm -rf "$temp_dir"
|
||||
|
||||
# 显示文件信息
|
||||
local binary_size=$(du -h "$SOURCE_DIR/agent" | cut -f1)
|
||||
echo -e "${GREEN}✓ 二进制文件下载完成 (文件大小: ${binary_size})${NC}"
|
||||
echo -e "${BLUE}版本: ${latest_tag}${NC}"
|
||||
echo -e "${BLUE}二进制文件: ${SOURCE_DIR}/agent${NC}"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# 从源码编译安装
|
||||
build_from_source() {
|
||||
echo -e "${BLUE}从源码编译安装节点端...${NC}"
|
||||
@@ -779,6 +1045,22 @@ create_service() {
|
||||
sudo chmod +x "$SOURCE_DIR/run.sh"
|
||||
sudo chmod +x "$SOURCE_DIR/start-systemd.sh"
|
||||
|
||||
# 检测 Go 的安装路径
|
||||
GO_PATH=""
|
||||
if [ -d "/usr/local/go/bin" ]; then
|
||||
GO_PATH="/usr/local/go/bin"
|
||||
elif command -v go > /dev/null 2>&1; then
|
||||
GO_BIN=$(command -v go)
|
||||
GO_PATH=$(dirname "$GO_BIN")
|
||||
fi
|
||||
|
||||
# 构建 PATH 环境变量
|
||||
if [ -n "$GO_PATH" ]; then
|
||||
ENV_PATH="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${GO_PATH}"
|
||||
else
|
||||
ENV_PATH="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
fi
|
||||
|
||||
sudo tee /etc/systemd/system/${SERVICE_NAME}.service > /dev/null <<EOF
|
||||
[Unit]
|
||||
Description=LinkMaster Node Service
|
||||
@@ -792,6 +1074,7 @@ ExecStart=$SOURCE_DIR/start-systemd.sh
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
Environment="BACKEND_URL=$BACKEND_URL"
|
||||
Environment="$ENV_PATH"
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1032,7 +1315,15 @@ main() {
|
||||
detect_fastest_mirror
|
||||
|
||||
install_dependencies
|
||||
build_from_source
|
||||
|
||||
# 优先尝试从 Releases 下载二进制文件
|
||||
if ! download_binary_from_releases; then
|
||||
echo -e "${BLUE}从 Releases 下载失败,开始从源码编译...${NC}"
|
||||
build_from_source
|
||||
else
|
||||
echo -e "${GREEN}✓ 使用预编译二进制文件,跳过编译步骤${NC}"
|
||||
fi
|
||||
|
||||
create_service
|
||||
configure_firewall
|
||||
register_node
|
||||
|
||||
Reference in New Issue
Block a user