大量更新

This commit is contained in:
zeaslity
2026-05-19 14:28:56 +08:00
parent 9fc3372fa3
commit 37a6c6510f
223 changed files with 140833 additions and 2424 deletions

View File

@@ -0,0 +1,24 @@
# master节点
sudo apt update
sudo apt install -y apt-cacher-ng
systemctl status apt-cacher-ng
# worker节点
sudo tee /etc/apt/apt.conf.d/01proxy <<EOF
Acquire::http::Proxy "http://10.22.57.8:3142";
Acquire::https::Proxy "http://10.22.57.8:3142";
EOF
ssh root@${server} "printf '%s\n' \
'Acquire::http::Proxy \"http://10.22.57.8:3142\";' \
'Acquire::https::Proxy \"http://10.22.57.8:3142\";' \
| tee /etc/apt/apt.conf.d/01proxy >/dev/null"

View File

@@ -0,0 +1,47 @@
# master节点
# 安装 squid
yum install -y squid
# 备份默认配置
cp /etc/squid/squid.conf /etc/squid/squid.conf.bak
# 编辑 /etc/squid/squid.conf
# 定义内网网段 关键!
acl localnet src 192.168.5.0/24
# 允许内网访问
http_access allow localnet
http_access allow localhost
# 监听端口
http_port 3128
# 其余保持默认,拒绝所有其他
http_access deny all
systemctl enable squid --now
# worker节点
## 编辑 /etc/yum.conf
[main]
# ... 其他配置 ...
proxy=http://192.168.5.41:3128
# 在客户端节点执行
yum makecache
yum install -y wget
# 直接执行
sed -n '/^proxy=/ {p;q}; $ {a proxy=http://192.168.5.41:3128' -e 'p}' /etc/yum.conf
# 批量执行
ssh root@${server} "grep -q '^proxy=' /etc/yum.conf && grep '^proxy=' /etc/yum.conf || echo 'proxy=http://192.168.5.41:3128' >> /etc/yum.conf"

View File

