mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-13 18:36:37 +08:00
[优化] 部署脚本优化
This commit is contained in:
@@ -20,12 +20,16 @@ sidebar: false
|
|||||||
|
|
||||||
### 新增
|
### 新增
|
||||||
|
|
||||||
|
- 新增 Agent 交互式安装向导,支持选择本地安装和 Docker 运行模式;未传参数时自动进入交互菜单
|
||||||
|
- 新增 Docker 运行模式的智能环境检查,检测到未安装 Docker 时支持一键在线安装,中国大陆环境支持多镜像源自动测速优选与加速器配置
|
||||||
|
- 新增 Agent 交互式卸载向导,支持选择本地卸载和 Docker 容器卸载模式;未传参数时自动进入交互菜单
|
||||||
- 新增 Pages 静态托管使用指南(`pages-usage.md`),讲解 ZIP 上传、SPA Fallback 与 API 代理配置
|
- 新增 Pages 静态托管使用指南(`pages-usage.md`),讲解 ZIP 上传、SPA Fallback 与 API 代理配置
|
||||||
- 新增 Uptime Kuma 监控同步集成指南(`uptime-kuma.md`),说明同步参数与专属标签隔离机制
|
- 新增 Uptime Kuma 监控同步集成指南(`uptime-kuma.md`),说明同步参数与专属标签隔离机制
|
||||||
- 完善 WAF IP 组订阅模式使用指南(`waf-usage.md`),补充 JSON 路径提取映射规则与同步参数说明
|
- 完善 WAF IP 组订阅模式使用指南(`waf-usage.md`),补充 JSON 路径提取映射规则与同步参数说明
|
||||||
|
|
||||||
### 变更
|
### 变更
|
||||||
|
|
||||||
|
- 重构 `install-agent.sh` 安装脚本与 `uninstall-agent.sh` 卸载脚本以兼容交互式导引、非交互式命令行参数及 Docker 部署/卸载参数(`--docker`/`--method docker`)
|
||||||
- 重构 Go 包依赖结构为统一模块(Monorepo),模块命名为 `github.com/rain-kl/openflare`
|
- 重构 Go 包依赖结构为统一模块(Monorepo),模块命名为 `github.com/rain-kl/openflare`
|
||||||
- 移除各子目录下独立的 `go.mod`/`go.sum` 文件,统一由根目录 `go.mod` 进行全局依赖管理与依赖版本锁定
|
- 移除各子目录下独立的 `go.mod`/`go.sum` 文件,统一由根目录 `go.mod` 进行全局依赖管理与依赖版本锁定
|
||||||
- 替换全仓库 Go 源文件中的内部引用路径,由本地相对路径迁移为标准 GitHub 绝对导入路径
|
- 替换全仓库 Go 源文件中的内部引用路径,由本地相对路径迁移为标准 GitHub 绝对导入路径
|
||||||
|
|||||||
+54
-11
@@ -20,7 +20,19 @@ OpenFlare Agent 运行在代理节点侧。它不会接收远程 shell 指令,
|
|||||||
|
|
||||||
## 一键安装
|
## 一键安装
|
||||||
|
|
||||||
使用 `discovery_token`:
|
### 交互式安装 (推荐)
|
||||||
|
|
||||||
|
如果在不传递任何参数的情况下运行安装脚本,脚本将进入交互模式。您将可以通过向导选择安装方式(本地运行 / Docker 容器运行),并配置 Server 地址与认证 Token(若选择 Docker 方式且本地没有 Docker,脚本还会询问并智能安装 Docker):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自动化 (非交互式) 安装
|
||||||
|
|
||||||
|
如果在执行脚本时附加了任何参数,脚本将进入自动化安装模式,不需要任何交互。
|
||||||
|
|
||||||
|
使用 `discovery_token` 进行本地安装:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \
|
curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \
|
||||||
@@ -28,7 +40,7 @@ curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/inst
|
|||||||
--discovery-token YOUR_DISCOVERY_TOKEN
|
--discovery-token YOUR_DISCOVERY_TOKEN
|
||||||
```
|
```
|
||||||
|
|
||||||
使用节点专属 `agent_token`:
|
使用节点专属 `agent_token` 进行本地安装:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \
|
curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \
|
||||||
@@ -36,19 +48,30 @@ curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/inst
|
|||||||
--agent-token YOUR_AGENT_TOKEN
|
--agent-token YOUR_AGENT_TOKEN
|
||||||
```
|
```
|
||||||
|
|
||||||
安装脚本会下载最新 Agent,默认写入 `/opt/openflare-agent`,生成 `agent.json`,并在 Linux + systemd 环境创建 `openflare-agent.service`。
|
使用 Docker 容器自动化安装:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/install-agent.sh | bash -s -- \
|
||||||
|
--server-url http://your-server:3000 \
|
||||||
|
--discovery-token YOUR_DISCOVERY_TOKEN \
|
||||||
|
--docker
|
||||||
|
```
|
||||||
|
|
||||||
|
安装脚本在本地安装模式下会下载最新 Agent,默认写入 `/opt/openflare-agent`,生成 `agent.json`,并在 Linux + systemd 环境创建 `openflare-agent.service`。
|
||||||
|
|
||||||
支持参数:
|
支持参数:
|
||||||
|
|
||||||
| 参数 | 说明 |
|
| 参数 | 说明 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `--server-url` | Server 地址,必填 |
|
| `--server-url` | Server 地址 |
|
||||||
| `--discovery-token` | 首次自动注册 Token |
|
| `--discovery-token` | 首次自动注册 Token |
|
||||||
| `--agent-token` | 节点专属 Token |
|
| `--agent-token` | 节点专属 Token |
|
||||||
| `--install-dir` | 安装目录,默认 `/opt/openflare-agent` |
|
| `--install-dir` | 安装目录,默认 `/opt/openflare-agent`(仅本地安装生效) |
|
||||||
| `--openresty-path` | OpenResty 二进制路径,未传时自动查找 `openresty` |
|
| `--openresty-path` | OpenResty 二进制路径,未传时自动查找 `openresty`(仅本地安装生效) |
|
||||||
| `--repo` | 下载 Agent 的 GitHub 仓库,默认 `Rain-kl/OpenFlare` |
|
| `--repo` | 下载 Agent 的 GitHub 仓库,默认 `Rain-kl/OpenFlare` |
|
||||||
| `--no-service` | 不创建 systemd 服务 |
|
| `--no-service` | 不创建 systemd 服务(仅本地安装生效) |
|
||||||
|
| `--docker` | 使用 Docker 容器方式安装 |
|
||||||
|
| `--method` | 安装方式,可选 `local` 或 `docker`(默认 `local`) |
|
||||||
|
|
||||||
## 配置文件
|
## 配置文件
|
||||||
|
|
||||||
@@ -150,20 +173,40 @@ export LOG_LEVEL='info'
|
|||||||
|
|
||||||
## 卸载
|
## 卸载
|
||||||
|
|
||||||
如需彻底卸载 Agent 并清空本地数据:
|
### 交互式卸载 (推荐)
|
||||||
|
|
||||||
|
如果在不传递任何参数的情况下运行卸载脚本,脚本将进入交互模式。您可以通过提示菜单选择卸载方式(本地卸载 / Docker 容器卸载):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/uninstall-agent.sh | bash
|
curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/uninstall-agent.sh | bash
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 自动化 (非交互式) 卸载
|
||||||
|
|
||||||
|
使用命令行传参进行无人值守卸载。
|
||||||
|
|
||||||
|
本地卸载(默认):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/uninstall-agent.sh | bash -s -- --install-dir /opt/openflare-agent
|
||||||
|
```
|
||||||
|
|
||||||
|
Docker 容器卸载:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/Rain-kl/OpenFlare/main/scripts/uninstall-agent.sh | bash -s -- --docker
|
||||||
|
```
|
||||||
|
|
||||||
支持参数:
|
支持参数:
|
||||||
|
|
||||||
| 参数 | 说明 |
|
| 参数 | 说明 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `--install-dir` | 安装目录,默认 `/opt/openflare-agent` |
|
| `--install-dir` | 安装目录,默认 `/opt/openflare-agent`(仅本地卸载生效) |
|
||||||
| `--service-name` | systemd 服务名,默认 `openflare-agent` |
|
| `--service-name` | systemd 服务名,默认 `openflare-agent`(仅本地卸载生效) |
|
||||||
|
| `--docker` | 使用 Docker 容器方式卸载 |
|
||||||
|
| `--method` | 卸载方式,可选 `local` 或 `docker`(默认 `local`) |
|
||||||
|
|
||||||
卸载脚本只移除 Agent 服务、进程和安装目录,不会删除本机 OpenResty。
|
本地卸载只会移除 Agent 服务、进程和安装目录,不会删除本机 OpenResty。Docker 卸载会停止并删除 `openflare-agent` 容器,交互模式下还可以选择是否清理对应的 Docker 镜像。
|
||||||
|
|
||||||
## 常见问题
|
## 常见问题
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
# 交互式智能安装脚本实现计划
|
||||||
|
|
||||||
|
本计划旨在拓展 OpenFlare Agent 安装脚本的功能,支持交互式选择本地安装或 Docker 容器安装,并提供智能检测/在线安装 Docker 环境的机制,同时保留通过命令行传参进行自动化安装的既有能力。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 目标与背景 (Goal & Context)
|
||||||
|
* **需求背景**:当前安装脚本 `install-agent.sh` 仅支持在宿主机直接下载二进制并配置为本地 systemd 服务运行。随着 Docker 部署方式的普及,需要让用户在一键安装时能根据需要交互式选择 Docker 或本地部署,从而提升部署体验。
|
||||||
|
* **开发范围 (Scope)**:
|
||||||
|
* 支持交互式运行(未传参时):提示用户选择 Local 方式或 Docker 方式。
|
||||||
|
* 当选择 Docker 方式时,检测本地是否存在 `docker` 命令。若不存在,提示并在线安装 Docker(支持国内镜像源及自动测速选择最低延迟源)。
|
||||||
|
* 交互引导用户配置 `server_url` 和 `agent-token` 或 `discovery-token`。
|
||||||
|
* 如果选择 Docker,则最终拉取 Agent 镜像并运行容器;如果选择 Local,则继续原有的本地二进制下载及配置发布逻辑。
|
||||||
|
* 兼容非交互式模式:如果执行脚本时传递了任意参数,则跳过任何交互式提示,直接进行自动化安装(支持新参数 `--docker` / `--method docker` 来自动选用 Docker 部署)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 设计与决策 (Design & Decisions)
|
||||||
|
|
||||||
|
### 交互工作流
|
||||||
|
1. 检查 `$#`(参数数量)。若 `$# -eq 0`,激活 `INTERACTIVE=true`。
|
||||||
|
2. 在交互模式下:
|
||||||
|
* 引导用户选择安装方法(1: Local, 2: Docker)。
|
||||||
|
* 若选择 Docker,调用 `Install_Docker` 检测并安装环境。
|
||||||
|
* 引导用户输入 `SERVER_URL` 并进行非空校验。
|
||||||
|
* 引导用户选择 Token 类型(1: Discovery Token, 2: Agent Token),并输入对应的 Token 值。
|
||||||
|
* 若选择 Local 且未传 `--openresty-path`,如果 `openresty` 二进制未能在 $PATH 中找到,交互提示用户手动输入 OpenResty 路径。
|
||||||
|
3. 非交互模式下:
|
||||||
|
* 解析命令行参数。
|
||||||
|
* 支持通过 `--docker` 或 `--method docker` 指定 Docker 容器安装。
|
||||||
|
* 依然根据传入的 `--server-url` 和 Token 自动执行安装,绝不进行任何交互。
|
||||||
|
|
||||||
|
### 数据流与架构图
|
||||||
|
```mermaid
|
||||||
|
graph TD
|
||||||
|
Start[执行 install-agent.sh] --> CheckArgs{是否有命令行参数?}
|
||||||
|
|
||||||
|
CheckArgs -- 是 (非交互模式) --> ParseArgs[解析参数]
|
||||||
|
ParseArgs --> IsDockerParam{是否指定 Docker?}
|
||||||
|
IsDockerParam -- 是 --> RunDocker[Docker 容器拉取与启动]
|
||||||
|
IsDockerParam -- 否 --> RunLocal[本地二进制下载与 systemd 服务创建]
|
||||||
|
|
||||||
|
CheckArgs -- 否 (交互模式) --> PromptMethod[提示选择 Local 或 Docker]
|
||||||
|
PromptMethod --> MethodChosen{选择结果}
|
||||||
|
|
||||||
|
MethodChosen -- Docker --> CheckDocker{本地有 Docker 吗?}
|
||||||
|
CheckDocker -- 否 --> PromptDockerInstall[询问是否安装 Docker?]
|
||||||
|
PromptDockerInstall -- 是 --> InstallDocker[在线安装 Docker + 配置国内镜像加速]
|
||||||
|
PromptDockerInstall -- 否 --> ExitScript[取消安装并退出]
|
||||||
|
CheckDocker -- 是 --> PromptServerUrl[提示输入 Server URL & Token]
|
||||||
|
InstallDocker --> PromptServerUrl
|
||||||
|
|
||||||
|
MethodChosen -- Local --> PromptLocalConfig[检测 OpenResty 并提示输入 Server URL & Token]
|
||||||
|
|
||||||
|
PromptServerUrl --> RunDocker
|
||||||
|
PromptLocalConfig --> RunLocal
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 具体修改文件清单 (Proposed Changes)
|
||||||
|
|
||||||
|
### 边缘 Agent 与部署脚本
|
||||||
|
* #### [MODIFY] [install-agent.sh](file:///Users/ryan/DEV/Go/OpenFlare/scripts/install-agent.sh)
|
||||||
|
* 职责:
|
||||||
|
1. 引入交互式选择逻辑和 `Install_Docker` / `configure_accelerator` 函数。
|
||||||
|
2. 新增 `--docker` 和 `--method` 命令行参数支持。
|
||||||
|
3. 支持用户交互输入配置项。
|
||||||
|
4. 增加 Docker 镜像拉取、停止旧容器并启动新容器的安装路径。
|
||||||
|
* #### [MODIFY] [agent.md](file:///Users/ryan/DEV/Go/OpenFlare/docs/deployment/agent.md)
|
||||||
|
* 职责:更新一键安装说明文档,增加交互式模式的说明以及 `--docker` 参数的自动化 Docker 安装说明。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 验证计划 (Verification Plan)
|
||||||
|
|
||||||
|
### 自动化与脚本测试
|
||||||
|
* 在干净的测试环境运行脚本:
|
||||||
|
* `bash scripts/install-agent.sh` (测试交互模式 -> 选用 Local)
|
||||||
|
* `bash scripts/install-agent.sh` (测试交互模式 -> 选用 Docker)
|
||||||
|
* `bash scripts/install-agent.sh --server-url http://127.0.0.1:3000 --discovery-token mytoken` (测试自动 Local 安装)
|
||||||
|
* `bash scripts/install-agent.sh --server-url http://127.0.0.1:3000 --discovery-token mytoken --docker` (测试自动 Docker 安装)
|
||||||
|
|
||||||
|
### 数据面生效验证
|
||||||
|
* 通过 `docker ps` 和 `docker logs openflare-agent` 确认容器成功拉取并启动,环境参数注入正确。
|
||||||
+355
-20
@@ -15,6 +15,252 @@ AGENT_TOKEN=""
|
|||||||
CREATE_SERVICE="true"
|
CREATE_SERVICE="true"
|
||||||
SERVICE_NAME="openflare-agent"
|
SERVICE_NAME="openflare-agent"
|
||||||
OPENRESTY_PATH=""
|
OPENRESTY_PATH=""
|
||||||
|
INSTALL_METHOD=""
|
||||||
|
|
||||||
|
CURRENT_DIR="$(pwd)"
|
||||||
|
LOG_FILE="${CURRENT_DIR}/install.log"
|
||||||
|
|
||||||
|
# Translation text variables
|
||||||
|
TXT_DOCKER_RESTARTED="Docker 已启动/重启并运行中"
|
||||||
|
TXT_LOW_DOCKER_VERSION="Docker 版本较低,建议升级到 20.10 及以上版本"
|
||||||
|
TXT_INSTALL_DOCKER_CONFIRM="未检测到 Docker,是否现在安装?(y/n) [y]: "
|
||||||
|
TXT_DOCKER_INSTALL_ONLINE="开始在线安装 Docker..."
|
||||||
|
TXT_INSTALL_DOCKER_ONLINE="使用 opkg 在线安装 Docker..."
|
||||||
|
TXT_CHOOSE_LOWEST_LATENCY_SOURCE="选择延迟最低的镜像源:"
|
||||||
|
TXT_CHOOSE_LOWEST_LATENCY_DELAY="延迟为:"
|
||||||
|
TXT_TRY_NEXT_LINK="尝试使用链接:"
|
||||||
|
TXT_DOWNLOAD_DOCKER_SCRIPT="下载 Docker 安装脚本..."
|
||||||
|
TXT_DOWNLOAD_DOCKER_SCRIPT_SUCCESS="下载成功:"
|
||||||
|
TXT_SUCCESSFULLY_MESSAGE="开始执行安装..."
|
||||||
|
TXT_DOWNLOAD_FAIELD="下载失败:"
|
||||||
|
TXT_ALL_DOWNLOAD_ATTEMPTS_FAILED="所有 Docker 下载尝试均失败,请手动安装 Docker"
|
||||||
|
TXT_DOCKER_INSTALL_FAIL="Docker 安装失败"
|
||||||
|
TXT_DOCKER_INSTALL_SUCCESS="Docker 安装成功"
|
||||||
|
TXT_CANNOT_SELECT_SOURCE="无法选择合适的镜像源"
|
||||||
|
TXT_REGIONS_OTHER_THAN_CHINA="检测到非中国大陆地区,使用官方源安装 Docker..."
|
||||||
|
TXT_DOCKER_START_NOTICE="正在启动 Docker 服务..."
|
||||||
|
TXT_CANCEL_INSTALL_DOCKER="已取消 Docker 安装"
|
||||||
|
TXT_INVALID_YN_INPUT="无效的输入,请输入 y 或 n"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo -e "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_accelerator() {
|
||||||
|
log "配置 Docker 国内镜像加速源..."
|
||||||
|
local docker_config_folder="/etc/docker"
|
||||||
|
if [[ ! -d "$docker_config_folder" ]]; then
|
||||||
|
mkdir -p "$docker_config_folder"
|
||||||
|
fi
|
||||||
|
cat > /etc/docker/daemon.json <<EOF
|
||||||
|
{
|
||||||
|
"registry-mirrors": [
|
||||||
|
"https://registry.docker-cn.com",
|
||||||
|
"https://docker.mirrors.ustc.edu.cn",
|
||||||
|
"https://hub-mirror.c.163.com",
|
||||||
|
"https://mirror.baidubce.com"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
if command -v systemctl &>/dev/null; then
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl restart docker
|
||||||
|
else
|
||||||
|
service dockerd restart
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function Install_Docker(){
|
||||||
|
if which docker >/dev/null 2>&1; then
|
||||||
|
docker_version=$(docker --version | grep -oE '[0-9]+\.[0-9]+' | head -n 1)
|
||||||
|
major_version=${docker_version%%.*}
|
||||||
|
minor_version=${docker_version##*.}
|
||||||
|
local service_cmd="service dockerd start && service dockerd status"
|
||||||
|
if command -v systemctl &>/dev/null; then
|
||||||
|
service_cmd="systemctl start docker && systemctl status docker"
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
local service_status=$($service_cmd 2>&1)
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ $service_status == *running* ]]; then
|
||||||
|
log "$TXT_DOCKER_RESTARTED"
|
||||||
|
else
|
||||||
|
if [[ $major_version -lt 20 ]]; then
|
||||||
|
log "$TXT_LOW_DOCKER_VERSION"
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
local country_code=$(curl -s --max-time 5 ipinfo.io/country)
|
||||||
|
set -e
|
||||||
|
if [[ "$country_code" == "CN" ]]; then
|
||||||
|
configure_accelerator
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
while true; do
|
||||||
|
read -p "$TXT_INSTALL_DOCKER_CONFIRM" install_docker_choice
|
||||||
|
install_docker_choice=${install_docker_choice:-y}
|
||||||
|
case "$install_docker_choice" in
|
||||||
|
[yY])
|
||||||
|
log "$TXT_DOCKER_INSTALL_ONLINE"
|
||||||
|
|
||||||
|
if command -v opkg &>/dev/null; then
|
||||||
|
log "$TXT_INSTALL_DOCKER_ONLINE"
|
||||||
|
opkg update
|
||||||
|
opkg install luci-i18n-dockerman-zh-cn
|
||||||
|
opkg install zoneinfo-asia
|
||||||
|
service system restart
|
||||||
|
set +e
|
||||||
|
local country_code=$(curl -s --max-time 5 ipinfo.io/country)
|
||||||
|
set -e
|
||||||
|
if [[ "$country_code" == "CN" ]]; then
|
||||||
|
configure_accelerator
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
set +e
|
||||||
|
local country_code=$(curl -s --max-time 5 ipinfo.io/country)
|
||||||
|
set -e
|
||||||
|
if [[ "$country_code" == "CN" ]]; then
|
||||||
|
sources=(
|
||||||
|
"https://mirrors.aliyun.com/docker-ce"
|
||||||
|
"https://mirrors.tencent.com/docker-ce"
|
||||||
|
"https://mirrors.163.com/docker-ce"
|
||||||
|
"https://mirrors.cernet.edu.cn/docker-ce"
|
||||||
|
)
|
||||||
|
|
||||||
|
docker_install_scripts=(
|
||||||
|
"https://get.docker.com"
|
||||||
|
"https://testingcf.jsdelivr.net/gh/docker/docker-install@master/install.sh"
|
||||||
|
"https://cdn.jsdelivr.net/gh/docker/docker-install@master/install.sh"
|
||||||
|
"https://fastly.jsdelivr.net/gh/docker/docker-install@master/install.sh"
|
||||||
|
"https://gcore.jsdelivr.net/gh/docker/docker-install@master/install.sh"
|
||||||
|
"https://raw.githubusercontent.com/docker/docker-install/master/install.sh"
|
||||||
|
)
|
||||||
|
|
||||||
|
get_average_delay() {
|
||||||
|
local source=$1
|
||||||
|
local total_delay=0
|
||||||
|
local iterations=2
|
||||||
|
local timeout=2
|
||||||
|
|
||||||
|
for ((i = 0; i < iterations; i++)); do
|
||||||
|
delay=$(curl -o /dev/null -s -m $timeout -w "%{time_total}\n" "$source")
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
delay=$timeout
|
||||||
|
fi
|
||||||
|
total_delay=$(awk "BEGIN {print $total_delay + $delay}")
|
||||||
|
done
|
||||||
|
|
||||||
|
average_delay=$(awk "BEGIN {print $total_delay / $iterations}")
|
||||||
|
echo "$average_delay"
|
||||||
|
}
|
||||||
|
|
||||||
|
min_delay=99999999
|
||||||
|
selected_source=""
|
||||||
|
|
||||||
|
for source in "${sources[@]}"; do
|
||||||
|
average_delay=$(get_average_delay "$source" &)
|
||||||
|
|
||||||
|
if (( $(awk 'BEGIN { print '"$average_delay"' < '"$min_delay"' }') )); then
|
||||||
|
min_delay=$average_delay
|
||||||
|
selected_source=$source
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
wait
|
||||||
|
|
||||||
|
if [ -n "$selected_source" ]; then
|
||||||
|
log "$TXT_CHOOSE_LOWEST_LATENCY_SOURCE $selected_source,$TXT_CHOOSE_LOWEST_LATENCY_DELAY $min_delay"
|
||||||
|
export DOWNLOAD_URL="$selected_source"
|
||||||
|
|
||||||
|
for alt_source in "${docker_install_scripts[@]}"; do
|
||||||
|
log "$TXT_TRY_NEXT_LINK $alt_source $TXT_DOWNLOAD_DOCKER_SCRIPT"
|
||||||
|
if curl -fsSL --retry 2 --retry-delay 3 --connect-timeout 5 --max-time 10 "$alt_source" -o get-docker.sh; then
|
||||||
|
log "$TXT_DOWNLOAD_DOCKER_SCRIPT_SUCCESS $alt_source $TXT_SUCCESSFULLY_MESSAGE"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
log "$TXT_DOWNLOAD_FAIELD $alt_source $TXT_TRY_NEXT_LINK"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ! -f "get-docker.sh" ]; then
|
||||||
|
log "$TXT_ALL_DOWNLOAD_ATTEMPTS_FAILED"
|
||||||
|
log "bash <(curl -sSL https://linuxmirrors.cn/docker.sh)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sh get-docker.sh 2>&1 | tee -a "${CURRENT_DIR}/install.log"
|
||||||
|
|
||||||
|
docker_config_folder="/etc/docker"
|
||||||
|
if [[ ! -d "$docker_config_folder" ]]; then
|
||||||
|
mkdir -p "$docker_config_folder"
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
docker version >/dev/null 2>&1
|
||||||
|
local docker_ver_res=$?
|
||||||
|
set -e
|
||||||
|
if [[ $docker_ver_res -ne 0 ]]; then
|
||||||
|
log "$TXT_DOCKER_INSTALL_FAIL"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
log "$TXT_DOCKER_INSTALL_SUCCESS"
|
||||||
|
if command -v systemctl &>/dev/null; then
|
||||||
|
systemctl enable docker 2>&1 | tee -a "${LOG_FILE}"
|
||||||
|
fi
|
||||||
|
configure_accelerator
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "$TXT_CANNOT_SELECT_SOURCE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "$TXT_REGIONS_OTHER_THAN_CHINA"
|
||||||
|
export DOWNLOAD_URL="https://download.docker.com"
|
||||||
|
curl -fsSL "https://get.docker.com" -o get-docker.sh
|
||||||
|
sh get-docker.sh 2>&1 | tee -a "${LOG_FILE}"
|
||||||
|
|
||||||
|
log "$TXT_DOCKER_START_NOTICE"
|
||||||
|
if command -v systemctl &>/dev/null; then
|
||||||
|
systemctl enable docker; systemctl daemon-reload; systemctl start docker 2>&1 | tee -a "${LOG_FILE}"
|
||||||
|
else
|
||||||
|
service dockerd start 2>&1 | tee -a "${LOG_FILE}"
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker_config_folder="/etc/docker"
|
||||||
|
if [[ ! -d "$docker_config_folder" ]]; then
|
||||||
|
mkdir -p "$docker_config_folder"
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +e
|
||||||
|
docker version >/dev/null 2>&1
|
||||||
|
local docker_ver_res=$?
|
||||||
|
set -e
|
||||||
|
if [[ $docker_ver_res -ne 0 ]]; then
|
||||||
|
log "$TXT_DOCKER_INSTALL_FAIL"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
log "$TXT_DOCKER_INSTALL_SUCCESS"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN])
|
||||||
|
echo "$TXT_CANCEL_INSTALL_DOCKER"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log "$TXT_INVALID_YN_INPUT"
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
@@ -24,29 +270,35 @@ Usage:
|
|||||||
install-agent.sh [OPTIONS]
|
install-agent.sh [OPTIONS]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--server-url URL Server URL (required)
|
--server-url URL Server URL
|
||||||
--discovery-token TOKEN Discovery token for auto-registration
|
--discovery-token TOKEN Discovery token for auto-registration
|
||||||
--agent-token TOKEN Node-specific agent token
|
--agent-token TOKEN Node-specific agent token
|
||||||
--install-dir DIR Installation directory (default: /opt/openflare-agent)
|
--install-dir DIR Installation directory (default: /opt/openflare-agent)
|
||||||
--openresty-path PATH OpenResty binary path (default: auto-detect from PATH)
|
--openresty-path PATH OpenResty binary path (default: auto-detect from PATH)
|
||||||
--repo REPO GitHub repository (default: Rain-kl/OpenFlare)
|
--repo REPO GitHub repository (default: Rain-kl/OpenFlare)
|
||||||
--no-service Do not create systemd service
|
--no-service Do not create systemd service
|
||||||
|
--docker Install via Docker container
|
||||||
|
--method METHOD Installation method: 'local' or 'docker' (default: local)
|
||||||
-h, --help Show this help message
|
-h, --help Show this help message
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
# Install with discovery token (auto-register)
|
# Interactive installation (prompts for options)
|
||||||
|
install-agent.sh
|
||||||
|
|
||||||
|
# Automated local installation
|
||||||
install-agent.sh --server-url http://10.0.0.1:3000 --discovery-token abc123
|
install-agent.sh --server-url http://10.0.0.1:3000 --discovery-token abc123
|
||||||
|
|
||||||
# Install with node-specific token
|
# Automated Docker installation
|
||||||
install-agent.sh --server-url http://10.0.0.1:3000 --agent-token node-token-xyz
|
install-agent.sh --server-url http://10.0.0.1:3000 --discovery-token abc123 --docker
|
||||||
|
|
||||||
Notes:
|
|
||||||
Reinstall will remove the entire install directory before installing again,
|
|
||||||
including the old agent.json, local state, cached data, and downloaded binary.
|
|
||||||
EOF
|
EOF
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HAS_ARGS="false"
|
||||||
|
if [[ $# -gt 0 ]]; then
|
||||||
|
HAS_ARGS="true"
|
||||||
|
fi
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--server-url) SERVER_URL="$2"; shift 2 ;;
|
--server-url) SERVER_URL="$2"; shift 2 ;;
|
||||||
@@ -56,19 +308,111 @@ while [[ $# -gt 0 ]]; do
|
|||||||
--openresty-path) OPENRESTY_PATH="$2"; shift 2 ;;
|
--openresty-path) OPENRESTY_PATH="$2"; shift 2 ;;
|
||||||
--repo) REPO="$2"; shift 2 ;;
|
--repo) REPO="$2"; shift 2 ;;
|
||||||
--no-service) CREATE_SERVICE="false"; shift ;;
|
--no-service) CREATE_SERVICE="false"; shift ;;
|
||||||
|
--docker) INSTALL_METHOD="docker"; shift ;;
|
||||||
|
--method) INSTALL_METHOD="$2"; shift 2 ;;
|
||||||
-h|--help) usage ;;
|
-h|--help) usage ;;
|
||||||
*) echo "Unknown option: $1"; exit 1 ;;
|
*) echo "Unknown option: $1"; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ -z "$SERVER_URL" ]]; then
|
if [[ "$HAS_ARGS" == "false" ]]; then
|
||||||
|
echo "=================================================="
|
||||||
|
echo "欢迎使用 OpenFlare Agent 安装脚本"
|
||||||
|
echo "Welcome to the OpenFlare Agent Installer"
|
||||||
|
echo "=================================================="
|
||||||
|
echo "请选择安装方式 / Please choose installation method:"
|
||||||
|
echo " 1) Local (本地安装: 下载二进制运行,需要本地有 OpenResty)"
|
||||||
|
echo " 2) Docker (容器安装: 运行内置 OpenResty 的 Agent 容器)"
|
||||||
|
read -p "请输入序号 [1-2] (默认 1): " method_choice
|
||||||
|
method_choice=${method_choice:-1}
|
||||||
|
case "$method_choice" in
|
||||||
|
2) INSTALL_METHOD="docker" ;;
|
||||||
|
*) INSTALL_METHOD="local" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [[ "$INSTALL_METHOD" == "docker" ]]; then
|
||||||
|
Install_Docker
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prompt for Server URL
|
||||||
|
while [[ -z "$SERVER_URL" ]]; do
|
||||||
|
read -p "请输入 OpenFlare Server 地址 (例如 http://127.0.0.1:3000): " SERVER_URL
|
||||||
|
done
|
||||||
|
|
||||||
|
# Prompt for Token
|
||||||
|
while [[ -z "$DISCOVERY_TOKEN" && -z "$AGENT_TOKEN" ]]; do
|
||||||
|
echo "请选择认证 Token 类型 / Please choose token type:"
|
||||||
|
echo " 1) Discovery Token (自动注册凭证 - 适合新节点上线)"
|
||||||
|
echo " 2) Agent Token (专属接入凭证 - 适合预创建节点)"
|
||||||
|
read -p "请输入序号 [1-2] (默认 1): " token_type_choice
|
||||||
|
token_type_choice=${token_type_choice:-1}
|
||||||
|
if [[ "$token_type_choice" == "2" ]]; then
|
||||||
|
read -p "请输入 Agent Token: " AGENT_TOKEN
|
||||||
|
else
|
||||||
|
read -p "请输入 Discovery Token: " DISCOVERY_TOKEN
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
# Non-interactive mode validation
|
||||||
|
if [[ -z "$INSTALL_METHOD" ]]; then
|
||||||
|
INSTALL_METHOD="local"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$SERVER_URL" ]]; then
|
||||||
echo "Error: --server-url is required"
|
echo "Error: --server-url is required"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "$DISCOVERY_TOKEN" && -z "$AGENT_TOKEN" ]]; then
|
if [[ -z "$DISCOVERY_TOKEN" && -z "$AGENT_TOKEN" ]]; then
|
||||||
echo "Error: either --discovery-token or --agent-token is required"
|
echo "Error: either --discovery-token or --agent-token is required"
|
||||||
exit 1
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run Docker container installation if Docker method selected
|
||||||
|
if [[ "$INSTALL_METHOD" == "docker" ]]; then
|
||||||
|
echo "拉取最新的 OpenFlare Agent 镜像..."
|
||||||
|
docker pull ghcr.io/rain-kl/openflare-agent:latest
|
||||||
|
|
||||||
|
echo "停止并移除旧的 openflare-agent 容器 (如果存在)..."
|
||||||
|
docker rm -f openflare-agent 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "启动 openflare-agent 容器..."
|
||||||
|
if [[ -n "$AGENT_TOKEN" ]]; then
|
||||||
|
docker run -d --name openflare-agent --restart unless-stopped \
|
||||||
|
-p 80:80 -p 443:443/tcp -p 443:443/udp \
|
||||||
|
-e OPENFLARE_SERVER_URL="${SERVER_URL}" \
|
||||||
|
-e OPENFLARE_AGENT_TOKEN="${AGENT_TOKEN}" \
|
||||||
|
ghcr.io/rain-kl/openflare-agent:latest
|
||||||
|
else
|
||||||
|
docker run -d --name openflare-agent --restart unless-stopped \
|
||||||
|
-p 80:80 -p 443:443/tcp -p 443:443/udp \
|
||||||
|
-e OPENFLARE_SERVER_URL="${SERVER_URL}" \
|
||||||
|
-e OPENFLARE_DISCOVERY_TOKEN="${DISCOVERY_TOKEN}" \
|
||||||
|
ghcr.io/rain-kl/openflare-agent:latest
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "OpenFlare Agent (Docker) 安装成功!"
|
||||||
|
echo "您可以执行以下命令查看运行日志:"
|
||||||
|
echo " docker logs -f openflare-agent"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Local installation starts below
|
||||||
|
if [[ -z "$OPENRESTY_PATH" ]]; then
|
||||||
|
if command -v openresty >/dev/null 2>&1; then
|
||||||
|
OPENRESTY_PATH="$(command -v openresty)"
|
||||||
|
elif [[ "$HAS_ARGS" == "false" ]]; then
|
||||||
|
read -p "未在 PATH 中检测到 openresty,请输入 OpenResty 二进制路径: " OPENRESTY_PATH
|
||||||
|
if [[ -z "$OPENRESTY_PATH" ]]; then
|
||||||
|
echo "Error: OpenResty binary path is required for local installation."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Error: openresty was not found in PATH. Install OpenResty first or pass --openresty-path."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Detect platform
|
# Detect platform
|
||||||
@@ -85,15 +429,6 @@ if [[ "$OS" != "linux" && "$OS" != "darwin" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "$OPENRESTY_PATH" ]]; then
|
|
||||||
if command -v openresty >/dev/null 2>&1; then
|
|
||||||
OPENRESTY_PATH="$(command -v openresty)"
|
|
||||||
else
|
|
||||||
echo "Error: openresty was not found in PATH. Install OpenResty first or pass --openresty-path."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -x "$OPENRESTY_PATH" ]]; then
|
if [[ ! -x "$OPENRESTY_PATH" ]]; then
|
||||||
echo "Error: OpenResty binary is not executable: ${OPENRESTY_PATH}"
|
echo "Error: OpenResty binary is not executable: ${OPENRESTY_PATH}"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -1,192 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
INSTALL_DIR="/opt/openflare-agent"
|
|
||||||
SERVICE_NAME="openflare-agent"
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
cat <<EOF
|
|
||||||
OpenFlare Agent Uninstaller
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
uninstall-agent.sh [OPTIONS]
|
|
||||||
|
|
||||||
Options:
|
|
||||||
--install-dir DIR Installation directory (default: /opt/openflare-agent)
|
|
||||||
--service-name NAME systemd service name (default: openflare-agent)
|
|
||||||
-h, --help Show this help message
|
|
||||||
|
|
||||||
Behavior:
|
|
||||||
1. Stop the agent service/process and remove the entire installation directory
|
|
||||||
2. Remove the systemd service definition when present
|
|
||||||
3. Check the saved agent config to identify the OpenResty mode
|
|
||||||
4. If Docker mode was used, remove the OpenResty container and try to remove its image
|
|
||||||
5. If local openresty_path mode was used, do not modify the local OpenResty install
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
uninstall-agent.sh
|
|
||||||
uninstall-agent.sh --install-dir /srv/openflare-agent
|
|
||||||
EOF
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
case "$1" in
|
|
||||||
--install-dir) INSTALL_DIR="$2"; shift 2 ;;
|
|
||||||
--service-name) SERVICE_NAME="$2"; shift 2 ;;
|
|
||||||
-h|--help) usage ;;
|
|
||||||
*) echo "Unknown option: $1"; exit 1 ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ -z "$INSTALL_DIR" || "$INSTALL_DIR" == "/" || "$INSTALL_DIR" == "." ]]; then
|
|
||||||
echo "Refusing to remove unsafe install directory: '${INSTALL_DIR}'"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
json_get_string() {
|
|
||||||
local file="$1"
|
|
||||||
local key="$2"
|
|
||||||
local match
|
|
||||||
|
|
||||||
match=$(grep -o "\"${key}\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" "$file" 2>/dev/null | head -n 1 || true)
|
|
||||||
if [[ -z "$match" ]]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf '%s\n' "$match" | sed -E 's/.*:[[:space:]]*"([^"]*)"/\1/'
|
|
||||||
}
|
|
||||||
|
|
||||||
AGENT_BINARY="${INSTALL_DIR}/openflare-agent"
|
|
||||||
CONFIG_FILE="${INSTALL_DIR}/agent.json"
|
|
||||||
SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service"
|
|
||||||
|
|
||||||
OPENRESTY_PATH=""
|
|
||||||
OPENRESTY_CONTAINER_NAME="openflare-openresty"
|
|
||||||
OPENRESTY_DOCKER_IMAGE="openresty/openresty:alpine"
|
|
||||||
DOCKER_BINARY="docker"
|
|
||||||
OPENRESTY_MODE="unknown"
|
|
||||||
|
|
||||||
if [[ -f "$CONFIG_FILE" ]]; then
|
|
||||||
OPENRESTY_PATH="$(json_get_string "$CONFIG_FILE" "openresty_path")"
|
|
||||||
OPENRESTY_CONTAINER_NAME="$(json_get_string "$CONFIG_FILE" "openresty_container_name")"
|
|
||||||
OPENRESTY_DOCKER_IMAGE="$(json_get_string "$CONFIG_FILE" "openresty_docker_image")"
|
|
||||||
DOCKER_BINARY="$(json_get_string "$CONFIG_FILE" "docker_binary")"
|
|
||||||
|
|
||||||
if [[ -z "$OPENRESTY_CONTAINER_NAME" ]]; then
|
|
||||||
OPENRESTY_CONTAINER_NAME="openflare-openresty"
|
|
||||||
fi
|
|
||||||
if [[ -z "$OPENRESTY_DOCKER_IMAGE" ]]; then
|
|
||||||
OPENRESTY_DOCKER_IMAGE="openresty/openresty:alpine"
|
|
||||||
fi
|
|
||||||
if [[ -z "$DOCKER_BINARY" ]]; then
|
|
||||||
DOCKER_BINARY="docker"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n "$OPENRESTY_PATH" ]]; then
|
|
||||||
OPENRESTY_MODE="local"
|
|
||||||
else
|
|
||||||
OPENRESTY_MODE="docker"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
SYSTEMCTL_AVAILABLE="false"
|
|
||||||
if command -v systemctl >/dev/null 2>&1; then
|
|
||||||
SYSTEMCTL_AVAILABLE="true"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Uninstalling OpenFlare Agent from ${INSTALL_DIR}..."
|
|
||||||
|
|
||||||
if [[ "$SYSTEMCTL_AVAILABLE" == "true" ]]; then
|
|
||||||
if systemctl is-active --quiet "$SERVICE_NAME"; then
|
|
||||||
echo "Stopping service: ${SERVICE_NAME}"
|
|
||||||
systemctl stop "$SERVICE_NAME"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if systemctl is-enabled --quiet "$SERVICE_NAME" >/dev/null 2>&1; then
|
|
||||||
echo "Disabling service: ${SERVICE_NAME}"
|
|
||||||
systemctl disable "$SERVICE_NAME" >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if command -v pgrep >/dev/null 2>&1; then
|
|
||||||
mapfile -t agent_pids < <(pgrep -f "$AGENT_BINARY" || true)
|
|
||||||
if (( ${#agent_pids[@]} > 0 )); then
|
|
||||||
echo "Stopping agent process: ${agent_pids[*]}"
|
|
||||||
kill "${agent_pids[@]}" || true
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
mapfile -t remaining_agent_pids < <(pgrep -f "$AGENT_BINARY" || true)
|
|
||||||
if (( ${#remaining_agent_pids[@]} > 0 )); then
|
|
||||||
echo "Force stopping remaining agent process: ${remaining_agent_pids[*]}"
|
|
||||||
kill -9 "${remaining_agent_pids[@]}" || true
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -f "$SERVICE_FILE" ]]; then
|
|
||||||
echo "Removing service file: ${SERVICE_FILE}"
|
|
||||||
rm -f "$SERVICE_FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$SYSTEMCTL_AVAILABLE" == "true" ]]; then
|
|
||||||
systemctl daemon-reload || true
|
|
||||||
systemctl reset-failed "$SERVICE_NAME" >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -d "$INSTALL_DIR" ]]; then
|
|
||||||
echo "Removing installation directory: ${INSTALL_DIR}"
|
|
||||||
rm -rf "$INSTALL_DIR"
|
|
||||||
else
|
|
||||||
echo "Installation directory not found, skipping: ${INSTALL_DIR}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Agent uninstall complete."
|
|
||||||
echo ""
|
|
||||||
echo "Checking OpenResty installation mode..."
|
|
||||||
|
|
||||||
if [[ "$OPENRESTY_MODE" == "docker" ]]; then
|
|
||||||
echo "Detected Docker OpenResty mode."
|
|
||||||
|
|
||||||
if ! command -v "$DOCKER_BINARY" >/dev/null 2>&1; then
|
|
||||||
echo "Docker binary '${DOCKER_BINARY}' was not found."
|
|
||||||
echo "Please remove container '${OPENRESTY_CONTAINER_NAME}' and image '${OPENRESTY_DOCKER_IMAGE}' manually."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if "$DOCKER_BINARY" inspect "$OPENRESTY_CONTAINER_NAME" >/dev/null 2>&1; then
|
|
||||||
if [[ -z "$OPENRESTY_DOCKER_IMAGE" ]]; then
|
|
||||||
OPENRESTY_DOCKER_IMAGE="$("$DOCKER_BINARY" inspect -f '{{.Config.Image}}' "$OPENRESTY_CONTAINER_NAME" 2>/dev/null || true)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Removing Docker container: ${OPENRESTY_CONTAINER_NAME}"
|
|
||||||
"$DOCKER_BINARY" rm -f "$OPENRESTY_CONTAINER_NAME"
|
|
||||||
else
|
|
||||||
echo "Docker container not found, skipping: ${OPENRESTY_CONTAINER_NAME}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n "$OPENRESTY_DOCKER_IMAGE" ]] && "$DOCKER_BINARY" image inspect "$OPENRESTY_DOCKER_IMAGE" >/dev/null 2>&1; then
|
|
||||||
other_container_ids="$("$DOCKER_BINARY" ps -a --filter "ancestor=${OPENRESTY_DOCKER_IMAGE}" --format '{{.ID}}' 2>/dev/null || true)"
|
|
||||||
if [[ -z "$other_container_ids" ]]; then
|
|
||||||
echo "Removing Docker image: ${OPENRESTY_DOCKER_IMAGE}"
|
|
||||||
if ! "$DOCKER_BINARY" image rm "$OPENRESTY_DOCKER_IMAGE"; then
|
|
||||||
echo "Image removal skipped because Docker reported it is still in use."
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Docker image is still used by other containers, skipping image removal: ${OPENRESTY_DOCKER_IMAGE}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Docker OpenResty cleanup complete."
|
|
||||||
elif [[ "$OPENRESTY_MODE" == "local" ]]; then
|
|
||||||
echo "Detected local OpenResty mode via openresty_path:"
|
|
||||||
echo " ${OPENRESTY_PATH}"
|
|
||||||
echo "Agent has been removed, but the local OpenResty installation was not modified."
|
|
||||||
echo "Please uninstall the local OpenResty manually if you no longer need it."
|
|
||||||
else
|
|
||||||
echo "OpenResty mode could not be determined because ${CONFIG_FILE} was not found before uninstall."
|
|
||||||
echo "If you were using Docker OpenResty, please remove its container and image manually if needed."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "OpenFlare Agent uninstall finished."
|
|
||||||
@@ -3,6 +3,7 @@ set -euo pipefail
|
|||||||
|
|
||||||
INSTALL_DIR="/opt/openflare-agent"
|
INSTALL_DIR="/opt/openflare-agent"
|
||||||
SERVICE_NAME="openflare-agent"
|
SERVICE_NAME="openflare-agent"
|
||||||
|
INSTALL_METHOD=""
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
@@ -14,29 +15,102 @@ Usage:
|
|||||||
Options:
|
Options:
|
||||||
--install-dir DIR Installation directory (default: /opt/openflare-agent)
|
--install-dir DIR Installation directory (default: /opt/openflare-agent)
|
||||||
--service-name NAME systemd service name (default: openflare-agent)
|
--service-name NAME systemd service name (default: openflare-agent)
|
||||||
|
--docker Uninstall Docker container agent
|
||||||
|
--method METHOD Uninstall method: 'local' or 'docker' (default: local)
|
||||||
-h, --help Show this help message
|
-h, --help Show this help message
|
||||||
|
|
||||||
Behavior:
|
Behavior:
|
||||||
1. Stop the agent service/process and remove the entire installation directory
|
1. Stop the agent service/process and remove the entire installation directory
|
||||||
2. Remove the systemd service definition when present
|
2. Remove the systemd service definition when present
|
||||||
3. Leave the local OpenResty installation untouched
|
3. Uninstall Docker container when --docker is specified
|
||||||
|
4. Leave the local OpenResty installation untouched
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
# Interactive uninstall (prompts for options)
|
||||||
uninstall-agent.sh
|
uninstall-agent.sh
|
||||||
uninstall-agent.sh --install-dir /srv/openflare-agent
|
|
||||||
|
# Automated local uninstall
|
||||||
|
uninstall-agent.sh --install-dir /opt/openflare-agent
|
||||||
|
|
||||||
|
# Automated Docker uninstall
|
||||||
|
uninstall-agent.sh --docker
|
||||||
EOF
|
EOF
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HAS_ARGS="false"
|
||||||
|
if [[ $# -gt 0 ]]; then
|
||||||
|
HAS_ARGS="true"
|
||||||
|
fi
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--install-dir) INSTALL_DIR="$2"; shift 2 ;;
|
--install-dir) INSTALL_DIR="$2"; shift 2 ;;
|
||||||
--service-name) SERVICE_NAME="$2"; shift 2 ;;
|
--service-name) SERVICE_NAME="$2"; shift 2 ;;
|
||||||
|
--docker) INSTALL_METHOD="docker"; shift ;;
|
||||||
|
--method) INSTALL_METHOD="$2"; shift 2 ;;
|
||||||
-h|--help) usage ;;
|
-h|--help) usage ;;
|
||||||
*) echo "Unknown option: $1"; exit 1 ;;
|
*) echo "Unknown option: $1"; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [[ "$HAS_ARGS" == "false" ]]; then
|
||||||
|
echo "=================================================="
|
||||||
|
echo "欢迎使用 OpenFlare Agent 卸载脚本"
|
||||||
|
echo "Welcome to the OpenFlare Agent Uninstaller"
|
||||||
|
echo "=================================================="
|
||||||
|
echo "请选择卸载方式 / Please choose uninstall method:"
|
||||||
|
echo " 1) Local (本地卸载: 停止服务并删除二进制及配置)"
|
||||||
|
echo " 2) Docker (容器卸载: 停止并删除 Docker 容器)"
|
||||||
|
read -p "请输入序号 [1-2] (默认 1): " method_choice
|
||||||
|
method_choice=${method_choice:-1}
|
||||||
|
case "$method_choice" in
|
||||||
|
2) INSTALL_METHOD="docker" ;;
|
||||||
|
*) INSTALL_METHOD="local" ;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
if [[ -z "$INSTALL_METHOD" ]]; then
|
||||||
|
INSTALL_METHOD="local"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$INSTALL_METHOD" == "docker" ]]; then
|
||||||
|
echo "正在卸载 OpenFlare Agent (Docker)..."
|
||||||
|
|
||||||
|
# Check if container exists
|
||||||
|
if command -v docker >/dev/null 2>&1; then
|
||||||
|
if docker ps -a --format '{{.Names}}' | grep -Eq "^openflare-agent$"; then
|
||||||
|
echo "停止并移除 openflare-agent 容器..."
|
||||||
|
docker stop openflare-agent || true
|
||||||
|
docker rm -f openflare-agent || true
|
||||||
|
echo "已成功移除 openflare-agent 容器。"
|
||||||
|
else
|
||||||
|
echo "未检测到 openflare-agent 容器。"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# In interactive mode, ask if user wants to remove docker image
|
||||||
|
if [[ "$HAS_ARGS" == "false" ]]; then
|
||||||
|
read -p "是否删除 OpenFlare Agent 镜像 (ghcr.io/rain-kl/openflare-agent:latest)? (y/n) [n]: " remove_image_choice
|
||||||
|
remove_image_choice=${remove_image_choice:-n}
|
||||||
|
case "$remove_image_choice" in
|
||||||
|
[yY])
|
||||||
|
echo "正在删除 Docker 镜像..."
|
||||||
|
docker rmi ghcr.io/rain-kl/openflare-agent:latest || true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "保留 Docker 镜像。"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Error: 未检测到 Docker 运行环境,无法进行 Docker 方式的卸载。"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "OpenFlare Agent (Docker) 卸载完成。"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -z "$INSTALL_DIR" || "$INSTALL_DIR" == "/" || "$INSTALL_DIR" == "." ]]; then
|
if [[ -z "$INSTALL_DIR" || "$INSTALL_DIR" == "/" || "$INSTALL_DIR" == "." ]]; then
|
||||||
echo "Refusing to remove unsafe install directory: '${INSTALL_DIR}'"
|
echo "Refusing to remove unsafe install directory: '${INSTALL_DIR}'"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
Reference in New Issue
Block a user