368 lines
9.9 KiB
Bash
Raw Normal View History

2025-09-16 11:54:39 +08:00
#!/bin/bash
set -e
# =========================================== 基础检查与更新 ===========================================
SCRIPT_PATH=`pwd`
function check() {
if [ "$(id -u)" -ne 0 ]; then
echo "请以root权限运行此脚本" >&2
exit 1
fi
osCheck=`uname -a`
if [[ $osCheck =~ 'x86_64' ]];then
architecture="amd64"
else
echo "暂不支持的系统架构,选择受支持的系统。"
exit 1
fi
if [ ! -d "offline_resources" ]; then
echo "未找到资源目录请确保offline_resources目录与脚本在同一位置" >&2
exit 1
fi
}
function upgrade() {
echo "更新系统源"
sudo apt update -y
sudo apt upgrade -y
}
# =========================================== Docker与1Panel ===========================================
function check_docker_installed() {
if command -v docker &> /dev/null; then
echo "Docker 已安装,版本: $(docker --version)"
return 0
else
echo "Docker 未安装"
return 1
fi
}
function check_1panel_installed() {
if systemctl status 1panel-core &> /dev/null; then
echo "1Panel 已安装,状态: $(systemctl is-active 1panel-core)"
return 0
else
echo "1Panel 未安装"
return 1
fi
}
function install_docker() {
if check_docker_installed; then
echo "Docker 已经安装,跳过安装步骤"
return 0
fi
echo && echo "正在安装依赖包和Docker..." && echo
dpkg -i debs/*.deb || apt-get -f install -y
echo && echo "启动Docker服务..." && echo
systemctl start docker
systemctl enable docker
echo && echo "安装Docker Compose..." && echo
cp docker-compose/`ls docker-compose/ | grep docker-compose | head -n 1` /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
if check_docker_installed; then
echo "Docker 安装成功!"
else
echo "Docker 安装失败!" >&2
exit 1
fi
}
function install_1panel() {
if check_1panel_installed; then
echo "1Panel 已经安装,跳过安装步骤"
return 0
fi
echo && echo "安装1Panel..." && echo
panel_package=$(ls 1panel | grep -G '1panel-v.*\.tar\.gz' | head -n 1)
if [ -z "${panel_package}" ]; then
echo "未找到1Panel安装包" >&2
exit 1
fi
tar -zxvf "1panel/${panel_package}" -C 1panel
panel_dir=$(ls -l 1panel | grep '^d' | grep 1panel | awk '{print $NF}' | head -n 1)
if [ -z "$panel_dir" ]; then
echo "未找到1Panel解压目录" >&2
exit 1
fi
chmod u+x "./1panel/$panel_dir/install.sh"
sudo "./1panel/$panel_dir/install.sh"
sleep 3
if check_1panel_installed; then
echo "1Panel 安装成功!"
else
echo "1Panel 安装失败!" >&2
exit 1
fi
}
# =========================================== 通用函数处理 ===========================================
# 主函数:空处理
function process_empty() {
return 0
}
# 主函数处理tar文件并执行指定函数
function process_tar_files() {
local resource_dir="$1"
local process_function="$2"
local file_patterns=("${@:3}")
if [ ${#file_patterns[@]} -eq 0 ]; then
file_patterns=("*.tar")
fi
if [ ! -d "$resource_dir" ]; then
echo "错误: 目录 $resource_dir 不存在"
return 1
fi
if ! declare -f "$process_function" > /dev/null; then
echo "错误: 函数 $process_function 未定义"
return 1
fi
local file_count=0
local success_count=0
local fail_count=0
echo "开始在目录 $resource_dir 中查找文件..."
for pattern in "${file_patterns[@]}"; do
echo "搜索模式: $pattern"
for tar_file in "$resource_dir"/$pattern; do
filename=$(basename "$tar_file")
"$process_function" "$tar_file" "${filename}"
file_count=$((file_count + 1))
done
done
echo "=== 处理完成 ==="
echo "总共找到: $file_count 个文件"
echo "成功: $success_count"
echo "失败: $fail_count"
if [ $file_count -eq 0 ]; then
echo "在目录 $resource_dir 中未找到以下模式的文件: ${file_patterns[*]}"
echo "目录内容:"
ls -la "$resource_dir/" 2>/dev/null || echo "无法列出目录内容"
fi
return $fail_count
}
# 处理关联数组的函数
function process_associative_array() {
# arg1: 默认路径
# arg2: 执行数组
# arg3: 自定义初始化函数
local path="$1"
local array_name="$2"
local func_name="$3"
eval "local keys=(\"\${!${array_name}[@]}\")"
for key in "${keys[@]}"; do
eval "local value=\"\${${array_name}[\$key]}\""
name=$(echo "${key}" | awk -F. '{if (NF>1) {for(i=1;i<NF;i++) printf "%s%s", $i, (i<NF-1?".":"")}}')
"${func_name}" "${path}/${name}" "${key}" "${value}"
done
}
# =========================================== 部署容器 ===========================================
function docker_load_tar() {
# arg1 加载的镜像文件名称
# arg2 镜像描述
SOURCE_FILE=$1
SOURCE_DESCRIPTION=$2
echo "加载 ${SOURCE_DESCRIPTION} 镜像"
docker load -i ${SOURCE_FILE} || { echo "加载 ${SOURCE_DESCRIPTION} 镜像失败"; exit 1; }
}
function docker_installer() {
# arg1: 安装到 1panel 的程序目录
# arg2: 迁移到 1panel 程序目录的压缩文件
# arg3: 自定义初始化函数(可选)
local TARGET_DIR="${1}"
local SOURCE_FILE="${2}"
local CUSTOM_INIT_FUNC="${3}"
local SOURCE_PATH=$(pwd)
local DEFAULT_DOCKER_COMPOSE="docker-compose.yml"
local TIMESTAMP=$(date +%Y%m%d_%H%M%S)
local BACKUP_DIR="${TARGET_DIR}_backup_${TIMESTAMP}"
if [ $# -lt 2 ]; then
echo "错误:缺少必要参数"
echo "用法: docker_installer <目标目录> <源压缩文件> [自定义初始化函数]"
return 1
fi
if [ ! -f "${SOURCE_FILE}" ] || [ ! -r "${SOURCE_FILE}" ]; then
echo "错误:源文件 ${SOURCE_FILE} 不存在或不可读"
return 1
fi
if [ ! -d "${TARGET_DIR}" ]; then
echo "目录 ${TARGET_DIR} 不存在,尝试创建..."
mkdir -p "${TARGET_DIR}" || {
echo "无法创建目录 ${TARGET_DIR}"
return 1
}
fi
echo "复制文件到 ${TARGET_DIR}"
cp "${SOURCE_FILE}" "${TARGET_DIR}/" || {
echo "复制文件失败"
return 1
}
cd "${TARGET_DIR}" || {
echo "无法进入目录 ${TARGET_DIR}"
return 1
}
local FILENAME=$(basename "${SOURCE_FILE}")
echo "开始解压 ${FILENAME}"
case "${FILENAME##*.}" in
zip)
unzip -q "${FILENAME}" || {
echo "解压 ${FILENAME} 失败"
return 1
}
;;
tar|gz|tgz|bz2)
tar -xf "${FILENAME}" || {
echo "解压 ${FILENAME} 失败"
return 1
}
;;
*)
echo "不支持的压缩格式: ${FILENAME##*.}"
return 1
;;
esac
rm -f "${FILENAME}"
if [ -n "${CUSTOM_INIT_FUNC}" ]; then
if type "${CUSTOM_INIT_FUNC}" &>/dev/null; then
echo "执行自定义初始化函数 ${CUSTOM_INIT_FUNC}"
${CUSTOM_INIT_FUNC} || {
echo "自定义初始化函数执行失败"
return 1
}
else
echo "警告:初始化函数 ${CUSTOM_INIT_FUNC} 不存在,跳过"
fi
fi
local COMPOSE_FILE="${DEFAULT_DOCKER_COMPOSE}"
if [ -f "${COMPOSE_FILE}" ]; then
echo "${TARGET_DIR} 下启动 Docker Compose"
if ! command -v docker-compose &>/dev/null; then
echo "错误docker-compose 未安装"
return 1
fi
if ! docker info &>/dev/null; then
echo "错误Docker 守护进程未运行"
return 1
fi
docker-compose up -d || {
echo "Docker Compose 启动失败"
return 1
}
echo "Docker Compose 启动成功"
else
echo "${TARGET_DIR} 下未找到 ${COMPOSE_FILE}"
echo "可用文件:"
ls -la
return 1
fi
cd "${SOURCE_PATH}" >/dev/null
echo && echo "操作完成" && echo
echo "目标目录: ${TARGET_DIR}"
if [ -d "${BACKUP_DIR}" ]; then
echo "备份位置: ${BACKUP_DIR}"
fi
}
# =========================================== 特殊初始化 ===========================================
function init_rocketmq() {
cd rocketmq
sh scripts/init.sh || { echo "初始化 init.sh 失败"; exit 1; }
}
# =========================================== 主流程 ===========================================
function main() {
check
# upgrade
cd ${SCRIPT_PATH}/offline_resources
install_docker
install_1panel
echo && echo "验证安装结果..."
echo && echo "Docker版本: $(docker --version)"
echo && echo "Docker Compose版本: $(docker-compose --version)"
echo && echo "1Panel状态: $(systemctl status 1panel-core | grep Active)"
echo && echo
echo && echo "所有组件安装完成!" && echo && echo
cd ${SCRIPT_PATH}/busicess_resources
process_tar_files "`pwd`/containers" "docker_load_tar"
echo && echo "所有镜像安装完成!" && echo && echo
NETWORK_NAME="1panel-network"
if ! docker network ls | grep -q "$NETWORK_NAME"; then
echo "网络 $NETWORK_NAME 不存在,正在创建..."
docker network create "$NETWORK_NAME"
echo "网络 $NETWORK_NAME 创建成功!"
fi
cd ${SCRIPT_PATH}/busicess_resources/dataset
declare -A my_assoc_array=(
["minio.zip"]="process_empty"
["mysql.zip"]="process_empty"
["redis.zip"]="process_empty"
["rocketmq.zip"]="init_rocketmq"
["portainer-ce.zip"]="process_empty"
["phpmyadmin.zip"]="process_empty"
["simulation.zip"]="process_empty"
)
process_associative_array "/opt/1panel/apps" my_assoc_array "docker_installer" || { echo "初始化 init.sh 失败"; exit 1; }
echo && echo "所有容器安装完成!" && echo && echo
}
main