@@ -0,0 +1,90 @@
#!/bin/bash
set -e
# =========================================================
# 用户配置部分
# =========================================================
DISK="/dev/nvme0n1" # 要操作的物理磁盘(例如 /dev/sdb 或 /dev/nvme0n1
MOUNT_PATH="/var/lib/docker" # 挂载点路径(目录会自动创建)
FS_TYPE="ext4" # 文件系统类型支持ext4/xfs默认ext4
# =========================================================
# 核心逻辑(建议非必要不修改)
# =========================================================
function check_prerequisites() {
# 必须root权限运行检查
[[ $EUID -ne 0 ]] && echo -e "\033[31m错误必须使用root权限运行此脚本\033[0m" && exit 1
# 磁盘存在性检查
[[ ! -b "$DISK" ]] && echo -e "\033[31m错误磁盘 $DISK 不存在\033[0m" && exit 1
# 文件系统类型校验
if [[ "$FS_TYPE" != "ext4" && "$FS_TYPE" != "xfs" ]]; then
echo -e "\033[31m错误不支持的磁盘格式 $FS_TYPE,仅支持 ext4/xfs\033[0m"
exit 1
fi
}
function prepare_disk() {
local partition
# 核心修复:兼容 NVMe 和传统 SCSI/SATA 磁盘的分区命名规则
# 如果物理磁盘名称以数字结尾 (如 nvme0n1),分区名加 'p' (nvme0n1p1)
# 如果以字母结尾 (如 sdb),分区名直接加数字 (sdb1)
if [[ "$DISK" =~ [0-9]$ ]]; then
partition="${DISK}p1"
else
partition="${DISK}1"
fi
echo -e "\033[34m正在初始化磁盘分区...\033[0m"
parted "$DISK" --script mklabel gpt
parted "$DISK" --script mkpart primary 0% 100%
parted "$DISK" --script set 1 lvm on
# 通知系统内核重新读取分区表
partprobe "$DISK"
# 增加极短暂延时确保NVMe设备分区节点已在 /dev/ 下成功生成
sleep 2
echo -e "\033[34m正在创建LVM结构 ($partition)...\033[0m"
pvcreate "$partition"
vgcreate datavg "$partition"
lvcreate -y -l 100%FREE -n lvdata datavg
}
function format_and_mount() {
echo -e "\033[34m格式化逻辑卷...\033[0m"
if [[ "$FS_TYPE" == "ext4" ]]; then
mkfs.ext4 -F "/dev/datavg/lvdata"
else
mkfs.xfs -f "/dev/datavg/lvdata"
fi
echo -e "\033[34m设置挂载配置...\033[0m"
mkdir -p "$MOUNT_PATH"
UUID=$(blkid -s UUID -o value "/dev/datavg/lvdata")
# 备份 fstab 防呆,方便回滚
cp /etc/fstab /etc/fstab.bak_$(date +%Y%m%d%H%M%S)
echo "UUID=$UUID $MOUNT_PATH $FS_TYPE defaults 0 0" | tee -a /etc/fstab >/dev/null
mount -a
}
function verify_result() {
echo -e "\n\033[1;36m最终验证结果\033[0m"
lsblk -f "$DISK"
echo -e "\n磁盘空间使用情况"
df -TH "$MOUNT_PATH"
}
# =========================================================
# 主执行流程
# =========================================================
check_prerequisites
prepare_disk
format_and_mount
verify_result
echo -e "\n\033[32m操作执行完毕请仔细核查上述输出信息\033[0m"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,582 @@
#!/usr/bin/env bash
# ==============================================================================
# Metadata
# ==============================================================================
# ubuntu 22.04 版本对应关系
# docker-ce=5:24.0.9-1~ubuntu.22.04~jammy
# docker-ce-cli=5:24.0.9-1~ubuntu.22.04~jammy
# docker-ce-rootless-extras=5:24.0.9-1~ubuntu.22.04~jammy
# docker-compose-plugin=2.24.5-1~ubuntu.22.04~jammy
# 官方为 1.7.13
# containerd=1.7.24-0ubuntu1~22.04.2
# docker-buildx-plugin=0.11.2-1~ubuntu.22.04~jammy
# ==============================================================================
set -euo pipefail
# ==============================================================================
# Global Constants
# ==============================================================================
readonly SCRIPT_NAME="$(basename "$0")"
readonly SCRIPT_VERSION="2.0.0"
# Default mirror for Docker repo (you asked: only focus on docker source)
readonly DEFAULT_DOCKER_APT_MIRROR="https://mirrors.aliyun.com/docker-ce/linux/ubuntu"
# Default keyring location (recommended by modern Ubuntu)
readonly DEFAULT_KEYRING_PATH="/etc/apt/keyrings/docker.gpg"
# Exit codes
readonly EC_OK=0
readonly EC_GENERAL=1
readonly EC_UNSUPPORTED_OS=10
readonly EC_DEPENDENCY=11
readonly EC_OFFLINE_NO_KEY=20
readonly EC_APT_FAILURE=30
# ==============================================================================
# Configurable Variables (Environment Overrides)
# ==============================================================================
# You may export these before running:
# DOCKER_VERSION="20.10" # or "20.10.15" (optional)
# DOCKER_APT_MIRROR="https://..."
# DOCKER_KEYRING_PATH="/root/wdd/docker.gpg"
# LOCAL_DOCKER_GPG="/path/to/docker.gpg" (optional)
# LOG_LEVEL="DEBUG|INFO|WARN|ERROR"
DOCKER_VERSION="${DOCKER_VERSION:-24.0.9}"
DOCKER_APT_MIRROR="${DOCKER_APT_MIRROR:-$DEFAULT_DOCKER_APT_MIRROR}"
DOCKER_KEYRING_PATH="${DOCKER_KEYRING_PATH:-$DEFAULT_KEYRING_PATH}"
LOCAL_DOCKER_GPG="${LOCAL_DOCKER_GPG:-/root/wdd/docker.gpg}"
LOG_LEVEL="${LOG_LEVEL:-INFO}"
# ==============================================================================
# Function Call Graph (ASCII)
# ==============================================================================
# main
# |
# +--> init_traps
# |
# +--> check_platform
# |
# +--> ensure_prerequisites
# |
# +--> detect_public_network
# | |
# | +--> can_fetch_url_head
# |
# +--> ensure_docker_gpg_key
# | |
# | +--> install_key_from_online
# | | |
# | | +--> require_cmd (curl, gpg)
# | |
# | +--> install_key_from_local
# |
# +--> configure_docker_repo
# |
# +--> install_docker_packages
# | |
# | +--> resolve_docker_version
# |
# +--> pin_docker_packages
# |
# +--> enable_docker_service
# ==============================================================================
# ==============================================================================
# Logging
# ==============================================================================
### Map log level string to numeric value.
### @param level_str string Level string (DEBUG/INFO/WARN/ERROR)
### @return 0 Always returns 0; outputs numeric level to stdout
### @require none
log_level_to_num() {
case "${1:-INFO}" in
DEBUG) echo 10 ;;
INFO) echo 20 ;;
WARN) echo 30 ;;
ERROR) echo 40 ;;
*) echo 20 ;;
esac
}
### Unified logger with level gating.
### @param level string Log level
### @param message string Message
### @return 0 Always returns 0
### @require date
log() {
local level="${1:?level required}"
shift
local message="${*:-}"
local now
now="$(date '+%F %T')"
local current_level_num wanted_level_num
current_level_num="$(log_level_to_num "$LOG_LEVEL")"
wanted_level_num="$(log_level_to_num "$level")"
if [ "$wanted_level_num" -lt "$current_level_num" ]; then
return 0
fi
# > Keep format stable for parsing by log collectors
printf '%s [%s] %s: %s\n' "$now" "$level" "$SCRIPT_NAME" "$message" >&2
}
# ==============================================================================
# Error Handling & Traps
# ==============================================================================
### Trap handler for unexpected errors.
### @param exit_code int Exit code from failing command
### @return 0 Always returns 0
### @require none
on_error() {
local exit_code="${1:-$EC_GENERAL}"
log ERROR "Unhandled error occurred (exit_code=${exit_code})."
exit "$exit_code"
}
### Trap handler for script exit.
### @param exit_code int Exit code
### @return 0 Always returns 0
### @require none
on_exit() {
local exit_code="${1:-$EC_OK}"
if [ "$exit_code" -eq 0 ]; then
log INFO "Done."
else
log WARN "Exited with code ${exit_code}."
fi
return 0
}
### Initialize traps (ERR/INT/TERM/EXIT).
### @return 0 Success
### @require none
init_traps() {
trap 'on_error $?' ERR
trap 'log WARN "Interrupted (SIGINT)"; exit 130' INT
trap 'log WARN "Terminated (SIGTERM)"; exit 143' TERM
trap 'on_exit $?' EXIT
}
# ==============================================================================
# Privilege Helpers
# ==============================================================================
### Run a command as root (uses sudo if not root).
### @param cmd string Command to run
### @return 0 Success; non-zero on failure
### @require sudo (if not root)
run_root() {
if [ "$(id -u)" -eq 0 ]; then
# shellcheck disable=SC2068
"$@"
else
# shellcheck disable=SC2068
sudo "$@"
fi
}
# ==============================================================================
# Dependency Checks
# ==============================================================================
### Ensure a command exists in PATH.
### @param cmd_name string Command name
### @return 0 If exists; 1 otherwise
### @require none
require_cmd() {
local cmd_name="${1:?cmd required}"
if ! command -v "$cmd_name" >/dev/null 2>&1; then
log ERROR "Missing dependency: ${cmd_name}"
return 1
fi
return 0
}
# ==============================================================================
# Platform Check
# ==============================================================================
### Check OS is Ubuntu and supported versions.
### @return 0 Supported; exits otherwise
### @require lsb_release, awk
check_platform() {
require_cmd lsb_release || exit "$EC_DEPENDENCY"
local distro version
distro="$(lsb_release -is 2>/dev/null || true)"
version="$(lsb_release -rs 2>/dev/null || true)"
if [ "$distro" != "Ubuntu" ]; then
log ERROR "Unsupported OS: ${distro}. This script supports Ubuntu only."
exit "$EC_UNSUPPORTED_OS"
fi
case "$version" in
18.04|20.04|22.04|24.04) ;;
*)
log ERROR "Unsupported Ubuntu version: ${version}. Supported: 18.04/20.04/22.04/24.04"
exit "$EC_UNSUPPORTED_OS"
;;
esac
log INFO "Platform OK: ${distro} ${version}"
}
# ==============================================================================
# APT Prerequisites
# ==============================================================================
### Install required packages for repository/key management and Docker installation.
### @return 0 Success; exits on apt failures
### @require apt-get
ensure_prerequisites() {
require_cmd apt-get || exit "$EC_DEPENDENCY"
log INFO "Installing prerequisites (does NOT modify APT sources or proxy)..."
# > apt update must work via your existing proxy+mirror scripts
if ! run_root apt-get update; then
log ERROR "apt-get update failed. Check APT proxy / mirror configuration."
exit "$EC_APT_FAILURE"
fi
# > Keep dependencies minimal; curl/gpg used only for online key fetch.
if ! run_root apt-get install -y ca-certificates gnupg lsb-release; then
log ERROR "Failed to install prerequisites."
exit "$EC_APT_FAILURE"
fi
log INFO "Prerequisites installed."
}
# ==============================================================================
# Public Network Reachability
# ==============================================================================
### Check whether we can fetch HTTP headers from a URL (lightweight reachability).
### @param test_url string URL to test
### @return 0 Reachable; 1 otherwise
### @require curl (optional; if missing returns 1)
can_fetch_url_head() {
local test_url="${1:?url required}"
if ! command -v curl >/dev/null 2>&1; then
log WARN "curl not found; cannot test public network reachability via HTTP."
return 1
fi
# > Use short timeout to avoid hanging in restricted networks
curl -fsSI --max-time 3 "$test_url" >/dev/null 2>&1
}
### Detect whether public network access is available for Docker key fetch.
### @return 0 Online; 1 Offline/Uncertain
### @require none
detect_public_network() {
local test_url="${DOCKER_APT_MIRROR%/}/gpg"
log INFO "Detecting public network reachability: HEAD ${test_url}"
if can_fetch_url_head "$test_url"; then
log INFO "Public network reachable for Docker mirror."
return 0
fi
log WARN "Public network NOT reachable (or curl missing). Will try local GPG key."
return 1
}
# ==============================================================================
# Docker GPG Key Management
# ==============================================================================
### Install Docker GPG key from online source (mirror).
### @param gpg_url string GPG URL
### @param keyring_path string Keyring output path
### @return 0 Success; non-zero on failure
### @require curl, gpg, install, mkdir, chmod
install_key_from_online() {
local gpg_url="${1:?gpg_url required}"
local keyring_path="${2:?keyring_path required}"
require_cmd curl || return 1
require_cmd gpg || return 1
# > Write to temp then atomically install to avoid partial files
local tmp_dir tmp_gpg
tmp_dir="$(mktemp -d)"
tmp_gpg="${tmp_dir}/docker.gpg"
log INFO "Fetching Docker GPG key online: ${gpg_url}"
curl -fsSL --max-time 10 "$gpg_url" | gpg --dearmor -o "$tmp_gpg"
run_root mkdir -p "$(dirname "$keyring_path")"
run_root install -m 0644 "$tmp_gpg" "$keyring_path"
run_root chmod a+r "$keyring_path" || true
rm -rf "$tmp_dir"
log INFO "Docker GPG key installed: ${keyring_path}"
return 0
}
### Install Docker GPG key from local file (offline-friendly).
### @param local_gpg_path string Local GPG file path
### @param keyring_path string Keyring output path
### @return 0 Success; 1 if local key missing; non-zero on other failures
### @require install, mkdir, chmod
install_key_from_local() {
local local_gpg_path="${1:?local_gpg_path required}"
local keyring_path="${2:?keyring_path required}"
if [ ! -f "$local_gpg_path" ]; then
log WARN "Local Docker GPG key not found: ${local_gpg_path}"
return 1
fi
run_root mkdir -p "$(dirname "$keyring_path")"
run_root install -m 0644 "$local_gpg_path" "$keyring_path"
run_root chmod a+r "$keyring_path" || true
log INFO "Docker GPG key installed from local: ${local_gpg_path} -> ${keyring_path}"
return 0
}
### Ensure Docker GPG key exists, using online if reachable; otherwise local-only.
### Offline policy: if local key missing -> DO NOT proceed (exit).
### @param is_online int 0 online; 1 offline
### @return 0 Success; exits with EC_OFFLINE_NO_KEY when offline and no local key
### @require none
ensure_docker_gpg_key() {
local is_online="${1:?is_online required}"
# > If keyring already exists, reuse it (idempotent)
if [ -f "$DOCKER_KEYRING_PATH" ]; then
log INFO "Docker keyring already exists: ${DOCKER_KEYRING_PATH}"
run_root chmod a+r "$DOCKER_KEYRING_PATH" || true
return 0
fi
# > Determine local key candidate paths (priority order)
local script_dir local_candidate
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -n "$LOCAL_DOCKER_GPG" ]; then
local_candidate="$LOCAL_DOCKER_GPG"
elif [ -f "${script_dir}/docker.gpg" ]; then
local_candidate="${script_dir}/docker.gpg"
else
local_candidate=""
fi
local gpg_url
gpg_url="${DOCKER_APT_MIRROR%/}/gpg"
if [ "$is_online" -eq 0 ]; then
# Online: try online key fetch first; if fails, fallback to local if present.
log DEBUG "Online mode: attempt online key install, fallback to local."
if install_key_from_online "$gpg_url" "$DOCKER_KEYRING_PATH"; then
return 0
fi
if [ -n "$local_candidate" ] && install_key_from_local "$local_candidate" "$DOCKER_KEYRING_PATH"; then
return 0
fi
log ERROR "Failed to install Docker GPG key (online fetch failed and no usable local key)."
exit "$EC_DEPENDENCY"
fi
# Offline: strictly local only; if missing -> do not proceed
log INFO "Offline mode: install Docker GPG key from local only."
if [ -n "$local_candidate" ] && install_key_from_local "$local_candidate" "$DOCKER_KEYRING_PATH"; then
return 0
fi
log ERROR "Offline and local Docker GPG key is missing. Will NOT proceed (per policy)."
exit "$EC_OFFLINE_NO_KEY"
}
# ==============================================================================
# Docker Repo Configuration
# ==============================================================================
### Configure Docker APT repository list file.
### @return 0 Success; exits on apt update failures
### @require dpkg, lsb_release, tee, apt-get
configure_docker_repo() {
require_cmd dpkg || exit "$EC_DEPENDENCY"
require_cmd lsb_release || exit "$EC_DEPENDENCY"
require_cmd tee || exit "$EC_DEPENDENCY"
local codename arch list_file
codename="$(lsb_release -cs)"
arch="$(dpkg --print-architecture)"
list_file="/etc/apt/sources.list.d/docker.list"
log INFO "Configuring Docker APT repo: ${DOCKER_APT_MIRROR} (${codename}, ${arch})"
# > Only touch docker repo; do not touch system sources.list
run_root tee "$list_file" >/dev/null <<EOF
deb [arch=${arch} signed-by=${DOCKER_KEYRING_PATH}] ${DOCKER_APT_MIRROR} ${codename} stable
EOF
if ! run_root apt-get update; then
log ERROR "apt-get update failed after configuring Docker repo."
exit "$EC_APT_FAILURE"
fi
log INFO "Docker APT repo configured: ${list_file}"
}
# ==============================================================================
# Docker Installation
# ==============================================================================
### Resolve Docker package version string from APT cache.
### @param docker_version string Desired version ("20.10" or "20.10.15")
### @return 0 Success and echoes full apt version string; exits if not found
### @require apt-cache, awk, grep, sort, head
resolve_docker_version() {
local docker_version="${1:?docker_version required}"
require_cmd apt-cache || exit "$EC_DEPENDENCY"
require_cmd awk || exit "$EC_DEPENDENCY"
require_cmd grep || exit "$EC_DEPENDENCY"
require_cmd sort || exit "$EC_DEPENDENCY"
require_cmd head || exit "$EC_DEPENDENCY"
local resolved=""
# > apt-cache madison output includes epoch, keep it for apt-get install
if [[ "$docker_version" =~ ^[0-9]+\.[0-9]+$ ]]; then
# Pick newest patch/build for that major.minor
resolved="$(
apt-cache madison docker-ce \
| awk -F'|' '{gsub(/ /,"",$2); print $2}' \
| grep -E "^[0-9]+:${docker_version}([.-]|\~)" \
| sort -rV \
| head -1 || true
)"
elif [[ "$docker_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
resolved="$(
apt-cache madison docker-ce \
| awk -F'|' '{gsub(/ /,"",$2); print $2}' \
| grep -E "^[0-9]+:${docker_version}.*" \
| head -1 || true
)"
else
log ERROR "Invalid DOCKER_VERSION format: ${docker_version} (expect 20.10 or 20.10.15)"
exit "$EC_GENERAL"
fi
if [ -z "$resolved" ]; then
log ERROR "Cannot find Docker version '${docker_version}' from APT. Check repo/mirror and apt proxy."
exit "$EC_APT_FAILURE"
fi
echo "$resolved"
return 0
}
### Install Docker packages via APT.
### @return 0 Success; exits on failure
### @require apt-get, systemctl
install_docker_packages() {
require_cmd apt-get || exit "$EC_DEPENDENCY"
local full_version
full_version="$(resolve_docker_version "$DOCKER_VERSION")"
log INFO "Installing Docker packages: docker-ce=${full_version}"
# > Compose: use docker-compose-plugin (no curl downloading binaries)
if ! run_root apt-get install -y \
"docker-ce=${full_version}" \
"docker-ce-cli=${full_version}" \
"docker-ce-rootless-extras=${full_version}" \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin; then
log ERROR "Docker installation failed."
exit "$EC_APT_FAILURE"
fi
# > Optional: provide docker-compose legacy command compatibility
if ! command -v docker-compose >/dev/null 2>&1; then
if [ -x /usr/libexec/docker/cli-plugins/docker-compose ]; then
run_root ln -sf /usr/libexec/docker/cli-plugins/docker-compose /usr/local/bin/docker-compose || true
fi
fi
log INFO "Docker packages installed."
}
### Pin Docker packages to avoid unintended upgrades.
### @return 0 Success; non-zero on failures (non-fatal)
### @require apt-mark
pin_docker_packages() {
if ! command -v apt-mark >/dev/null 2>&1; then
log WARN "apt-mark not found; skip pinning."
return 0
fi
log INFO "Holding Docker packages (prevent auto-upgrade)..."
run_root apt-mark hold \
docker-ce docker-ce-cli docker-ce-rootless-extras containerd.io \
docker-buildx-plugin docker-compose-plugin >/dev/null 2>&1 || true
return 0
}
### Enable and start Docker service, then verify versions.
### @return 0 Success; exits on failure to enable docker
### @require systemctl, docker
enable_docker_service() {
require_cmd systemctl || exit "$EC_DEPENDENCY"
log INFO "Enabling and starting docker service..."
run_root systemctl enable --now docker
# > Verification should not hard-fail the whole script
if command -v docker >/dev/null 2>&1; then
docker --version || true
docker compose version || true
fi
if command -v docker-compose >/dev/null 2>&1; then
docker-compose --version || true
fi
log INFO "Docker service enabled."
}
# ==============================================================================
# Main
# ==============================================================================
### Main entrypoint.
### @return 0 Success; non-zero on failure
### @require none
main() {
init_traps
log INFO "Starting Docker installer (v${SCRIPT_VERSION})..."
check_platform
ensure_prerequisites
local is_online=1
if detect_public_network; then
is_online=0
fi
ensure_docker_gpg_key "$is_online"
configure_docker_repo
install_docker_packages
pin_docker_packages
enable_docker_service
log INFO "All tasks completed successfully."
exit "$EC_OK"
}
main "$@"

View File

@@ -0,0 +1,23 @@
#!/bin/bash
nfs_data_path="/var/lib/docker/nfs_data"
#nfs_data_path="/data/nfs_data"
deploy_nfs_server(){
mkdir -p $nfs_data_path
chmod 777 $nfs_data_path
echo "${nfs_data_path} *(rw,no_root_squash,no_all_squash,sync)" >> /etc/exports
systemctl restart rpcbind
systemctl restart nfs-server
systemctl enable rpcbind
systemctl enable nfs-server
}
deploy_nfs_server
# docker login -u admin -p V2ryStr@ngPss 10.100.2.121:8033

View File

@@ -0,0 +1,9 @@
#!/bin/bash
rm -rf *.tar.gz
rm -rf 2023*.txt
for item in $(mc ls demo/cmlc-installation/tmp/ | awk '{print$6}')
do
mc rm demo/cmlc-installation/tmp/"${item}"
done

View File

