功能: 添加LXD API服务器一键安装脚本

This commit is contained in:
勿忘心安
2025-11-16 19:08:11 +00:00
parent db5f60b949
commit 11167fcdec

888
install.sh Normal file
View File

@@ -0,0 +1,888 @@
#!/bin/bash
cd /root >/dev/null 2>&1
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
REGEX=("debian|astra" "ubuntu")
RELEASE=("Debian" "Ubuntu")
CMD=("$(grep -i pretty_name /etc/os-release 2>/dev/null | cut -d \" -f2)" "$(lsb_release -sd 2>/dev/null)")
SYS="${CMD[0]}"
[[ -n $SYS ]] || exit 1
for ((int = 0; int < ${#REGEX[@]}; int++)); do
if [[ $(echo "$SYS" | tr '[:upper:]' '[:lower:]') =~ ${REGEX[int]} ]]; then
SYSTEM="${RELEASE[int]}"
[[ -n $SYSTEM ]] && break
fi
done
if [[ "$SYSTEM" != "Debian" && "$SYSTEM" != "Ubuntu" ]]; then
echo -e "${RED}[ERR]${NC} 此脚本仅支持 Debian 和 Ubuntu 系统"
exit 1
fi
if [ ! -d "/usr/local/bin" ]; then
mkdir -p /usr/local/bin
fi
log() { echo -e "$1"; }
ok() { log "${GREEN}[OK]${NC} $1"; }
info() { log "${BLUE}[INFO]${NC} $1"; }
warn() { log "${YELLOW}[WARN]${NC} $1"; }
err() { log "${RED}[ERR]${NC} $1"; exit 1; }
print_step() {
local step=$1
local total=$2
local title=$3
echo
echo "========================================"
echo " 步骤 $step/$total: $title"
echo "========================================"
echo
}
reading() { read -rp "$(echo -e "${GREEN}$1${NC}")" "$2"; }
sed_compatible() {
if echo "test" | sed -E 's/test/ok/' >/dev/null 2>&1; then
sed -E "$@"
else
sed -r "$@"
fi
}
service_manager() {
local action=$1
local service_name=$2
case "$action" in
enable)
systemctl enable "$service_name" 2>/dev/null
;;
disable)
systemctl disable "$service_name" 2>/dev/null
;;
start)
systemctl start "$service_name" 2>/dev/null
;;
stop)
systemctl stop "$service_name" 2>/dev/null
;;
restart)
systemctl restart "$service_name" 2>/dev/null
;;
daemon-reload)
systemctl daemon-reload 2>/dev/null
;;
is-active)
systemctl is-active --quiet "$service_name" 2>/dev/null
return $?
;;
esac
return 0
}
set_locale() {
utf8_locale=$(locale -a 2>/dev/null | grep -i -m 1 -E "utf8|UTF-8")
export DEBIAN_FRONTEND=noninteractive
if [[ -z "$utf8_locale" ]]; then
warn "未找到 UTF-8 语言环境"
else
export LC_ALL="$utf8_locale"
export LANG="$utf8_locale"
export LANGUAGE="$utf8_locale"
ok "语言环境设置为 $utf8_locale"
fi
}
install_package() {
package_name=$1
if dpkg -l 2>/dev/null | grep -q "^ii.*$package_name"; then
ok "$package_name 已安装"
else
apt-get install -y $package_name >/dev/null 2>&1
if [ $? -ne 0 ]; then
apt-get install -y $package_name --fix-missing >/dev/null 2>&1
fi
if dpkg -l 2>/dev/null | grep -q "^ii.*$package_name"; then
ok "$package_name 已安装"
else
warn "$package_name 安装失败"
fi
fi
}
get_available_space() {
local available_space
available_space=$(df -BG / | awk 'NR==2 {gsub("G","",$4); print $4}')
echo "$available_space"
}
install_base_packages() {
info "更新软件包列表..."
apt-get update >/dev/null 2>&1
apt-get autoremove -y >/dev/null 2>&1
install_package wget
install_package curl
install_package sudo
install_package unzip
install_package lxcfs
install_package iptables-persistent
install_package nginx
if systemctl is-active --quiet lxcfs; then
ok "lxcfs 服务已运行"
else
service_manager start lxcfs
service_manager enable lxcfs
ok "lxcfs 服务已启动并设置为自动启动"
fi
if systemctl is-active --quiet nginx; then
ok "nginx 服务已运行"
else
service_manager start nginx
service_manager enable nginx
ok "nginx 服务已启动并设置为自动启动"
fi
}
install_lxd() {
lxd_snap=$(dpkg -l | awk '/^[hi]i/{print $2}' | grep -ow snap)
lxd_snapd=$(dpkg -l | awk '/^[hi]i/{print $2}' | grep -ow snapd)
if [[ "$lxd_snap" =~ ^snap.* ]] && [[ "$lxd_snapd" =~ ^snapd.* ]]; then
ok "snap 已安装"
else
info "开始安装 snap..."
apt-get update >/dev/null 2>&1
install_package snapd
fi
snap_core=$(snap list core 2>/dev/null)
snap_lxd=$(snap list lxd 2>/dev/null)
if [[ "$snap_core" =~ core.* ]] && [[ "$snap_lxd" =~ lxd.* ]]; then
ok "LXD 已安装"
lxd_lxc_detect=$(lxc list 2>/dev/null)
if [[ "$lxd_lxc_detect" =~ "snap-update-ns failed with code1".* ]]; then
service_manager restart apparmor
snap restart lxd
else
ok "环境检测无问题"
fi
else
info "开始安装 LXD..."
snap install lxd --channel=latest/stable 2>/dev/null
if [[ $? -ne 0 ]]; then
snap remove lxd 2>/dev/null
snap install core 2>/dev/null
snap install lxd --channel=latest/stable 2>/dev/null
fi
! lxc -h >/dev/null 2>&1 && echo 'alias lxc="/snap/bin/lxc"' >>/root/.bashrc && source /root/.bashrc
export PATH=$PATH:/snap/bin
! lxc -h >/dev/null 2>&1 && err 'lxc 路径有问题,请检查修复'
ok "LXD 安装完成"
fi
}
configure_resources() {
if [ "${noninteractive:-false}" = true ]; then
available_space=$(get_available_space)
disk_nums=$((available_space - 1))
storage_path=""
else
while true; do
reading "是否需要指定存储池的自定义路径?(y/n) [n]" use_custom_path
use_custom_path=${use_custom_path:-n}
if [[ "$use_custom_path" =~ ^[yYnN]$ ]]; then
break
else
warn "请输入 y 或 n"
fi
done
if [[ "$use_custom_path" =~ ^[yY]$ ]]; then
while true; do
reading "请输入自定义存储路径,例如 /data/lxd-storage" storage_path
if [[ -n "$storage_path" && "$storage_path" =~ ^/.+ ]]; then
if [ ! -d "$storage_path" ]; then
mkdir -p "$storage_path" 2>/dev/null
if [ $? -eq 0 ]; then
ok "已创建目录:$storage_path"
break
else
warn "创建目录失败,请检查权限或尝试其他路径"
fi
else
break
fi
else
warn "请输入以 / 开头的有效绝对路径"
fi
done
else
storage_path=""
fi
while true; do
reading "宿主机需要开设多大的存储池?单位 GB需要 10G 则输入 10" disk_nums
if [[ "$disk_nums" =~ ^[1-9][0-9]*$ ]]; then
break
else
warn "输入无效,请输入一个正整数"
fi
done
fi
}
get_available_space() {
local available_space
available_space=$(df -BG / | awk 'NR==2 {gsub("G","",$4); print $4}')
echo "$available_space"
}
create_sparse_file() {
local file_path="$1"
local size_gb="$2"
if dd if=/dev/zero of="$file_path" bs=1G count=0 seek="${size_gb}" 2>/dev/null; then
ok "使用 dd 创建稀疏文件成功: $file_path ${size_gb}GB"
return 0
else
warn "dd 创建失败,尝试使用 truncate..."
if command -v truncate >/dev/null 2>&1; then
if truncate -s "${size_gb}G" "$file_path" 2>/dev/null; then
ok "使用 truncate 创建稀疏文件成功: $file_path ${size_gb}GB"
return 0
else
err "truncate 创建失败"
return 1
fi
else
err "truncate 命令不可用,无法创建稀疏文件"
return 1
fi
fi
}
create_storage_pool_with_custom_path() {
local backend="$1"
local storage_path="$2"
local disk_nums="$3"
local loop_file temp status
mkdir -p "$storage_path"
loop_file="$storage_path/lvm_pool.img"
ok "创建 LVM 存储池..."
if [ -f "$loop_file" ]; then
warn "检测到旧的循环文件,正在清理..."
vgremove -f lxd_vg 2>/dev/null || true
losetup -d $(losetup -j "$loop_file" | cut -d: -f1) 2>/dev/null || true
rm -f "$loop_file"
fi
ok "创建稀疏文件:$loop_file ${disk_nums}GB..."
if ! create_sparse_file "$loop_file" "$disk_nums"; then
return 1
fi
ok "设置循环设备..."
loop_dev=$(losetup -f)
losetup "$loop_dev" "$loop_file"
ok "创建 LVM 物理卷和卷组..."
pvcreate "$loop_dev" >/dev/null 2>&1
vgcreate lxd_vg "$loop_dev" >/dev/null 2>&1
echo "$loop_file" > "$storage_path/lvm_loop_file.txt"
temp=$(/snap/bin/lxc storage create default lvm source=lxd_vg 2>&1)
status=$?
echo "$temp"
return $status
}
execute_storage_init() {
local backend="$1"
local temp
local status
if [ -n "$storage_path" ]; then
if create_storage_pool_with_custom_path "$backend" "$storage_path" "$disk_nums"; then
ok "LVM 存储池创建成功"
/snap/bin/lxd init --auto >/dev/null 2>&1 || true
temp="Storage pool created successfully"
status=0
else
temp="Failed to create LVM storage pool"
status=1
fi
else
temp=$(/snap/bin/lxd init --storage-backend "$backend" --storage-create-loop "$disk_nums" --storage-pool default --auto 2>&1)
status=$?
fi
echo "$temp"
return $status
}
init_storage_backend() {
local backend="lvm"
ok "使用 lvm 类型,存储池大小为 $disk_nums GB"
local need_reboot=false
if ! command -v lvm >/dev/null; then
warn "正在安装 lvm2..."
install_package lvm2
modprobe dm-mod || true
ok "LVM 模块加载。如果失败请重启系统后再次执行脚本"
echo "lvm" >/usr/local/bin/lxd_reboot
need_reboot=true
fi
if ! grep -q dm-mod /proc/modules; then
modprobe dm-mod || true
fi
if [ "$need_reboot" = true ]; then
exit 1
fi
local temp
temp=$(execute_storage_init "$backend")
local status=$?
info "初始化存储:"
echo "$temp"
if echo "$temp" | grep -q "lxd.migrate" && [ $status -ne 0 ]; then
/snap/bin/lxd.migrate
temp=$(execute_storage_init "$backend")
status=$?
echo "$temp"
fi
if [ $status -eq 0 ]; then
ok "使用 lvm 初始化成功"
echo "lvm" >/usr/local/bin/lxd_storage_type
return 0
else
err "使用 lvm 初始化失败"
return 1
fi
}
setup_storage() {
if [ -f "/usr/local/bin/lxd_reboot" ]; then
ok "检测到系统重启,尝试继续使用 lvm"
rm -f /usr/local/bin/lxd_reboot
modprobe dm-mod || true
if init_storage_backend "lvm"; then
return 0
fi
fi
init_storage_backend "lvm"
}
download_and_import_image() {
local image_name="$1"
local arch="$2"
local base_url="$3"
local image_url="${base_url}/${image_name}-${arch}.tar.gz"
info "下载: ${image_name}-${arch}.tar.gz"
local temp_file=$(mktemp)
if wget -q --show-progress -O "$temp_file" "$image_url" 2>&1; then
info "导入到 LXD..."
if lxc image import "$temp_file" --alias "$image_name" 2>/dev/null; then
ok "成功导入: $image_name"
else
warn "导入失败: $image_name"
fi
rm -f "$temp_file"
else
warn "下载失败: ${image_name}"
rm -f "$temp_file"
fi
}
import_container_images() {
info "检测系统架构..."
sys_arch=$(uname -m)
case $sys_arch in
x86_64)
arch="amd64"
ok "检测到架构: x86_64"
;;
aarch64|arm64)
arch="arm64"
ok "检测到架构: $sys_arch"
;;
*)
err "不支持的架构: $sys_arch,仅支持 amd64 和 arm64"
;;
esac
IMAGES_BASE_URL="https://github.com/xkatld/zjmf-lxd-server/releases/download/images"
declare -A IMAGE_MAP
IMAGE_MAP=(
[1]="alma8" [2]="alma9" [3]="alma10"
[4]="alpine319" [5]="alpine320" [6]="alpine321" [7]="alpine322" [8]="alpineEdge"
[9]="amazon2023"
[10]="centos9" [11]="centos10"
[12]="debian11" [13]="debian12" [14]="debian13"
[15]="fedora41" [16]="fedora42"
[17]="oracle8" [18]="oracle9"
[19]="rocky8" [20]="rocky9" [21]="rocky10"
[22]="suse155" [23]="suse156" [24]="suseTumbleweed"
[25]="ubuntu2204" [26]="ubuntu2404" [27]="ubuntu2410"
)
echo
echo "============================================================================================================"
echo " 1) alma8 2) alma9 3) alma10 4) alpine319 5) alpine320 "
echo " 6) alpine321 7) alpine322 8) alpineEdge 9) amazon2023 10) centos9 "
echo "11) centos10 12) debian11 13) debian12 14) debian13 15) fedora41 "
echo "16) fedora42 17) oracle8 18) oracle9 19) rocky8 20) rocky9 "
echo "21) rocky10 22) suse155 23) suse156 24) suseTumbleweed "
echo "25) ubuntu2204 26) ubuntu2404 27) ubuntu2410 "
echo "============================================================================================================"
echo
reading "请输入镜像编号,多个用逗号分隔如 1,2,3 或输入 all 全部导入 [默认: 2,5,13,26]" image_choices
image_choices=${image_choices:-"2,5,13,26"}
if [[ "$image_choices" == "all" ]]; then
selected_images=(${IMAGE_MAP[@]})
else
IFS=',' read -ra choices <<< "$image_choices"
selected_images=()
for choice in "${choices[@]}"; do
choice=$(echo "$choice" | xargs)
if [[ -n "${IMAGE_MAP[$choice]}" ]]; then
selected_images+=("${IMAGE_MAP[$choice]}")
fi
done
fi
if [[ ${#selected_images[@]} -eq 0 ]]; then
warn "未选择任何镜像"
return
fi
echo
ok "已选择 ${#selected_images[@]} 个镜像"
echo
current=0
for img in "${selected_images[@]}"; do
((current++))
echo "[$current/${#selected_images[@]}]"
download_and_import_image "$img" "$arch" "$IMAGES_BASE_URL"
echo
done
}
deploy_lxdapi() {
info "检测系统架构..."
sys_arch=$(uname -m)
case $sys_arch in
x86_64)
arch="amd64"
ok "检测到架构: x86_64"
;;
aarch64|arm64)
arch="arm64"
ok "检测到架构: $sys_arch"
;;
*)
err "不支持的架构: $sys_arch"
;;
esac
info "获取最新版本..."
latest_tag=$(curl -s https://api.github.com/repos/xkatld/lxdapi-web-server/releases/latest | grep '"tag_name"' | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p')
if [ -z "$latest_tag" ]; then
err "无法获取最新版本信息"
fi
ok "最新版本: $latest_tag"
download_url="https://github.com/xkatld/lxdapi-web-server/releases/download/${latest_tag}/lxdapi-linux-${arch}.tar.gz"
info "下载 lxdapi..."
info "下载地址: $download_url"
temp_file=$(mktemp)
if wget -q --show-progress -O "$temp_file" "$download_url" 2>&1; then
ok "下载完成"
else
rm -f "$temp_file"
err "下载失败"
fi
info "解压到 /opt/lxdapi..."
mkdir -p /opt/lxdapi
tar -xzf "$temp_file" -C /opt/lxdapi --strip-components=1
rm -f "$temp_file"
}
configure_lxdapi() {
info "配置 lxdapi..."
config_file="/opt/lxdapi/configs/config.yaml"
if [ ! -f "$config_file" ]; then
err "配置文件不存在: $config_file"
fi
reading "请输入服务端口 [8848]" server_port
server_port=${server_port:-8848}
reading "请输入API密钥 [随机生成]" api_hash
if [ -z "$api_hash" ]; then
api_hash=$(openssl rand -hex 16)
ok "API密钥已生成: $api_hash"
fi
reading "请输入流量采集间隔秒数 [20]" traffic_interval
traffic_interval=${traffic_interval:-20}
reading "请输入流量批量更新数量 [5]" traffic_batch_size
traffic_batch_size=${traffic_batch_size:-5}
while true; do
reading "请选择数据库类型 sqlite/mysql/postgres [sqlite]" db_type
db_type=${db_type:-sqlite}
if [[ "$db_type" =~ ^(sqlite|mysql|postgres)$ ]]; then
break
else
warn "请输入 sqlite、mysql 或 postgres"
fi
done
if [[ "$db_type" == "mysql" ]]; then
while true; do
reading "使用本地安装还是远程配置local/remote [local]" mysql_location
mysql_location=${mysql_location:-local}
if [[ "$mysql_location" =~ ^(local|remote)$ ]]; then
break
else
warn "请输入 local 或 remote"
fi
done
if [[ "$mysql_location" == "local" ]]; then
info "安装 MariaDB..."
install_package mariadb-server
service_manager start mariadb
service_manager enable mariadb
mysql_host="localhost"
mysql_port="3306"
mysql_user="lxdapi"
mysql_password=$(openssl rand -hex 8)
mysql_database="lxdapi"
info "创建数据库和用户..."
mysql -u root << EOF
CREATE DATABASE IF NOT EXISTS ${mysql_database};
CREATE USER IF NOT EXISTS '${mysql_user}'@'localhost' IDENTIFIED BY '${mysql_password}';
GRANT ALL PRIVILEGES ON ${mysql_database}.* TO '${mysql_user}'@'localhost';
FLUSH PRIVILEGES;
EOF
ok "MariaDB 数据库已创建"
ok "用户: $mysql_user"
ok "密码: $mysql_password"
else
reading "请输入 MySQL 主机地址:" mysql_host
reading "请输入 MySQL 端口 [3306]" mysql_port
mysql_port=${mysql_port:-3306}
reading "请输入 MySQL 用户名:" mysql_user
reading "请输入 MySQL 密码:" mysql_password
reading "请输入 MySQL 数据库名:" mysql_database
fi
sed -i "s|__MYSQL_HOST__|$mysql_host|g" "$config_file"
sed -i "s|__MYSQL_PORT__|$mysql_port|g" "$config_file"
sed -i "s|__MYSQL_USER__|$mysql_user|g" "$config_file"
sed -i "s|__MYSQL_PASSWORD__|$mysql_password|g" "$config_file"
sed -i "s|__MYSQL_DATABASE__|$mysql_database|g" "$config_file"
elif [[ "$db_type" == "postgres" ]]; then
while true; do
reading "使用本地安装还是远程配置local/remote [local]" postgres_location
postgres_location=${postgres_location:-local}
if [[ "$postgres_location" =~ ^(local|remote)$ ]]; then
break
else
warn "请输入 local 或 remote"
fi
done
if [[ "$postgres_location" == "local" ]]; then
info "安装 PostgreSQL..."
install_package postgresql
service_manager start postgresql
service_manager enable postgresql
postgres_host="localhost"
postgres_port="5432"
postgres_user="lxdapi"
postgres_password=$(openssl rand -hex 8)
postgres_database="lxdapi"
postgres_sslmode="disable"
info "创建数据库和用户..."
sudo -u postgres psql << EOF
CREATE DATABASE ${postgres_database};
CREATE USER ${postgres_user} WITH PASSWORD '${postgres_password}';
GRANT ALL PRIVILEGES ON DATABASE ${postgres_database} TO ${postgres_user};
EOF
ok "PostgreSQL 数据库已创建"
ok "用户: $postgres_user"
ok "密码: $postgres_password"
else
reading "请输入 PostgreSQL 主机地址:" postgres_host
reading "请输入 PostgreSQL 端口 [5432]" postgres_port
postgres_port=${postgres_port:-5432}
reading "请输入 PostgreSQL 用户名:" postgres_user
reading "请输入 PostgreSQL 密码:" postgres_password
reading "请输入 PostgreSQL 数据库名:" postgres_database
reading "请输入 PostgreSQL SSL模式 [disable]" postgres_sslmode
postgres_sslmode=${postgres_sslmode:-disable}
fi
sed -i "s|__POSTGRES_HOST__|$postgres_host|g" "$config_file"
sed -i "s|__POSTGRES_PORT__|$postgres_port|g" "$config_file"
sed -i "s|__POSTGRES_USER__|$postgres_user|g" "$config_file"
sed -i "s|__POSTGRES_PASSWORD__|$postgres_password|g" "$config_file"
sed -i "s|__POSTGRES_DATABASE__|$postgres_database|g" "$config_file"
sed -i "s|__POSTGRES_SSLMODE__|$postgres_sslmode|g" "$config_file"
fi
while true; do
reading "请选择任务队列后端 memory/redis [memory]" task_backend
task_backend=${task_backend:-memory}
if [[ "$task_backend" =~ ^(memory|redis)$ ]]; then
break
else
warn "请输入 memory 或 redis"
fi
done
if [[ "$task_backend" == "redis" ]]; then
info "安装 Redis..."
install_package redis-server
service_manager start redis-server
service_manager enable redis-server
redis_host="localhost"
redis_port="6379"
redis_password=""
redis_db="0"
ok "Redis 已安装并启动"
sed -i "s|__REDIS_HOST__|$redis_host|g" "$config_file"
sed -i "s|__REDIS_PORT__|$redis_port|g" "$config_file"
sed -i "s|__REDIS_PASSWORD__|$redis_password|g" "$config_file"
sed -i "s|__REDIS_DB__|$redis_db|g" "$config_file"
fi
reading "请输入管理员用户名 [admin]" admin_user
admin_user=${admin_user:-admin}
reading "请输入管理员密码 [随机生成]" admin_pass
if [ -z "$admin_pass" ]; then
admin_pass=$(openssl rand -hex 4)
ok "管理员密码已生成: $admin_pass"
fi
reading "请输入Session密钥 [随机生成]" session_secret
if [ -z "$session_secret" ]; then
session_secret=$(openssl rand -hex 16)
ok "Session密钥已生成: $session_secret"
fi
info "写入配置文件..."
sed -i "s|__SERVER_PORT__|$server_port|g" "$config_file"
sed -i "s|__API_HASH__|$api_hash|g" "$config_file"
sed -i "s|__TRAFFIC_INTERVAL__|$traffic_interval|g" "$config_file"
sed -i "s|__TRAFFIC_BATCH_SIZE__|$traffic_batch_size|g" "$config_file"
sed -i "s|__DB_TYPE__|$db_type|g" "$config_file"
sed -i "s|__TASK_BACKEND__|$task_backend|g" "$config_file"
sed -i "s|__ADMIN_USER__|$admin_user|g" "$config_file"
sed -i "s|__ADMIN_PASS__|$admin_pass|g" "$config_file"
sed -i "s|__SESSION_SECRET__|$session_secret|g" "$config_file"
sed -i "s|__MYSQL_HOST__|localhost|g" "$config_file"
sed -i "s|__MYSQL_PORT__|3306|g" "$config_file"
sed -i "s|__MYSQL_USER__|lxdapi|g" "$config_file"
sed -i "s|__MYSQL_PASSWORD__|password|g" "$config_file"
sed -i "s|__MYSQL_DATABASE__|lxdapi|g" "$config_file"
sed -i "s|__POSTGRES_HOST__|localhost|g" "$config_file"
sed -i "s|__POSTGRES_PORT__|5432|g" "$config_file"
sed -i "s|__POSTGRES_USER__|lxdapi|g" "$config_file"
sed -i "s|__POSTGRES_PASSWORD__|password|g" "$config_file"
sed -i "s|__POSTGRES_DATABASE__|lxdapi|g" "$config_file"
sed -i "s|__POSTGRES_SSLMODE__|disable|g" "$config_file"
sed -i "s|__REDIS_HOST__|localhost|g" "$config_file"
sed -i "s|__REDIS_PORT__|6379|g" "$config_file"
sed -i "s|__REDIS_PASSWORD__||g" "$config_file"
sed -i "s|__REDIS_DB__|0|g" "$config_file"
ok "配置文件已更新"
}
setup_lxdapi_service() {
info "配置 lxdapi 系统服务..."
config_file="/opt/lxdapi/configs/config.yaml"
if [ ! -f "$config_file" ]; then
err "配置文件不存在: $config_file"
fi
if grep -q "__SERVER_PORT__" "$config_file"; then
err "配置文件未完成配置"
fi
sys_arch=$(uname -m)
case $sys_arch in
x86_64)
exec_bin="/opt/lxdapi/lxdapi-amd64"
;;
aarch64|arm64)
exec_bin="/opt/lxdapi/lxdapi-arm64"
;;
*)
err "不支持的架构: $sys_arch"
;;
esac
service_file="/etc/systemd/system/lxdapi.service"
cat > "$service_file" << EOF
[Unit]
Description=LXD API Server
After=network.target lxd.service
Wants=lxd.service
[Service]
Type=simple
User=root
WorkingDirectory=/opt/lxdapi
ExecStart=$exec_bin
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
ok "服务文件已创建: $service_file"
info "重载 systemd 配置..."
systemctl daemon-reload
info "启用开机自启..."
systemctl enable lxdapi
info "启动 lxdapi 服务..."
systemctl start lxdapi
sleep 2
if systemctl is-active --quiet lxdapi; then
ok "lxdapi 服务已启动"
echo
info "===== 服务状态 ====="
systemctl status lxdapi --no-pager | head -10
else
warn "lxdapi 服务启动失败"
echo
info "===== 错误日志 ====="
journalctl -u lxdapi -n 20 --no-pager
fi
}
main() {
print_step "1" "5" "初始化环境"
set_locale
install_base_packages
ok "环境初始化完成"
print_step "2" "5" "安装 LXD"
install_lxd
print_step "3" "5" "配置存储资源"
configure_resources
setup_storage
ok "存储配置完成"
print_step "4" "5" "导入容器镜像"
import_container_images
ok "镜像导入完成"
print_step "5" "5" "部署 lxdapi"
deploy_lxdapi
configure_lxdapi
setup_lxdapi_service
ok "lxdapi 部署完成"
echo
echo "========================================"
echo " lxdapi 安装完成"
echo "========================================"
echo
info "LXD 版本: $(lxd --version)"
info "LXC 版本: $(lxc --version)"
echo
info "===== 1. 网络配置 ====="
lxc network list
echo
info "===== 2. 存储配置 ====="
lxc storage list
echo
info "===== 3. 镜像配置 ====="
lxc image list
echo
info "===== 4. 后端配置 ====="
info "服务端口: $server_port"
info "API密钥: $api_hash"
info "流量间隔: $traffic_interval"
info "批量大小: $traffic_batch_size"
info "数据库: $db_type"
if [[ "$db_type" == "mysql" ]]; then
info "MySQL: $mysql_user@$mysql_host:$mysql_port/$mysql_database"
info "MySQL密码: $mysql_password"
elif [[ "$db_type" == "postgres" ]]; then
info "PostgreSQL: $postgres_user@$postgres_host:$postgres_port/$postgres_database"
info "PostgreSQL密码: $postgres_password"
fi
info "任务队列: $task_backend"
if [[ "$task_backend" == "redis" ]]; then
info "Redis: localhost:6379"
fi
info "管理员: $admin_user"
info "管理员密码: $admin_pass"
info "Session密钥: $session_secret"
echo
info "===== 5. lxdapi 服务状态 ====="
info "等待服务启动..."
sleep 5
systemctl status lxdapi --no-pager -l
}
main