@@ -0,0 +1,438 @@
#!/bin/bash
# 约定内容
NeedUploadFolder=99
IsUpload=99
UploadImageName=""
ImageListName=""
ImageTarName=""
ImageName=""
ImageTag=""
InnerIPv4CIDR=""
InnerIPv6CIDR=""
InnerIPv4=""
InnerIPv6=""
CmiiImagePrefix="harbor.cdcyy.com.cn/cmii/"
OSS_URL="https://oss.demo.uavcmlc.com/cmlc-installation/tmp/"
Custom_Client_Harbor="REPLACE:8033"
app_name=""
new_tag=""
harbor_host=""
namespace="xmyd"
#######################################
# description
# Globals:
# ImageName
# ImageTag
# ImageTarName
# RANDOM
# UploadImageName
# Arguments:
# None
#######################################
get_image_tar_name() {
# harbor.cdcyy.com.cn/cmii/cmii-uav-oauth:4.1.6
ImageName=$(echo $UploadImageName | cut -d ":" -f1 | cut -d"/" -f3)
ImageTag=$(echo $UploadImageName | cut -d ":" -f2)
local currentDate=$(date +'%Y-%m-%d')
local random_number=$((RANDOM % 900 + 100))
ImageTarName="$ImageName=$ImageTag=$currentDate=$random_number.tar.gz"
}
#######################################
# description
# Globals:
# ImageName
# ImageTag
# ImageTarName
# UploadImageName
# Arguments:
# None
#######################################
get_image_name_from_tar() {
if [[ $ImageTarName == cmlc* ]]; then
# 兼容octopus-agent的模式
# cmlc=cmii=cmii-uav-busybox=0326.tar.gz
# rancher=rancher=cmii-uav-busybox=0326.tar.gz
# 使用${variable%.pattern}进行后缀删除
ImageName=$(echo $image_name | cut -d "=" -f3)
local tagWithSuffix=$(echo $image_name | cut -d "=" -f4)
ImageTag="${tagWithSuffix%.tar.gz}"
UploadImageName="$ImageName:$ImageTag"
return
fi
# cmii-uav-oauth_4.1.6-0918_20230918_123.tar.gz
ImageName=$(echo $ImageTarName | cut -d "=" -f1)
ImageTag=$(echo $ImageTarName | cut -d"=" -f2)
UploadImageName="$ImageName:$ImageTag"
}
# 获取服务器的公网IP地址
get_Internal_IP_CIDR() {
local interface_prefix=("[[:space:]]eth[0-9]{1,2}" "[[:space:]]ens[0-9]{1,3}" "[[:space:]]eno[0-9]{1,3}" "[[:space:]]enp[0-9]{1,2}")
local real_interface="eth90"
for interface in "${interface_prefix[@]}"; do
echo $(ip link show) | grep -oE ${interface} | head -1
if [[ $? -eq 0 ]]; then
real_interface=$(echo $(ip link show) | grep -oE ${interface} | head -1 | cut -d" " -f2)
echo "当前主机的真实内网网卡为 => [$real_interface]"
break
fi
done
# 提取IPv4地址CIDR格式
local ipv4_regex="inet[[:space:]](25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/[0-9]{1,2}"
# 提取IPv6地址CIDR格式
local ipv6_regex="inet6[[:space:]]([0-9a-fA-F]{0,4}(:[0-9a-fA-F]{0,4}){1,7})\/[0-9]{1,3}"
# 查找IPv4地址
local inner_ipv4=$(echo $(ip addr show $real_interface) | grep -oE $ipv4_regex | cut -d" " -f2)
InnerIPv4CIDR=$inner_ipv4
echo "Interface: $real_interface, IPv4 Address: $inner_ipv4"
# 查找IPv6地址
local inner_ipv6=$(echo $(ip addr show $real_interface) | grep -oE $ipv6_regex | cut -d" " -f2)
InnerIPv6CIDR=$inner_ipv6
echo "Interface: $real_interface, IPv4 Address: $inner_ipv6"
}
#######################################
# description
# Globals:
# InnerIPv4
# InnerIPv4CIDR
# InnerIPv6
# InnerIPv6CIDR
# Arguments:
# None
#######################################
get_Internal_IP() {
get_Internal_IP_CIDR
InnerIPv4=$(echo $InnerIPv4CIDR | cut -d "/" -f1)
InnerIPv6=$(echo $InnerIPv6CIDR | cut -d "/" -f1)
echo "服务器的内网IPv4地址为 $InnerIPv4"
echo "服务器的内网IPv6地址为 $InnerIPv6"
}
parse_args(){
if [ "$1" == "" ]; then
echo "no zip file in error!"
exit 233
fi
local image_name="$1"
if [[ $image_name == cmlc* ]]; then
# 兼容octopus-agent的模式
# cmlc=cmii=cmii-uav-busybox=0326.tar.gz
# rancher=rancher=cmii-uav-busybox=0326.tar.gz
app_name=$(echo $image_name | cut -d "=" -f3)
local tagWithSuffix=$(echo $image_name | cut -d "=" -f4)
new_tag="${tagWithSuffix%.tar.gz}"
return
fi
# 本脚本的模式
# cmii-uav-surveillance=5.2.0-27031-cqga=2024-03-04=573.tar.gz
# cmii-uav-mqtthandler=5.4.0-031201=2024-03-12=138.tar.gz
app_name=$(echo $image_name | cut -d "=" -f1)
new_tag=$(echo $image_name | cut -d "=" -f2)
}
update_image_tag(){
if [ "$new_tag" == "" ]; then
echo "new tag error!"
exit 233
fi
echo ""
echo "[update_image_tag] - start to update => ${harbor_host}/cmii/$app_name:${new_tag}"
echo ""
local image_prefix=$(kubectl -n ${namespace} get deployment "${app_name}" -o=jsonpath='{.spec.template.spec.containers[*].image}' | cut -d":" -f1)
echo "image grep is => ${image_prefix}"
echo "start to update ${namespace} ${app_name} to ${new_tag} !"
echo ""
kubectl -n ${namespace} patch deployment "${app_name}" -p "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"${app_name}\",\"image\": \"${harbor_host}/cmii/$app_name:${new_tag}\"}]}}}}"
echo ""
echo "start to wait for 3 seconds!"
sleep 3
local image_new=$(kubectl -n ${namespace} get deployment "${app_name}" -o=jsonpath='{.spec.template.spec.containers[*].image}')
echo ""
echo "new image are => $image_new"
echo ""
}
#######################################
# description
# Globals:
# _m_opts
# Arguments:
# None
#######################################
_math() {
_m_opts="$@"
printf "%s" "$((_m_opts))"
}
# 前文内容
while [[ $# -gt 0 ]]; do
case "$1" in
-fu | --fileupload)
NeedUploadFolder=1
ImageListName=${2}
shift # past argument
;;
-fd | --filedownload)
NeedUploadFolder=2
ImageListName=${2}
shift # past argument
;;
-u | --upload)
IsUpload=1
UploadImageName="${2}"
shift # past argument
;;
-d | --download)
IsUpload=2
ImageTarName="${2}"
shift # past argument
;;
-h | --harbor)
Custom_Client_Harbor="${2}"
shift # past argument
;;
*)
# unknown option
;;
esac
shift # past argument or value
done
#######################################
# description
# Globals:
# ImageTarName
# UploadImageName
# Arguments:
# None
#######################################
Download_Compress_UploadOss() {
# upload
echo "【上传】 - 需要处理的镜像名称为 => $UploadImageName"
echo ""
echo "【上传】 - 开始下载镜像!"
echo ""
if docker pull "${UploadImageName}" >/dev/null 2>&1; then
echo "下载-镜像下载成功! => $UploadImageName"
else
if docker inspect "${UploadImageName}" >/dev/null 2>&1; then
echo "下载-镜像已经存在 => $UploadImageName"
else
echo ""
echo "下载-镜像下载 失败! => $UploadImageName"
echo "下载-镜像下载 失败! => $UploadImageName"
echo ""
return 233
fi
fi
echo ""
get_image_tar_name
echo "【上传】 - 将要把镜像压缩为 => $ImageTarName"
docker save $UploadImageName | gzip --stdout >${ImageTarName}
echo "【上传】 - 压缩成功 $(ls | grep ${ImageTarName})"
echo""
echo "【上传】 - 开始上传至OSS中!"
mc cp ./${ImageTarName} demo/cmlc-installation/tmp/
echo "【上传】 - 上传OSS成功 => $(mc ls demo/cmlc-installation/tmp/ | grep ${ImageTarName})"
echo""
}
#######################################
# description
# Globals:
# CmiiImagePrefix
# ImageTarName
# InnerIPv4
# OSS_URL
# UploadImageName
# custom_prefix
# Arguments:
# None
# Returns:
# <unknown> ...
#######################################
Download_Load_Tag_UploadHarbor_Update() {
# 更加方便
# Check if the variable starts with "harbor"
# if [[ $ImageTarName != harbor* ]]; then
# ImageTarName="$CmiiImagePrefix$ImageTarName"
# fi
echo "【下载】 - 需要处理的压缩包名称为 => $ImageTarName"
echo "【下载】 - 开始下载 ↓"
wget "$OSS_URL$ImageTarName"
if [[ $? -ne 0 ]]; then
echo "【下载】- 下载镜像失败!退出!"
return
fi
echo ""
echo "【下载】 - 开始解压压缩包 "
docker load <"${ImageTarName}"
echo ""
get_Internal_IP
echo "【下载】 - 开始上传镜像到本地的镜像仓库中 => $InnerIPv4:8033 "
custom_prefix="$InnerIPv4:8033/cmii/"
echo ""
get_image_name_from_tar
echo "【下载】 - 解析得到的 私有镜像地址为 => $custom_prefix$UploadImageName"
docker tag "$CmiiImagePrefix${UploadImageName}" "$custom_prefix$UploadImageName"
echo "【下载】 - 开始上传镜像到私有仓库 ↓"
docker login -u admin -p V2ryStr@ngPss "$InnerIPv4:8033"
echo ""
echo "【下载】 - 开始推送到私有仓库! "
docker push "$custom_prefix$UploadImageName"
echo ""
echo ""
echo ""
echo "【更新】-开始更新镜像名称!"
harbor_host="$InnerIPv4:8033"
parse_args $ImageTarName
update_image_tag
}
if [[ $NeedUploadFolder == 1 ]]; then
# 上传的是一个目录
echo "【上传】 - 上传的文件目录为 => ${ImageListName}"
currentDate=$(date +'%Y-%m-%d')
random_number=$((RANDOM % 900 + 100))
tar_image_txt_file="$currentDate-$random_number.txt"
echo "【上传】 - 复制文件目录为临时文件 => $tar_image_txt_file"
touch $tar_image_txt_file
echo ""
echo ""
while IFS= read -r i; do
[ -z "${i}" ] && continue
UploadImageName=${i}
Download_Compress_UploadOss || return ?
# 写入压缩文件名称
echo "$ImageTarName" >>"$tar_image_txt_file"
echo "-------------------------------------------------"
done <"${ImageListName}"
echo ""
echo "【上传】 - 上传压缩文件名称列表至OSS中 "
mc cp ./"$tar_image_txt_file" demo/cmlc-installation/tmp/
echo "【上传】 - 上传OSS成功 => $(mc ls demo/cmlc-installation/tmp/ | grep "${tar_image_txt_file}")"
echo ""
echo "【上传】 - 请在目标Master主机执行如下命令 ↓↓↓↓↓↓"
echo ""
echo ""
echo "source <(curl -sL https://b2.107421.xyz/image-sync.sh) -fd "$OSS_URL$tar_image_txt_file""
echo ""
echo ""
elif [[ $NeedUploadFolder == 2 ]]; then
# file download
echo "【下载】- 需要下载的压缩列表文件为 => $ImageListName"
wget ${ImageListName}
tar_image_txt_file=$(echo ${ImageListName} | cut -d"/" -f6)
image_count=0
while IFS= read -r i; do
[ -z "${i}" ] && continue
ImageTarName=${i}
Download_Load_Tag_UploadHarbor_Update
image_count="$(_math "$image_count" + 1)"
echo "-------------------------------------------------"
done <"${tar_image_txt_file}"
echo ""
echo "【下载】 - 请等待流程结束 ↓"
_sleep_c="500"
for (( i=1; i<$image_count; i++ )) ; do
_sleep_c="$(_math "$_sleep_c" + 500)"
done
echo "【下载】 - 共有 【 $image_count 】个镜像, 等待上传结束 => $_sleep_c"
while [ "$_sleep_c" -ge "0" ]; do
printf "\r \r"
printf -- "%b" "$_sleep_c"
_sleep_c="$(_math "$_sleep_c" - 1)"
sleep 1
done
printf "\r"
fi
if [[ $IsUpload == 1 ]]; then
# upload a image
Download_Compress_UploadOss || return ?
echo "【上传】 - 请在目标Master主机执行如下命令 ↓↓↓↓↓↓"
echo ""
echo ""
echo "source <(curl -sL https://b2.107421.xyz/image-sync.sh) -d $ImageTarName"
echo ""
echo ""
Client_Harbor_Address="$Custom_Client_Harbor/cmii/$ImageName:$ImageTag"
echo "【上传】 - 手动命令执行如下, 目标镜像全程地址为 => $Client_Harbor_Address"
echo ""
echo "wget $OSS_URL$ImageTarName && docker load < $ImageTarName && docker tag ${UploadImageName} $Client_Harbor_Address && docker push $Client_Harbor_Address"
echo ""
echo ""
elif [[ $IsUpload == 2 ]];then
# download a image
Download_Load_Tag_UploadHarbor_Update
echo "【下载】 - 请等待流程结束 ↓"
_sleep_c="500"
while [ "$_sleep_c" -ge "0" ]; do
printf "\r \r"
printf -- "%b" "$_sleep_c"
_sleep_c="$(_math "$_sleep_c" - 1)"
sleep 1
done
printf "\r"
fi

View File

@@ -0,0 +1,22 @@
rancher/mirrored-coreos-etcd:v3.5.12
rancher/rke-tools:v0.1.114
rancher/mirrored-k8s-dns-kube-dns:1.23.0
rancher/mirrored-k8s-dns-dnsmasq-nanny:1.23.0
rancher/mirrored-k8s-dns-sidecar:1.23.0
rancher/mirrored-cluster-proportional-autoscaler:v1.9.0
rancher/mirrored-coredns-coredns:1.11.1
rancher/mirrored-cluster-proportional-autoscaler:v1.9.0
rancher/mirrored-k8s-dns-node-cache:1.23.0
rancher/hyperkube:v1.30.14-rancher1
rancher/mirrored-flannel-flannel:v0.25.1
rancher/flannel-cni:v1.4.1-rancher1
rancher/mirrored-calico-node:v3.28.1
rancher/calico-cni:v3.28.1-rancher1
rancher/mirrored-calico-kube-controllers:v3.28.1
rancher/mirrored-calico-ctl:v3.28.1
rancher/mirrored-calico-pod2daemon-flexvol:v3.28.1
rancher/mirrored-pause:3.7
rancher/nginx-ingress-controller:nginx-1.11.5-rancher1
rancher/mirrored-nginx-ingress-controller-defaultbackend:1.5-rancher2
rancher/mirrored-ingress-nginx-kube-webhook-certgen:v1.5.2
rancher/mirrored-metrics-server:v0.7.1

View File

@@ -0,0 +1,13 @@
bitnamilegacy/redis:6.2.14-debian-11-r19
bitnamilegacy/redis:7.4.3-debian-12-r0
bitnamilegacy/mysql:8.1.0-debian-11-r42
bitnamilegacy/os-shell:12-debian-12-r51
bitnamilegacy/rabbitmq:3.13.7-debian-12-r5
ossrs/srs:v5.0.195
emqx/emqx:5.8.8
bitnamilegacy/influxdb:2.7.11-debian-12-r19
minio/minio:RELEASE.2023-06-02T23-17-26Z
kubernetesui/dashboard:v2.7.0
kubernetesui/metrics-scraper:v1.0.9
dyrnq/nfs-subdir-external-provisioner:v4.0.2
nginx:1.28.2

View File

@@ -0,0 +1,29 @@
我现在需要有一个镜像下载的脚本,有如下的要求
1. 通过参数传递docker镜像的文件 txt
1. docker镜像名文件约定为每行代表一个镜像的全名称
2. 脚本需要依次读取txt文件中的镜像名
3. 脚本具备三大类的功能
1. 下载镜像
2. 压缩镜像
3. 重新打包镜像,上传镜像
4. 下载镜像
1. 可以指定下载的CPU架构下载成功之后 需要inpsect提示镜像的架构
2. 可以附加下载的镜像加速前缀,如果附带 下载成功之后需要重新Tag为txt中的镜像名
3. 需要总结提示,下载失败的镜像
5. 压缩镜像
1. 需要首先判定每个镜像是否全部存在
1. 如果全部存在,则继续执行下一步
2. 如果存在不全,则退出脚本给出提示,显示所有缺失的镜像
3. 同样需要检测镜像的CPU架构是否正确
4. 可以通过--force强行跳过检查
2. 可以指定将每个镜像单独压缩为tar.gz文件
3. 可以指定将所有镜像打包为一个tar.gz文件
4. 默认为统一压缩
5. 压缩镜像需要使用多线程压缩充分利用CPU的性能
6. 重新打包镜像,上传镜像
1. 指定目标Harbor的地址
2. Harbor地址为 IP:PORT
3. Harbor的用户名和密码
4. Harbor的用户名 密码 PORT都有默认值可以写入脚本中

View File

@@ -0,0 +1,167 @@
#!/bin/bash
all_image_list_txt="all-cmii-image-list.txt" # 需要修改版本
gzip_image_list_txt="all-gzip-image-list.txt" # 一般不需要修改
oss_prefix_url="https://oss.demo.uavcmlc.com/cmlc-installation"
local_gzip_path="/var/lib/docker/wdd/octopus_image/"
DockerRegisterDomain="harbor.wdd.io:8033" # 需要根据实际修改
HarborAdminPass=Superboge.123 # 需要跟第一脚本中的密码保持一致
print_green() {
echo -e "\033[32m${1}\033[0m"
echo ""
}
print_red() {
echo -e "\033[31m${1}\033[0m"
echo ""
}
Download_Load_Tag_Upload() {
print_green "[DLTU] - start !"
while [[ $# -gt 0 ]]; do
case "$1" in
rke)
# print_green "download rke "
local_gzip_path="$local_gzip_path/rke"
mkdir -p ${local_gzip_path}
oss_prefix_url="$oss_prefix_url/rke13014/"
dltu
shift # past argument
;;
middle)
local_gzip_path="$local_gzip_path/middle_supervisor"
mkdir -p $local_gzip_path
oss_prefix_url="$oss_prefix_url/middle/"
dltu
shift # past argument
;;
cmii)
local_gzip_path="$local_gzip_path/cmii_uas_23"
mkdir -p $local_gzip_path
oss_prefix_url="$oss_prefix_url/uavms-2.0/"
dltu
shift # past argument
;;
*)
# unknown option
print_red "bad arguments"
;;
esac
done
}
dltu() {
print_green "download all image name list and gzip file list!"
cd $local_gzip_path || exit
rm $all_image_list_txt
rm $gzip_image_list_txt
wget "$oss_prefix_url$all_image_list_txt"
wget "$oss_prefix_url$gzip_image_list_txt"
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
echo ""
while IFS= read -r i; do
[ -z "${i}" ] && continue
echo "download gzip file =>: $oss_prefix_url${i}"
if wget "$oss_prefix_url${i}" >/dev/null 2>&1; then
echo "Gzip file download success : ${i}"
image_full_name=$(docker load -i ${i} | head -n1 |awk -F': ' '{print $2}')
app_name=$(echo "$image_full_name" | sed 's|.*/||g')
echo "extract short name is $app_name"
if echo $image_full_name | grep -q "rancher"
then
print_green "tag image to => $DockerRegisterDomain/rancher/$app_name"
docker tag ${image_full_name} $DockerRegisterDomain/rancher/$app_name
docker push $DockerRegisterDomain/rancher/$app_name
else
print_green "tag image to => $DockerRegisterDomain/cmii/$app_name"
docker tag ${image_full_name} $DockerRegisterDomain/cmii/$app_name
docker push $DockerRegisterDomain/cmii/$app_name
fi
else
print_red "Gzip file download FAILED : ${i}"
fi
echo "-------------------------------------------------"
done <"${gzip_image_list_txt}"
shift
}
Load_Tag_Upload(){
print_green "[LTU] - start to load image from offline !"
while [[ $# -gt 0 ]]; do
case "$1" in
rke)
# print_green "download rke "
local_gzip_path="$local_gzip_path/rke13014"
mkdir -p ${local_gzip_path}
oss_prefix_url="$oss_prefix_url/rke/"
ltu
shift # past argument
;;
middle)
local_gzip_path="$local_gzip_path/middle_supervisor"
mkdir -p $local_gzip_path
oss_prefix_url="$oss_prefix_url/middle/"
ltu
shift # past argument
;;
cmii)
local_gzip_path="$local_gzip_path/cmii_uas_23"
mkdir -p $local_gzip_path
oss_prefix_url="$oss_prefix_url/cmii/"
ltu
shift # past argument
;;
*)
# unknown option
print_red "bad arguments"
;;
esac
done
}
ltu(){
all_file_list=$(find $local_gzip_path -type f -name "*.tar.gz")
for file in $all_file_list; do
echo "offline gzip file is => : $file"
image_full_name=$(docker load -i ${file} | head -n1 |awk -F': ' '{print $2}')
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
app_name=$(echo "$image_full_name" | sed 's|.*/||g')
echo "extract short name is $app_name"
if echo $image_full_name | grep -q "rancher"
then
print_green "tag image to => $DockerRegisterDomain/rancher/$app_name"
docker tag ${image_full_name} $DockerRegisterDomain/rancher/$app_name
docker push $DockerRegisterDomain/rancher/$app_name
else
print_green "tag image to => $DockerRegisterDomain/cmii/$app_name"
docker tag ${image_full_name} $DockerRegisterDomain/cmii/$app_name
docker push $DockerRegisterDomain/cmii/$app_name
fi
done
}
test(){
app_name=$(echo "nginx:latest" | sed 's|.*/||g')
echo "extract short name is $app_name"
}
# test
#Download_Load_Tag_Upload "rke"
Load_Tag_Upload "rke"

View File

@@ -0,0 +1,15 @@
# https://dl.min.io/client/mc/release/windows-amd64/mc.exe
& "C:\Users\wddsh\Downloads\mc.exe" alias set uav-demo https://oss.demo.uavcmlc.com cmii B#923fC7mk
& "C:\Users\wddsh\Downloads\mc.exe" ls uav-demo/cmlc-installation/cmii_uas_23_tmp/ | ForEach-Object {
$item=($_.Split()[-1])
Write-Host "start to download $item "
& "C:\Users\wddsh\Downloads\mc.exe" get uav-demo/cmlc-installation/cmii_uas_23_tmp/$item "D:\CmiiDeployOffline\cmii_uas_23\"
Write-Host ""
}

View File

@@ -0,0 +1,134 @@
<#
.SYNOPSIS
MinIO 免 Alias 批量下载脚本 (强力兼容特殊字符版)。
.DESCRIPTION
1. 采用临时配置目录 (--config-dir),彻底解决密码中 #、@、$ 等符号导致的 URL 解析错误。
2. 自动清理:脚本结束或异常退出时,会自动销毁临时生成的凭证文件。
3. 路径追踪:支持递归下载、进度显示及失败文件自动清理。
#>
# =====================================================================
# 1. 解决中文编码问题
# =====================================================================
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
$OutputEncoding = [System.Text.Encoding]::UTF8
# =====================================================================
# 2. 变量配置区 (请按实际情况修改)
# =====================================================================
# MinIO 客户端 (mc.exe) 的全路径
$McExePath = "C:\Users\zzy\Desktop\cmii\mc.exe"
# 远端服务器信息
$MinioEndpoint = "https://oss.demo.uavcmlc.com"
$MinioUsername = "cmii"
# 注意:密码务必使用单引号 '' 包裹,防止 PowerShell 误解析其中的特殊符号
$MinioPassword = 'B#923fC7mk'
# 远端桶及目录 (需以 / 结尾)
$TargetBucketPath = "cmlc-installation/rke13014/"
# 本地保存全路径 (需以 \ 结尾)
$LocalSavePath = "C:\Users\zzy\Desktop\cmii\rke13014\"
# =====================================================================
# 3. 初始化临时环境 (避开环境变量 URL 解析 Bug)
# =====================================================================
Clear-Host
Write-Host "正在初始化安全传输环境..." -ForegroundColor Cyan
# 在系统临时目录下创建一个独立的 mc 配置文件夹
$TempConfigDir = Join-Path -Path $env:TEMP -ChildPath ("mc_tmp_" + [Guid]::NewGuid().ToString().Substring(0,8))
if (-not (Test-Path $TempConfigDir)) { New-Item -ItemType Directory -Path $TempConfigDir | Out-Null }
# 定义一个内部使用的临时 Alias 名称
$TmpAlias = "InternalTmp"
# =====================================================================
# 4. 建立连接 (使用 --config-dir 隔离配置)
# =====================================================================
Write-Host "正在建立与远端服务器的验证连接..." -ForegroundColor DarkGray
# 使用 alias set 命令,这种方式对密码中的 # 号等字符支持最稳健
& $McExePath --config-dir $TempConfigDir alias set $TmpAlias $MinioEndpoint $MinioUsername $MinioPassword --insecure | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Error "验证失败!请检查账密(特别是特殊字符)或网络地址。"
Remove-Item -Path $TempConfigDir -Recurse -Force -ErrorAction SilentlyContinue
exit
}
# 拼接 mc 识别路径
$RemoteDir = "$TmpAlias/$TargetBucketPath"
# 检查本地目录
if (-not (Test-Path $LocalSavePath)) {
New-Item -ItemType Directory -Path $LocalSavePath -Force | Out-Null
}
# =====================================================================
# 5. 安全获取文件列表
# =====================================================================
Write-Host "正在扫描远端文件..." -ForegroundColor Cyan
$jsonOutput = & $McExePath --config-dir $TempConfigDir ls --recursive --json --insecure $RemoteDir 2>&1
$fileList = @()
foreach ($line in $jsonOutput) {
if ([string]::IsNullOrWhiteSpace($line) -or $line -match "mc: ") { continue }
try {
$obj = $line | ConvertFrom-Json -ErrorAction Stop
if ($obj.type -eq "file") { $fileList += $obj }
} catch {
# 忽略非 JSON 的提示信息
}
}
$totalFiles = $fileList.Count
if ($totalFiles -eq 0) {
Write-Host "未发现可下载文件,请检查桶路径是否正确: $TargetBucketPath" -ForegroundColor Yellow
Remove-Item -Path $TempConfigDir -Recurse -Force -ErrorAction SilentlyContinue
exit
}
# =====================================================================
# 6. 循环下载与断点清理
# =====================================================================
Write-Host "共扫描到 $totalFiles 个文件,开始下载任务..." -ForegroundColor Green
$currentIndex = 0
foreach ($file in $fileList) {
$currentIndex++
$relPath = $file.key
$remoteFile = "$RemoteDir$relPath"
# 路径转换
$winRelPath = $relPath -replace '/', '\'
$localFile = Join-Path -Path $LocalSavePath -ChildPath $winRelPath
# 创建子目录
$parentDir = Split-Path $localFile -Parent
if (-not (Test-Path $parentDir)) { New-Item -ItemType Directory -Path $parentDir -Force | Out-Null }
Write-Host "[$currentIndex/$totalFiles] 正在下载: $relPath" -ForegroundColor Yellow
# 执行下载
& $McExePath --config-dir $TempConfigDir cp --insecure $remoteFile $localFile
if ($LASTEXITCODE -ne 0) {
Write-Host " [失败] 下载被中断。" -ForegroundColor Red
if (Test-Path $localFile) {
Write-Host " [清理] 删除不完整的临时文件: $localFile" -ForegroundColor DarkYellow
Remove-Item $localFile -Force
}
} else {
Write-Host " [完成]" -ForegroundColor Green
}
}
# =====================================================================
# 7. 彻底清理临时凭证
# =====================================================================
Write-Host "`n任务结束,正在销毁临时安全凭证..." -ForegroundColor Cyan
Remove-Item -Path $TempConfigDir -Recurse -Force -ErrorAction SilentlyContinue
Write-Host "脚本执行完毕。" -ForegroundColor White

View File

@@ -0,0 +1,16 @@
你是一名优秀的windows powershell专家你非常善于使用powershell和minio client的工具
## 注意事项
1. powershell的执行权限
2. 中文编码问题
3. 脚本中需要使用全路径,避免环境变量的问题
4. ps脚本使用变量区的方式写入固定的变量不使用参数传递
## 实现的功能
1. 从特定的minio的远端地址+目录下载其中的每一个内容
2. 支持进度追踪,如果下载失败,需要删除下载中断的文件
3. minio客户端需要指定全路径
# 仅对当前用户放开执行权限(推荐,较安全)
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

View File

@@ -0,0 +1,23 @@
#!/bin/bash
gzip_image_list_txt="all-gzip-image-list.txt" # 一般不需要修改
oss_prefix_url="https://oss.demo.uavcmlc.com/cmlc-installation"
local_gzip_path="/root/octopus-image"
local_gzip_path="$local_gzip_path/6.1.1"
mkdir -p $local_gzip_path
oss_prefix_url="$oss_prefix_url/6.1.1/"
cd $local_gzip_path || exit
wget "$oss_prefix_url$gzip_image_list_txt"
echo ""
while IFS= read -r i; do
[ -z "${i}" ] && continue
echo "download gzip file =>: $oss_prefix_url${i}"
if wget "$oss_prefix_url${i}" >/dev/null 2>&1; then
echo "download ok !"
echo ""
fi
done <"${gzip_image_list_txt}"

View File

@@ -0,0 +1,25 @@
#!/bin/bash
image_name_prefix_list=(harbor.cdcyy.com.cn)
for (( i=1; i<=100; i++ ))
do
echo $i
for image_name_prefix in "${image_name_prefix_list[@]}"
do
content=$(docker image ls | grep "${image_name_prefix}" | head -n1)
if [ ! "$content" == "" ]; then
echo "$content"
echo "$(echo $content | awk '{print$1}'):$(echo $content | awk '{print$2}')"
if [ "$(echo $content | awk '{print$2}')" == "<none*" ]; then
continue
fi
docker image rm "$(echo $content | awk '{print$1}'):$(echo $content | awk '{print$2}')"
fi
done
done
echo "y
" | docker image prune

View File

@@ -0,0 +1,68 @@
#!/bin/bash
harbor_host=172.31.2.7:8033/admin
namespace=szgz
app_name=""
new_tag=""
upload_image_to_harbor(){
if [ "$app_name" == "" ]; then
echo "app name null exit!"
exit 233
fi
if ! docker load < "$1"; then
echo "docker load error !"
fi
docker tag "harbor.cdcyy.com.cn/cmii/$app_name:$new_tag" "$harbor_host/cmii/$app_name:$new_tag"
echo ""
echo ""
echo "upload_image_to_harbor - start to push to => $harbor_host/cmii/$app_name:$new_tag"
docker login -u admin -p V2ryStr@ngPss $harbor_host
docker push "$harbor_host/cmii/$app_name:$new_tag"
echo ""
echo ""
}
parse_args(){
if [ "$1" == "" ]; then
echo "no zip file in error!"
exit 233
fi
local image_name="$1"
# cmii-uav-surveillance=5.2.0-27031-cqga=2024-03-04=573.tar.gz
app_name=$(echo $image_name | cut -d "=" -f1)
new_tag=$(echo $image_name | cut -d "=" -f2)
}
update_image_tag(){
if [ "$new_tag" == "" ]; then
echo "new tag error!"
exit 233
fi
local image_prefix=$(kubectl -n ${namespace} get deployment "${app_name}" -o=jsonpath='{.spec.template.spec.containers[*].image}' | cut -d":" -f1)
echo "image grep is => ${image_prefix}"
echo "start to update ${namespace} ${app_name} to ${new_tag} !"
echo ""
kubectl -n ${namespace} patch deployment "${app_name}" -p "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"${app_name}\",\"image\": \"${harbor_host}/cmii/$app_name:${new_tag}\"}]}}}}"
echo ""
echo "start to wait for 3 seconds!"
sleep 3
local image_new=$(kubectl -n ${namespace} get deployment "${app_name}" -o=jsonpath='{.spec.template.spec.containers[*].image}')
echo ""
echo "new image are => $image_new"
echo ""
}
main(){
parse_args "$1"
upload_image_to_harbor "$1"
update_image_tag
}
main "$@"

View File

@@ -0,0 +1,154 @@
#!/usr/bin/env bash
### 需要修改以下的内容 ###
#### 需要修改以下的内容 ###
#### 需要修改以下的内容 ###
cmlc_app_image_list="szga-0711.txt" # 需要修改版本
rancher_image_list="kubernetes-images-1.30.14.txt" # 一般不需要修改
middleware_image_list="middleware-images.txt" # 一般不需要修改
DockerRegisterDomain="192.168.5.41:8033" # 需要根据实际修改
# DockerRegisterDomain="172.31.2.7:8033/admin" # 需要根据实际修改
HarborAdminPass=V2ryStr@ngPss # 需要跟第一脚本中的密码保持一致
#### 需要修改以上的内容 ###
#### 需要修改以上的内容 ###
#### 需要修改以上的内容 ###
downloadAllNeededImages() {
while [[ $# > 0 ]]; do
pulled=""
while IFS= read -r i; do
[ -z "${i}" ] && continue
echo "开始下载:${i}"
if /usr/bin/docker pull --platform linux/arm64 "${i}" >/dev/null 2>&1; then
echo "Image pull success: ${i}"
# 增加检查,镜像 的架构
/usr/bin/docker image inspect ${i} | grep Architecture
pulled="${pulled} ${i}"
else
if /usr/bin/docker inspect "${i}" >/dev/null 2>&1; then
pulled="${pulled} ${i}"
else
echo "Image pull failed: ${i}"
fi
fi
echo "-------------------------------------------------"
done <"${1}"
shift
done
}
downloadAllNeededImagesAndCompress() {
while [[ $# > 0 ]]; do
pulled=""
while IFS= read -r i; do
[ -z "${i}" ] && continue
echo "开始下载:${i}"
if /usr/bin/docker pull --platform linux/arm64 "${i}" >/dev/null 2>&1; then
echo "Image pull success: ${i}"
# 增加检查,镜像 的架构
/usr/bin/docker image inspect ${i} | grep Architecture
pulled="${pulled} ${i}"
else
if /usr/bin/docker inspect "${i}" >/dev/null 2>&1; then
pulled="${pulled} ${i}"
else
echo "Image pull failed: ${i}"
fi
fi
echo "-------------------------------------------------"
done <"${1}"
compressPacName="$(echo ${1} | cut -d"." -f1).tar.gz"
echo "Creating ${compressPacName} with $(echo ${pulled} | wc -w | tr -d '[:space:]') images"
/usr/bin/docker save $(echo ${pulled}) | gzip --stdout > ${compressPacName}
shift
done
echo "已经完成打包工作!"
}
pushRKEImageToHarbor(){
linux_images=()
while IFS= read -r i; do
[ -z "${i}" ] && continue
linux_images+=("${i}");
done < "${rancher_image_list}"
/usr/bin/docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
for i in "${linux_images[@]}"; do
[ -z "${i}" ] && continue
case $i in
*/*)
image_name="${DockerRegisterDomain}/${i}"
;;
*)
image_name="${DockerRegisterDomain}/rancher/${i}"
;;
esac
echo "开始镜像至私有仓库推送:${image_name}"
/usr/bin/docker tag "${i}" "${image_name}"
/usr/bin/docker push "${image_name}"
echo "-------------------------------------------------"
done
}
pushCMLCAPPImageToHarbor(){
app_images=()
while IFS= read -r i; do
[ -z "${i}" ] && continue
app_images+=("${i}");
done < "${cmlc_app_image_list}"
/usr/bin/docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
for app in "${app_images[@]}"; do
[ -z "${app}" ] && continue
image_name="${DockerRegisterDomain}/$(echo ${app} | cut -d"/" -f2-8)"
echo "开始镜像至私有仓库推送:${image_name}"
/usr/bin/docker tag "${app}" "${image_name}"
/usr/bin/docker push "${image_name}"
echo "-------------------------------------------------"
done
}
pushMiddlewareImageToHarbor(){
middleware_image=()
while IFS= read -r i; do
[ -z "${i}" ] && continue
middleware_image+=("${i}");
done < "${middleware_image_list}"
/usr/bin/docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
for app in "${middleware_image[@]}"; do
[ -z "${app}" ] && continue
case ${app} in
*/*/*)
image_name="${DockerRegisterDomain}/cmii/$(echo "${app}" | cut -d"/" -f3-8)"
;;
*/*)
image_name="${DockerRegisterDomain}/cmii/$(echo "${app}" | cut -d"/" -f2-8)"
;;
esac
echo "开始镜像至私有仓库推送:${image_name}"
/usr/bin/docker tag "${app}" "${image_name}"
/usr/bin/docker push "${image_name}"
echo "-------------------------------------------------"
done
}
downloadAllNeededImagesAndCompress "${middleware_image_list}"
#downloadAllNeededImages "${rancher_image_list}"
#pushRKEImageToHarbor
#pushCMLCAPPImageToHarbor
# pushMiddlewareImageToHarbor

View File

@@ -0,0 +1,154 @@
#!/usr/bin/env bash
### 需要修改以下的内容 ###
#### 需要修改以下的内容 ###
#### 需要修改以下的内容 ###
cmlc_app_image_list="szga-0711.txt" # 需要修改版本
rancher_image_list="kubernetes-images-2.5.7-1.20.4.txt" # 一般不需要修改
middleware_image_list="middleware-images.txt" # 一般不需要修改
#DockerRegisterDomain="20.47.129.116:8033" # 需要根据实际修改
DockerRegisterDomain="172.10.125.92:8033" # 需要根据实际修改
HarborAdminPass=V2ryStr@ngPss # 需要跟第一脚本中的密码保持一致
#### 需要修改以上的内容 ###
#### 需要修改以上的内容 ###
#### 需要修改以上的内容 ###
downloadAllNeededImages() {
while [[ $# > 0 ]]; do
pulled=""
while IFS= read -r i; do
[ -z "${i}" ] && continue
echo "开始下载:${i}"
if docker pull "${i}" >/dev/null 2>&1; then
echo "Image pull success: ${i}"
# 增加检查,镜像 的架构
docker image inspect ${i} | grep Architecture
pulled="${pulled} ${i}"
else
if docker inspect "${i}" >/dev/null 2>&1; then
pulled="${pulled} ${i}"
else
echo "Image pull failed: ${i}"
fi
fi
echo "-------------------------------------------------"
done <"${1}"
shift
done
}
downloadAllNeededImagesAndCompress() {
while [[ $# > 0 ]]; do
pulled=""
while IFS= read -r i; do
[ -z "${i}" ] && continue
echo "开始下载:${i}"
if docker pull "${i}" >/dev/null 2>&1; then
echo "Image pull success: ${i}"
# 增加检查,镜像 的架构
docker image inspect ${i} | grep Architecture
pulled="${pulled} ${i}"
else
if docker inspect "${i}" >/dev/null 2>&1; then
pulled="${pulled} ${i}"
else
echo "Image pull failed: ${i}"
fi
fi
echo "-------------------------------------------------"
done <"${1}"
compressPacName="$(echo ${1} | cut -d"." -f1).tar.gz"
echo "Creating ${compressPacName} with $(echo ${pulled} | wc -w | tr -d '[:space:]') images"
docker save $(echo ${pulled}) | gzip --stdout > ${compressPacName}
shift
done
echo "已经完成打包工作!"
}
pushRKEImageToHarbor(){
linux_images=()
while IFS= read -r i; do
[ -z "${i}" ] && continue
linux_images+=("${i}");
done < "${rancher_image_list}"
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
for i in "${linux_images[@]}"; do
[ -z "${i}" ] && continue
case $i in
*/*)
image_name="${DockerRegisterDomain}/${i}"
;;
*)
image_name="${DockerRegisterDomain}/rancher/${i}"
;;
esac
echo "开始镜像至私有仓库推送:${image_name}"
docker tag "${i}" "${image_name}"
docker push "${image_name}"
echo "-------------------------------------------------"
done
}
pushCMLCAPPImageToHarbor(){
app_images=()
while IFS= read -r i; do
[ -z "${i}" ] && continue
app_images+=("${i}");
done < "${cmlc_app_image_list}"
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
for app in "${app_images[@]}"; do
[ -z "${app}" ] && continue
image_name="${DockerRegisterDomain}/$(echo ${app} | cut -d"/" -f2-8)"
echo "开始镜像至私有仓库推送:${image_name}"
docker tag "${app}" "${image_name}"
docker push "${image_name}"
echo "-------------------------------------------------"
done
}
pushMiddlewareImageToHarbor(){
middleware_image=()
while IFS= read -r i; do
[ -z "${i}" ] && continue
middleware_image+=("${i}");
done < "${middleware_image_list}"
docker login -u admin -p ${HarborAdminPass} ${DockerRegisterDomain}
for app in "${middleware_image[@]}"; do
[ -z "${app}" ] && continue
case ${app} in
*/*/*)
image_name="${DockerRegisterDomain}/cmii/$(echo "${app}" | cut -d"/" -f3-8)"
;;
*/*)
image_name="${DockerRegisterDomain}/cmii/$(echo "${app}" | cut -d"/" -f2-8)"
;;
esac
echo "开始镜像至私有仓库推送:${image_name}"
docker tag "${app}" "${image_name}"
docker push "${image_name}"
echo "-------------------------------------------------"
done
}
downloadAllNeededImagesAndCompress "${middleware_image_list}"
#downloadAllNeededImages "${rancher_image_list}"
#pushRKEImageToHarbor
#pushCMLCAPPImageToHarbor
#pushMiddlewareImageToHarbor

View File

@@ -0,0 +1,69 @@
function DownloadFileInChunks {
param (
[string]$url,
[string]$destinationFile,
[int]$chunkSizeGB = 1
)
# 将 GB 转换为字节
$chunkSize = $chunkSizeGB * 1024 * 1024 * 1024
# 获取文件的总大小
$response = Invoke-WebRequest -Uri $url -Method Head
$totalSize = [long]$response.Headers["Content-Length"]
# 计算分段数量
$chunks = [math]::Ceiling($totalSize / $chunkSize)
# 下载每一段
for ($i = 0; $i -lt $chunks; $i++) {
$start = $i * $chunkSize
$end = [math]::Min($start + $chunkSize - 1, $totalSize - 1)
$headers = @{
"Range" = "bytes=$start-$end"
}
$chunkResponse = Invoke-WebRequest -Uri $url -Headers $headers -Method Get
$chunkData = $chunkResponse.Content
# 以追加模式写入文件
[System.IO.File]::WriteAllBytes($destinationFile, $chunkData)
}
Write-Host "dowonload ok"
}
# 指定文件路径
$filePath = "D:\CmiiDeployOffline\ZheJiangErJiPingTai\all-gzip-image-list.txt"
# 指定下载的目标目录
$destinationFolder = "D:\CmiiDeployOffline\ZheJiangErJiPingTai"
$oss_prefix_url="https://oss.demo.uavcmlc.com/cmlc-installation/6.1.1/"
# 创建目标目录(如果不存在)
#if (-not (Test-Path $destinationFolder)) {
# New-Item -ItemType Directory -Path $destinationFolder
#}
#Write-Host "[DLTU] - 开始下载镜像压缩文件"
Write-Host ""
# 读取文件并下载每一行的 URL
Get-Content $filePath | ForEach-Object {
$url = $_
Write-Host "start to download $oss_prefix_url$url"
$fileName = Join-Path $destinationFolder $url
Write-Host $fileName
DownloadFileInChunks -url $oss_prefix_url$url -destinationFile $fileName -chunkSizeGB 0.1
# Invoke-WebRequest -Uri $oss_prefix_url$url -OutFile $fileName
Write-Host ""
}

View File

@@ -0,0 +1,66 @@
golang版本的代码如下
func ImageFullNameToScriptGzipName(imageName string) (scriptGzipName string) {
// harbor.cdcyy.cn/cmii/cmii-uav-platform:6.2.0-gz-121101-arm ==> cmii-uav-user=6.2.0-gz-121101-arm=2025-12-11=968.tar.gz
// nginx:latest ==> nginx=latest=2025-12-11=968.tar.gz
// bitnami/minio:2022.5.4 ==> minio=2022.5.4=2025-12-11=968.tar.gz
// simonrupf/chronyd:0.4.3 ==> chronyd=0.4.3=2025-12-11=968.tar.gz
// ossrs/srs:v5.0.1 ==> srs=v5.0.1=2025-12-11=968.tar.gz
// rancher/fleet:v0.3.4 ==> fleet=v0.3.4=2025-12-11=968.tar.gz
// 提取镜像名(去除仓库路径)
var shortName string
if strings.Contains(imageName, "/") {
parts := strings.Split(imageName, "/")
shortName = parts[len(parts)-1] // 获取最后一个部分
} else {
shortName = imageName
}
// 分离镜像名和标签
var name, tag string
if strings.Contains(shortName, ":") {
parts := strings.Split(shortName, ":")
name = parts[0]
tag = parts[1]
} else {
name = shortName
tag = "latest"
}
// 获取当前日期 (YYYY-MM-DD)
currentDate := time.Now().Format("2006-01-02")
// 生成 100-999 的随机数
randomNum := 100 + rand.Intn(900) // rand.Intn(900) 生成 0-899加100得到 100-999
// 组合成最终格式: name=tag=date=random.tar.gz
scriptGzipName = fmt.Sprintf("%s=%s=%s=%d", name, tag, currentDate, randomNum)
return scriptGzipName
}
linux脚本下面的旧的函数如下
get_image_tar_name() {
# harbor.cdcyy.com.cn/cmii/cmii-uav-oauth:4.1.6
ImageName=$(echo $UploadImageName | cut -d ":" -f1 | cut -d"/" -f3)
ImageTag=$(echo $UploadImageName | cut -d ":" -f2)
local currentDate=$(date +'%Y-%m-%d')
local random_number=$((RANDOM % 900 + 100))
ImageTarName="$ImageName=$ImageTag=$currentDate=$random_number.tar.gz"
}
请修改上面的内容golang和shell脚本都需要更新效果应该是统一的
最终镜像的格式应该为
1. harbor.cdcyy.com.cn/cmii/cmii-uav-oauth:4.1.6 => cmii=cmii-uav-oauth=4.1.6=<实际镜像的arch>=YYYY-MM-DD=XXX.tar.gz
2. nginx:latest ==> docker=nginx=latest=<实际镜像的arch>=2025-12-11=968.tar.gz
3. bitnami/minio:2022.5.4 ==> bitnami=minio=2022.5.4=<实际镜像的arch>=2025-12-11=968.tar.gz
4. simonrupf/chronyd:0.4.3 ==> simonrupf=chronyd=0.4.3=<实际镜像的arch>=2025-12-11=968.tar.gz
5. rancher/fleet:v0.3.4 ==> rancher=fleet=<实际镜像的arch>==v0.3.4=2025-12-11=968.tar.gz
<实际镜像的arch>需要查看镜像的详细信息docker inspect命令类似获取

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,767 @@
#!/bin/bash
###############################################################################
# NGINX Installation Script for China Mainland with Mirror Acceleration
###############################################################################
# @author Advanced Bash Shell Engineer
# @version 1.0.0
# @license MIT
# @created 2026-01-19
# @desc Production-grade NGINX installation script with China mirror support
# Supports Ubuntu 18.04/20.04/22.04/24.04 with version pinning
###############################################################################
###############################################################################
# GLOBAL CONSTANTS
###############################################################################
readonly SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")"
readonly SCRIPT_VERSION="1.0.0"
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Color codes for output
readonly COLOR_RED="\033[0;31m"
readonly COLOR_GREEN="\033[0;32m"
readonly COLOR_YELLOW="\033[1;33m"
readonly COLOR_BLUE="\033[0;34m"
readonly COLOR_RESET="\033[0m"
# Log levels
readonly LOG_LEVEL_DEBUG=0
readonly LOG_LEVEL_INFO=1
readonly LOG_LEVEL_WARN=2
readonly LOG_LEVEL_ERROR=3
# Default configuration
readonly DEFAULT_NGINX_VERSION="stable"
readonly DEFAULT_MIRROR="ustc"
readonly SUPPORTED_UBUNTU_VERSIONS=("18.04" "20.04" "22.04" "24.04")
# Mirror configurations (China mainland accelerated sources)
declare -A MIRROR_URLS=(
["aliyun"]="http://mirrors.aliyun.com/nginx"
["tsinghua"]="https://mirrors.tuna.tsinghua.edu.cn/nginx"
["ustc"]="https://mirrors.ustc.edu.cn/nginx/ubuntu"
["official"]="http://nginx.org"
)
declare -A MIRROR_KEY_URLS=(
["aliyun"]="http://mirrors.aliyun.com/nginx/keys/nginx_signing.key"
["tsinghua"]="https://mirrors.tuna.tsinghua.edu.cn/nginx/keys/nginx_signing.key"
["ustc"]="https://mirrors.ustc.edu.cn/nginx/keys/nginx_signing.key"
["official"]="https://nginx.org/keys/nginx_signing.key"
)
# Global variables
CURRENT_LOG_LEVEL="${LOG_LEVEL_INFO}"
NGINX_VERSION="${DEFAULT_NGINX_VERSION}"
MIRROR_SOURCE="${DEFAULT_MIRROR}"
FORCE_REINSTALL=false
DRY_RUN=false
###############################################################################
# ERROR HANDLING & TRAPS
###############################################################################
set -euo pipefail
IFS=$'\n\t'
###
### Cleanup function for graceful exit
### @param none
### @return void
### @require none
###
cleanup() {
local exit_code=$?
if [[ ${exit_code} -ne 0 ]]; then
log_error "脚本退出,错误码: ${exit_code}"
fi
# > Perform cleanup operations if needed
return "${exit_code}"
}
trap cleanup EXIT
trap 'log_error "用户中断脚本执行"; exit 130' INT TERM
###############################################################################
# LOGGING FUNCTIONS
###############################################################################
###
### Core logging function with level-based filtering
### @param log_level integer Log level (0-3)
### @param message string Message to log
### @param color string Color code for output
### @return void
### @require none
###
_log() {
local log_level=$1
local message=$2
local color=$3
local level_name=$4
if [[ ${log_level} -ge ${CURRENT_LOG_LEVEL} ]]; then
local timestamp
timestamp="$(date '+%Y-%m-%d %H:%M:%S')"
echo -e "${color}[${timestamp}] [${level_name}] ${message}${COLOR_RESET}" >&2
fi
}
###
### Debug level logging
### @param message string Debug message
### @return void
### @require none
###
log_debug() {
_log "${LOG_LEVEL_DEBUG}" "$1" "${COLOR_BLUE}" "调试"
}
###
### Info level logging
### @param message string Info message
### @return void
### @require none
###
log_info() {
_log "${LOG_LEVEL_INFO}" "$1" "${COLOR_GREEN}" "信息"
}
###
### Warning level logging
### @param message string Warning message
### @return void
### @require none
###
log_warn() {
_log "${LOG_LEVEL_WARN}" "$1" "${COLOR_YELLOW}" "警告"
}
###
### Error level logging
### @param message string Error message
### @return void
### @require none
###
log_error() {
_log "${LOG_LEVEL_ERROR}" "$1" "${COLOR_RED}" "错误"
}
###############################################################################
# VALIDATION FUNCTIONS
###############################################################################
###
### Check if script is running with root privileges
### @param none
### @return 0 if root, 1 otherwise
### @require none
###
check_root_privileges() {
if [[ ${EUID} -ne 0 ]]; then
log_error "此脚本必须以 root 身份运行,或使用 sudo 执行"
return 1
fi
log_debug "已确认具备 root 权限"
return 0
}
###
### Validate Ubuntu version compatibility
### @param none
### @return 0 if supported, 1 otherwise
### @require lsb_release command
###
validate_ubuntu_version() {
local ubuntu_version
# > Check if lsb_release exists
if ! command -v lsb_release &> /dev/null; then
log_error "未找到 lsb_release 命令,无法识别 Ubuntu 版本。"
return 1
fi
ubuntu_version="$(lsb_release -rs)"
log_debug "检测到 Ubuntu 版本: ${ubuntu_version}"
# > Validate against supported versions
local supported=false
for version in "${SUPPORTED_UBUNTU_VERSIONS[@]}"; do
if [[ "${ubuntu_version}" == "${version}" ]]; then
supported=true
break
fi
done
if [[ "${supported}" == false ]]; then
log_error "Ubuntu ${ubuntu_version} 不受支持。支持的版本: ${SUPPORTED_UBUNTU_VERSIONS[*]}"
return 1
fi
log_info "Ubuntu ${ubuntu_version} 受支持"
return 0
}
###
### Validate mirror source selection
### @param mirror_name string 镜像源 name
### @return 0 if valid, 1 otherwise
### @require none
###
validate_mirror_source() {
local mirror_name=$1
if [[ ! -v MIRROR_URLS["${mirror_name}"] ]]; then
log_error "无效的镜像源: ${mirror_name}"
log_info "可用镜像源: ${!MIRROR_URLS[*]}"
return 1
fi
log_debug "镜像源 '${mirror_name}' 有效"
return 0
}
###
### Check network connectivity to mirror
### @param mirror_url string URL to test
### @return 0 if reachable, 1 otherwise
### @require curl
###
check_mirror_connectivity() {
local mirror_url=$1
local timeout=10
log_debug "正在测试镜像连通性: ${mirror_url}"
if curl -sSf --connect-timeout "${timeout}" --max-time "${timeout}" \
"${mirror_url}" -o /dev/null 2>/dev/null; then
log_debug "镜像 ${mirror_url} 可访问"
return 0
else
log_warn "镜像 ${mirror_url} 不可访问"
return 1
fi
}
###############################################################################
# SYSTEM PREPARATION FUNCTIONS
###############################################################################
###
### Install required system dependencies
### @param none
### @return 0 on success, 1 on failure
### @require apt-get
###
install_dependencies() {
log_info "正在安装系统依赖..."
local dependencies=(
"curl"
"gnupg2"
"ca-certificates"
"lsb-release"
"ubuntu-keyring"
"apt-transport-https"
)
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会安装: ${dependencies[*]}"
return 0
fi
# > Update package index first
if ! apt-get update -qq; then
log_error "更新软件包索引失败"
return 1
fi
# > Install dependencies
if ! apt-get install -y -qq "${dependencies[@]}"; then
log_error "安装依赖失败"
return 1
fi
log_info "依赖安装完成"
return 0
}
###
### Remove existing NGINX installation if present
### @param none
### @return 0 on success or if not installed
### @require apt-get, dpkg
###
remove_existing_nginx() {
log_info "正在检查是否已安装 NGINX..."
if ! dpkg -l | grep -q "^ii.*nginx"; then
log_info "未发现已安装的 NGINX"
return 0
fi
if [[ "${FORCE_REINSTALL}" == false ]]; then
log_warn "NGINX 已安装。如需重装请使用 --force。"
return 1
fi
log_info "正在卸载已安装的 NGINX..."
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会卸载已安装的 NGINX"
return 0
fi
# > Stop NGINX service if running
if systemctl is-active --quiet nginx 2>/dev/null; then
systemctl stop nginx || true
fi
# > Remove NGINX packages
if ! apt-get remove --purge -y nginx nginx-common nginx-full 2>/dev/null; then
log_warn "部分 NGINX 软件包可能未能完全卸载(可忽略)"
fi
# > Clean up configuration files
apt-get autoremove -y -qq || true
log_info "已卸载现有 NGINX"
return 0
}
###############################################################################
# NGINX INSTALLATION FUNCTIONS
###############################################################################
###
### Import NGINX GPG signing key
### @param mirror_name string 镜像源 name
### @return 0 on success, 1 on failure
### @require curl, gpg
###
import_nginx_gpg_key() {
local mirror_name=$1
local key_url="${MIRROR_KEY_URLS[${mirror_name}]}"
local keyring_path="/usr/share/keyrings/nginx-archive-keyring.gpg"
log_info "正在导入 NGINX GPG 签名密钥(来源:${mirror_name}..."
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会从以下地址导入 GPG 密钥: ${key_url}"
return 0
fi
# > Remove old keyring if exists
[[ -f "${keyring_path}" ]] && rm -f "${keyring_path}"
# > Download and import GPG key
if ! curl -fsSL "${key_url}" | gpg --dearmor -o "${keyring_path}" 2>/dev/null; then
log_error "导入 GPG 密钥失败: ${key_url}"
return 1
fi
# > Verify the key was imported correctly
if ! gpg --dry-run --quiet --no-keyring --import --import-options import-show \
"${keyring_path}" &>/dev/null; then
log_error "GPG 密钥校验失败"
return 1
fi
# > Set proper permissions
chmod 644 "${keyring_path}"
log_info "GPG 密钥导入并校验成功"
return 0
}
###
### Configure NGINX APT repository
### @param mirror_name string 镜像源 name
### @return 0 on success, 1 on failure
### @require lsb_release
###
configure_nginx_repository() {
local mirror_name=$1
local mirror_url="${MIRROR_URLS[${mirror_name}]}"
local codename
codename="$(lsb_release -cs)"
local repo_file="/etc/apt/sources.list.d/nginx.list"
local keyring_path="/usr/share/keyrings/nginx-archive-keyring.gpg"
# > 不同镜像源目录结构可能不同:
# > - 官方/部分镜像:.../packages/ubuntu
# > - USTC.../ubuntu
local repo_base
case "${mirror_name}" in
ustc)
repo_base="${mirror_url}"
;;
*)
repo_base="${mirror_url}/packages/ubuntu"
;;
esac
log_info "正在配置 NGINX 软件源Ubuntu ${codename}..."
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会配置软件源deb [signed-by=${keyring_path}] ${repo_base} ${codename} nginx"
return 0
fi
# > Create repository configuration
local repo_config="deb [signed-by=${keyring_path}] ${repo_base} ${codename} nginx"
echo "${repo_config}" | tee "${repo_file}" > /dev/null
log_debug "已生成软件源配置文件:${repo_file}"
log_debug "软件源地址:${repo_base} ${codename}"
log_info "NGINX 软件源配置完成"
return 0
}
###
### Configure APT pinning preferences for NGINX
### @param none
### @return 0 on success
### @require none
###
configure_apt_pinning() {
local pref_file="/etc/apt/preferences.d/99nginx"
log_info "正在配置 APT Pin 优先级..."
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会配置 APT Pin 优先级"
return 0
fi
# > Create pinning configuration for priority
cat > "${pref_file}" <<EOF
Package: *
Pin: origin nginx.org
Pin: release o=nginx
Pin-Priority: 900
EOF
log_debug "APT Pin 配置写入:${pref_file}"
log_info "APT Pin 优先级配置完成"
return 0
}
###
### Install NGINX package
### @param version string NGINX version to install (stable/mainline/specific)
### @return 0 on success, 1 on failure
### @require apt-get
###
install_nginx_package() {
local version=$1
local package_spec="nginx"
log_info "正在安装 NGINX ${version}..."
# > Update package index with new repository
if [[ "${DRY_RUN}" == false ]]; then
if ! apt-get update -qq; then
log_error "更新软件包索引失败"
return 1
fi
fi
# > Handle version specification
if [[ "${version}" != "stable" && "${version}" != "mainline" ]]; then
# > Specific version requested
package_spec="nginx=${version}"
log_debug "安装指定版本:${package_spec}"
else
log_debug "从软件源安装:${version}"
fi
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会安装软件包:${package_spec}"
return 0
fi
# > Install NGINX
if ! DEBIAN_FRONTEND=noninteractive apt-get install -y -qq "${package_spec}"; then
log_error "安装 NGINX 失败"
return 1
fi
log_info "NGINX 安装完成"
return 0
}
###
### Verify NGINX installation
### @param none
### @return 0 on success, 1 on failure
### @require nginx
###
verify_nginx_installation() {
log_info "正在验证 NGINX 安装结果..."
# > Check if nginx binary exists
if ! command -v nginx &> /dev/null; then
log_error "未在 PATH 中找到 nginx 可执行文件"
return 1
fi
# > Get and display version
local nginx_version_output
nginx_version_output="$(nginx -v 2>&1)"
log_info "已安装: ${nginx_version_output}"
# > Test configuration
if ! nginx -t &>/dev/null; then
log_error "NGINX 配置文件校验失败"
return 1
fi
log_info "NGINX 安装验证通过"
return 0
}
###
### Enable and start NGINX service
### @param none
### @return 0 on success, 1 on failure
### @require systemctl
###
enable_nginx_service() {
log_info "正在设置 NGINX 开机自启并启动服务..."
if [[ "${DRY_RUN}" == true ]]; then
log_info "[演练模式] 将会启用并启动 NGINX 服务"
return 0
fi
# > Enable service to start on boot
if ! systemctl enable nginx &>/dev/null; then
log_error "设置 NGINX 开机自启失败"
return 1
fi
# > Start the service
if ! systemctl start nginx; then
log_error "启动 NGINX 服务失败"
return 1
fi
# > Verify service is running
if ! systemctl is-active --quiet nginx; then
log_error "NGINX 服务未处于运行状态"
return 1
fi
log_info "NGINX 服务已启用并启动"
return 0
}
###############################################################################
# MAIN ORCHESTRATION
###############################################################################
###
### Display usage information
### @param none
### @return void
### @require none
###
show_usage() {
cat <<EOF
Usage: ${SCRIPT_NAME} [选项]
NGINX 安装脚本(面向中国大陆镜像加速) v${SCRIPT_VERSION}
选项:
-v, --version VERSION 指定要安装的 NGINX 版本
stable/mainline/1.24.0/...
默认:${DEFAULT_NGINX_VERSION}
-m, --mirror MIRROR 选择镜像源
aliyun/tsinghua/ustc/official
默认:${DEFAULT_MIRROR}
-f, --force 若已安装则强制重装
-d, --dry-run 演练模式:仅展示将执行的操作,不真正执行
--debug 开启调试日志
-h, --help 显示帮助信息
示例:
# 使用默认镜像USTC安装稳定版
sudo ${SCRIPT_NAME}
# 使用清华镜像安装指定版本
sudo ${SCRIPT_NAME} --version 1.24.0 --mirror tsinghua
# 强制重装并开启调试
sudo ${SCRIPT_NAME} --force --debug
# 演练模式预览
sudo ${SCRIPT_NAME} --dry-run
支持的 Ubuntu 版本:
${SUPPORTED_UBUNTU_VERSIONS[*]}
可用镜像源:
${!MIRROR_URLS[*]}
EOF
}
###
### Parse command line arguments
### @param args array Command line arguments
### @return 0 on success, 1 on invalid arguments
### @require none
###
parse_arguments() {
while [[ $# -gt 0 ]]; do
case $1 in
-v|--version)
NGINX_VERSION="$2"
shift 2
;;
-m|--mirror)
MIRROR_SOURCE="$2"
shift 2
;;
-f|--force)
FORCE_REINSTALL=true
shift
;;
-d|--dry-run)
DRY_RUN=true
shift
;;
--debug)
CURRENT_LOG_LEVEL="${LOG_LEVEL_DEBUG}"
shift
;;
-h|--help)
show_usage
exit 0
;;
*)
log_error "未知参数: $1"
show_usage
exit 1
;;
esac
done
return 0
}
###
### Main installation workflow
### @param none
### @return 0 on success, 1 on failure
### @require all functions above
###
main() {
log_info "========================================="
log_info "NGINX 安装脚本 v${SCRIPT_VERSION}"
log_info "========================================="
# > Step 1: Pre-flight checks
log_info "步骤 1/8执行预检查..."
check_root_privileges || return 1
validate_ubuntu_version || return 1
validate_mirror_source "${MIRROR_SOURCE}" || return 1
# > Step 2: Check mirror connectivity
log_info "步骤 2/8检查镜像连通性..."
if ! check_mirror_connectivity "${MIRROR_URLS[${MIRROR_SOURCE}]}"; then
log_warn "主镜像不可用,尝试回退方案..."
# > Fallback to official if mirror fails
if [[ "${MIRROR_SOURCE}" != "official" ]]; then
MIRROR_SOURCE="official"
log_info "已回退到官方源"
fi
fi
# > Step 3: Install dependencies
log_info "步骤 3/8安装依赖..."
install_dependencies || return 1
# > Step 4: Handle existing installation
log_info "步骤 4/8检查已安装版本..."
remove_existing_nginx || return 1
# > Step 5: Import GPG key
log_info "步骤 5/8导入 NGINX GPG 密钥..."
import_nginx_gpg_key "${MIRROR_SOURCE}" || return 1
# > Step 6: Configure repository
log_info "步骤 6/8配置 NGINX 软件源..."
configure_nginx_repository "${MIRROR_SOURCE}" || return 1
configure_apt_pinning || return 1
# > Step 7: Install NGINX
log_info "步骤 7/8安装 NGINX..."
install_nginx_package "${NGINX_VERSION}" || return 1
verify_nginx_installation || return 1
# > Step 8: Enable service
log_info "步骤 8/8启用 NGINX 服务..."
enable_nginx_service || return 1
log_info "========================================="
log_info "✓ NGINX 安装完成!"
log_info "========================================="
if [[ "${DRY_RUN}" == false ]]; then
log_info "服务状态: $(systemctl is-active nginx)"
log_info "NGINX 版本: $(nginx -v 2>&1 | cut -d'/' -f2)"
log_info ""
log_info "常用命令:"
log_info " 启动: sudo systemctl start nginx"
log_info " 停止: sudo systemctl stop nginx"
log_info " 重启: sudo systemctl restart nginx"
log_info " 状态: sudo systemctl status nginx"
log_info " 校验配置: sudo nginx -t"
fi
return 0
}
###############################################################################
# SCRIPT ENTRY POINT
###############################################################################
# ASCII Flow Diagram - Function Call Hierarchy
# ┌─────────────────────────────────────────────────────────────┐
# │ MAIN() │
# └──────────────────┬──────────────────────────────────────────┘
# │
# ┌─────────────┼─────────────┬──────────────┬─────────────┐
# │ │ │ │ │
# ▼ ▼ ▼ ▼ ▼
# ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌────────────┐ ┌─────────┐
# │Pre-flight│ │Install │ │Import │ │Configure │ │Install │
# │Checks │ │Deps │ │GPG Key │ │Repository │ │NGINX │
# └─────────┘ └──────────┘ └─────────┘ └────────────┘ └─────────┘
# │ │ │ │ │
# ├─check_root_privileges │ │ │
# ├─validate_ubuntu_version │ │ │
# └─validate_mirror_source │ │ │
# │ │ │ │
# └─install_dependencies │ │
# │ │ │
# └─import_nginx_gpg_key │
# │ │
# ├─configure_nginx_repository
# └─configure_apt_pinning
# │
# ├─install_nginx_package
# └─verify_nginx_installation
# Parse command line arguments
parse_arguments "$@"
# Execute main workflow
main
exit $?

View File

@@ -0,0 +1,26 @@
#!/bin/bash
sudo yum install -y yum-utils
cat >/etc/yum.repos.d/nginx.repo<<EOF
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/8/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/8/x86_64/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF
yum-config-manager --enable nginx-mainline
yum install -y nginx

View File

@@ -0,0 +1,19 @@
#!/bin/bash
sudo apt install -y curl gnupg2 ca-certificates lsb-release ubuntu-keyring
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| sudo tee /etc/apt/preferences.d/99nginx
sudo apt update
sudo apt install -y nginx

View File

@@ -0,0 +1,32 @@
server {
listen 8889;
server_name localhost;
#允许跨域请求的域,*代表所有
add_header 'Access-Control-Allow-Origin' *;
#允许带上cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
#允许请求的方法,比如 GET/POST/PUT/DELETE
add_header 'Access-Control-Allow-Methods' *;
#允许请求的header
add_header 'Access-Control-Allow-Headers' *;
location /electronic {]
root /root/offline_map/;
autoindex on;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET,POST';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
}
location /satellite {
root /root/offline_map/;
autoindex on;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET,POST';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
}
# http://192.168.6.6:8889/electronic/{z}/{x}/{y}.png
# http://192.168.6.6:8889/satellite/{z}/{x}/{y}.png
# /root/offline_map/satellite /root/offline_map/electronic
}

View File

@@ -0,0 +1,92 @@
upstream proxy_server {
ip_hash;
server 192.168.1.128:30500;
server 192.168.1.22:30500;
server 192.168.1.221:30500;
server 192.168.1.82:30500;
server 192.168.1.238:30500;
}
server {
listen 8088;
server_name localhost;
location / {
proxy_pass http://proxy_server;
client_max_body_size 5120m;
client_body_buffer_size 5120m;
client_body_timeout 6000s;
proxy_send_timeout 10000s;
proxy_read_timeout 10000s;
proxy_connect_timeout 600s;
proxy_max_temp_file_size 5120m;
proxy_request_buffering on;
proxy_buffering off;
proxy_buffer_size 4k;
proxy_buffers 4 12k;
proxy_set_header Host fake-domain.sd-wf-ga-fly-260327.io;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /_AMapService/v4/map/styles {
set $args "$args&jscode=cf66cea95bdcdfcf8048456b36f357a1";
proxy_pass https://webapi.amap.com/v4/ap/styles;
}
location /_AMapService/ {
set $args "$args&jscode=cf66cea95bdcdfcf8048456b36f357a1";
proxy_pass https://restapi.amap.com/;
}
location /center/ws {
proxy_pass http://192.168.5.41:38083/mqtt;
proxy_http_version 1.1;
proxy_set_header Sec-WebSocket-Protocol mqtt;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
}
location /center/storage/ {
proxy_pass http://192.168.5.41:38899/storage/;
}
location /rtc/v1/ {
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
proxy_pass http://127.0.0.1:30985/rtc/v1/;
}
location /zlm/flv/ {
proxy_pass http://192.168.5.141:7088/;
}
location /zlm/hls/ {
proxy_pass http://192.168.5.141:7088/zlm/hls/;
}
location /zlm/webrtc {
proxy_pass http://192.168.5.141:7088/index/api/webrtc;
}
location /zlm/whip {
proxy_pass http://192.168.5.141:7088/index/api/whip;
}
location ~ ^/\w*/actuator/ {
return 403;
}
}

View File

@@ -0,0 +1,44 @@
user root;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
use epoll;
worker_connections 65535;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
server_tokens off;
sendfile on;
send_timeout 1200;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 600;
types_hash_max_size 2048;
client_max_body_size 2048m;
client_body_buffer_size 2048m;
underscores_in_headers on;
proxy_send_timeout 600;
proxy_read_timeout 600;
proxy_connect_timeout 600;
proxy_buffer_size 128k;
proxy_buffers 8 256k;
include /etc/nginx/conf.d/*.conf;
}
stream {
include /etc/nginx/conf.d/stream/*.conf;
}

View File

@@ -0,0 +1,17 @@
version: '3'
services:
cmii-nginx:
image: docker.io/library/nginx:1.28.2
volumes:
- /etc/nginx/conf.d:/etc/nginx/conf.d
- /etc/nginx/nginx.conf:/etc/nginx/nginx.conf
ports:
- "8088:8088"
- "31935:3193"
- "30090:30090"
restart: always
# mkdir -p /etc/nginx/conf.d
# touch /etc/nginx/nginx.conf

View File

@@ -0,0 +1,45 @@
#!/bin/bash
modify_ingress_nginx_host_network(){
echo "start to modify hostnetwork to false !"
kubectl patch daemonset nginx-ingress-controller -n ingress-nginx --patch '{"spec":{"template":{"spec":{"hostNetwork": false}}}}'
echo ""
kubectl get daemonset -n ingress-nginx nginx-ingress-controller -o jsonpath='{.spec.template.spec.hostNetwork}'
}
build_for_ingress_nginx_node_port(){
echo "start to write ingress nginx node port service !"
mkdir -p /root/wdd/install/
cat >>/root/wdd/install/k8s-ingress-nginx.yaml<<EOF
kind: Service
apiVersion: v1
metadata:
name: ingress-nginx-service
namespace: ingress-nginx
spec:
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
nodePort: 30500
- name: https
protocol: TCP
port: 443
targetPort: 443
nodePort: 31500
selector:
app: ingress-nginx
type: NodePort
sessionAffinity: None
EOF
echo ""
kubectl apply -f /root/wdd/install/k8s-ingress-nginx.yaml
}
modify_ingress_nginx_host_network
build_for_ingress_nginx_node_port

View File

@@ -0,0 +1,83 @@
#!/bin/bash
harbor_host=192.168.2.168:8033
namespace=cq-ws-260319
app_name=""
new_tag=""
download_from_oss() {
if [ "$1" == "" ]; then
echo "no zip file in error!"
exit 233
fi
echo "start to download => $1"
wget "https://oss.demo.uavcmlc.com/cmlc-installation/tmp/$1"
echo ""
echo ""
}
upload_image_to_harbor(){
if [ "$app_name" == "" ]; then
echo "app name null exit!"
exit 233
fi
if ! docker load < "$1"; then
echo "docker load error !"
fi
docker tag "harbor.cdcyy.com.cn/cmii/$app_name:$new_tag" "$harbor_host/cmii/$app_name:$new_tag"
echo ""
echo ""
echo "upload_image_to_harbor - start to push to => $harbor_host/cmii/$app_name:$new_tag"
docker login -u admin -p V2ryStr@ngPss $harbor_host
docker push "$harbor_host/cmii/$app_name:$new_tag"
echo ""
echo ""
}
parse_args(){
if [ "$1" == "" ]; then
echo "no zip file in error!"
exit 233
fi
local image_name="$1"
# cmii-uav-surveillance=5.2.0-27031-cqga=2024-03-04=573.tar.gz
app_name=$(echo $image_name | cut -d "=" -f1)
new_tag=$(echo $image_name | cut -d "=" -f2)
}
update_image_tag(){
if [ "$new_tag" == "" ]; then
echo "new tag error!"
exit 233
fi
local image_prefix=$(kubectl -n ${namespace} get deployment "${app_name}" -o=jsonpath='{.spec.template.spec.containers[*].image}' | cut -d":" -f1)
echo "image grep is => ${image_prefix}"
echo "start to update ${namespace} ${app_name} to ${new_tag} !"
echo ""
kubectl -n ${namespace} patch deployment "${app_name}" -p "{\"spec\":{\"template\":{\"spec\":{\"containers\":[{\"name\":\"${app_name}\",\"image\": \"${harbor_host}/cmii/$app_name:${new_tag}\"}]}}}}"
echo ""
echo "start to wait for 3 seconds!"
sleep 3
local image_new=$(kubectl -n ${namespace} get deployment "${app_name}" -o=jsonpath='{.spec.template.spec.containers[*].image}')
echo ""
echo "new image are => $image_new"
echo ""
}
main(){
parse_args "$1"
download_from_oss "$1"
upload_image_to_harbor "$1"
update_image_tag
}
main "$@"