大量更新
This commit is contained in:
@@ -2,40 +2,41 @@
|
||||
|
||||
|
||||
# 获取环境信息
|
||||
/usr/local/bin/agent-wdd info all
|
||||
cat /usr/local/etc/wdd/agent-wdd-config.yaml
|
||||
/usr/local/bin/rmdc-watchdog-node info all
|
||||
cat /usr/local/etc/wdd/rmdc-watchdog-node-config.yaml
|
||||
|
||||
# 手动执行全部的命令
|
||||
/usr/local/bin/agent-wdd base ssh key
|
||||
/usr/local/bin/agent-wdd base ssh config
|
||||
/usr/local/bin/rmdc-watchdog-node base ssh key
|
||||
/usr/local/bin/rmdc-watchdog-node base ssh config
|
||||
|
||||
/usr/local/bin/agent-wdd base tools
|
||||
/usr/local/bin/agent-wdd base swap
|
||||
/usr/local/bin/agent-wdd base firewall
|
||||
/usr/local/bin/agent-wdd base selinux
|
||||
/usr/local/bin/agent-wdd base sysconfig
|
||||
/usr/local/bin/rmdc-watchdog-node base tools
|
||||
|
||||
/usr/local/bin/agent-wdd zsh cn
|
||||
/usr/local/bin/rmdc-watchdog-node base swap
|
||||
/usr/local/bin/rmdc-watchdog-node base firewall
|
||||
/usr/local/bin/rmdc-watchdog-node base selinux
|
||||
/usr/local/bin/rmdc-watchdog-node base sysconfig
|
||||
|
||||
/usr/local/bin/rmdc-watchdog-node zsh cn
|
||||
|
||||
# 首先需要下载所有的依赖!
|
||||
|
||||
/usr/local/bin/agent-wdd base docker local
|
||||
/usr/local/bin/agent-wdd base dockercompose local
|
||||
/usr/local/bin/rmdc-watchdog-node base docker local
|
||||
/usr/local/bin/rmdc-watchdog-node base dockercompose local
|
||||
|
||||
# 仅在主节点执行
|
||||
/usr/local/bin/agent-wdd base docker config
|
||||
|
||||
/usr/local/bin/agent-wdd base harbor install
|
||||
/usr/local/bin/rmdc-watchdog-node base harbor install
|
||||
|
||||
|
||||
# 主节点执行
|
||||
# 安装octopus-agent
|
||||
mv agent-wdd_linux_amd64 /usr/local/bin/agent-wdd
|
||||
chmod +x /usr/local/bin/agent-wdd
|
||||
mv rmdc-watchdog-node_linux_amd64 /usr/local/bin/rmdc-watchdog-node
|
||||
chmod +x /usr/local/bin/rmdc-watchdog-node
|
||||
|
||||
mv rmdc-watchdog-node_linux_arm64 /usr/local/bin/rmdc-watchdog-node
|
||||
chmod +x /usr/local/bin/rmdc-watchdog-node
|
||||
|
||||
# 主节点安装ssh-key
|
||||
/usr/local/bin/agent-wdd base ssh config
|
||||
/usr/local/bin/agent-wdd base ssh key
|
||||
/usr/local/bin/rmdc-watchdog-node base ssh config
|
||||
/usr/local/bin/rmdc-watchdog-node base ssh key
|
||||
|
||||
# 批量执行命令
|
||||
host_list=(
|
||||
@@ -55,15 +56,24 @@ done
|
||||
# 复制 同步文件
|
||||
export server=172.16.100.62
|
||||
|
||||
scp /usr/local/bin/agent-wdd root@${server}:/usr/local/bin/agent-wdd
|
||||
ssh root@${server} "/usr/local/bin/agent-wdd base ssh config && /usr/local/bin/agent-wdd base ssh key"
|
||||
scp /usr/local/bin/rmdc-watchdog-node root@${server}:/usr/local/bin/rmdc-watchdog-node
|
||||
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base ssh config && /usr/local/bin/rmdc-watchdog-node base ssh key"
|
||||
ssh root@${server} "echo yes"
|
||||
|
||||
|
||||
# 安装docker-compose
|
||||
mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
|
||||
chmod +x /usr/local/bin/docker-compose
|
||||
|
||||
# ssh root@${server} "/usr/local/bin/agent-wdd base tools"
|
||||
# 批量执行rmdc-watchdog-node的命令
|
||||
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node info all"
|
||||
ssh root@${server} "cat /usr/local/etc/wdd/rmdc-watchdog-node-config.yaml"
|
||||
|
||||
|
||||
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base swap"
|
||||
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base firewall"
|
||||
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base selinux"
|
||||
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base sysconfig"
|
||||
|
||||
# APT代理加速
|
||||
scp /root/wdd/apt-change.sh root@${server}:/root/wdd/apt-change.sh
|
||||
@@ -84,6 +94,8 @@ scp /root/wdd/disk.sh root@${server}:/root/wdd/
|
||||
ssh root@${server} "bash /root/wdd/disk.sh"
|
||||
|
||||
# master节点安装docker
|
||||
|
||||
export DOCKER_VERSION=24
|
||||
bash /root/wdd/docker.sh
|
||||
|
||||
# 在线安装docker 通过APT代理
|
||||
@@ -98,21 +110,15 @@ ssh root@${server} "docker compose version"
|
||||
scp /root/wdd/docker-amd64-20.10.15.tgz root@${server}:/root/wdd/docker-amd64-20.10.15.tgz
|
||||
scp /root/wdd/docker-compose-v2.18.0-linux-amd64 root@${server}:/root/wdd/
|
||||
|
||||
# 批量执行agent-wdd的命令
|
||||
ssh root@${server} "/usr/local/bin/agent-wdd info all"
|
||||
ssh root@${server} "cat /usr/local/etc/wdd/agent-wdd-config.yaml"
|
||||
scp /root/wdd/docker-arm64-20.10.15.tgz root@${server}:/root/wdd/docker-arm64-20.10.15.tgz
|
||||
scp /root/wdd/docker-compose-v2.18.0-linux-arm64 root@${server}:/root/wdd/
|
||||
|
||||
|
||||
ssh root@${server} "/usr/local/bin/agent-wdd base swap"
|
||||
ssh root@${server} "/usr/local/bin/agent-wdd base firewall"
|
||||
ssh root@${server} "/usr/local/bin/agent-wdd base selinux"
|
||||
ssh root@${server} "/usr/local/bin/agent-wdd base sysconfig"
|
||||
|
||||
ssh root@${server} "/usr/local/bin/agent-wdd base docker local"
|
||||
ssh root@${server} "/usr/local/bin/agent-wdd base dockercompose local"
|
||||
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base docker local"
|
||||
ssh root@${server} "/usr/local/bin/rmdc-watchdog-node base dockercompose local"
|
||||
|
||||
# 仅在主节点执行
|
||||
/usr/local/bin/agent-wdd base docker config
|
||||
/usr/local/bin/rmdc-watchdog-node base docker config
|
||||
|
||||
# 下发docker的配置
|
||||
scp /etc/docker/daemon.json root@${server}:/etc/docker/daemon.json
|
||||
@@ -120,12 +126,12 @@ ssh root@${server} "cat /etc/docker/daemon.json"
|
||||
ssh root@${server} "systemctl restart docker"
|
||||
ssh root@${server} "docker info"
|
||||
|
||||
wget https://oss.demo.uavcmlc.com/cmlc-installation/tmp/nginx=1.27.0=2025-03-11=402.tar.gz && docker load < nginx=1.27.0=2025-03-11=402.tar.gz && docker run -it --rm harbor.cdcyy.com.cn/cmii/nginx:1.27.0
|
||||
# 清理脚本
|
||||
|
||||
ssh root@${server} "rm /root/wdd/*.sh"
|
||||
|
||||
# 主节点执行 安装harbor仓库
|
||||
/usr/local/bin/agent-wdd base harbor install
|
||||
/usr/local/bin/rmdc-watchdog-node base harbor install
|
||||
|
||||
# 安装rke kubectl
|
||||
mv /root/wdd/rke_linux-amd64 /usr/local/bin/rke
|
||||
@@ -135,6 +141,13 @@ mv /root/wdd/kubectl_v1.30.14_amd64 /usr/local/bin/kubectl
|
||||
chmod +x /usr/local/bin/kubectl
|
||||
|
||||
|
||||
## arm64
|
||||
mv /root/wdd/rke_linux-arm64 /usr/local/bin/rke
|
||||
chmod +x /usr/local/bin/rke
|
||||
|
||||
mv /root/wdd/kubectl_v1.30.14_arm64 /usr/local/bin/kubectl
|
||||
chmod +x /usr/local/bin/kubectl
|
||||
|
||||
# 安装 k8s-证书
|
||||
|
||||
mkdir /root/.kube
|
||||
@@ -144,7 +157,7 @@ cp ./kube_config_cluster.yml /root/.kube/config
|
||||
DEFAULT_HTTP_BACKEND_IP=$(kubectl -n ingress-nginx get svc default-http-backend -o jsonpath='{.spec.clusterIP}')
|
||||
|
||||
# master节点
|
||||
curl -s "http://${DEFAULT_HTTP_BACKEND_IP}"x
|
||||
curl -s "http://${DEFAULT_HTTP_BACKEND_IP}"
|
||||
|
||||
# worker节点
|
||||
ssh root@"$server" "DEFAULT_HTTP_BACKEND_IP='$DEFAULT_HTTP_BACKEND_IP' bash -s" <<'EOF'
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# 用户配置部分
|
||||
DISK="/dev/sdb" # 要操作的物理磁盘(请根据实际情况修改)
|
||||
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="${DISK}1"
|
||||
|
||||
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" # 确保系统识别新分区表
|
||||
|
||||
echo -e "\033[34m正在创建LVM结构...\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")
|
||||
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 -hT "$MOUNT_PATH"
|
||||
}
|
||||
|
||||
# 主执行流程
|
||||
check_prerequisites
|
||||
prepare_disk
|
||||
format_and_mount
|
||||
verify_result
|
||||
|
||||
echo -e "\n\033[32m操作执行完毕,请仔细核查上述输出信息\033[0m"
|
||||
|
||||
|
||||
|
||||
#请写一个shell脚本,脚本前面有变量可以设置 物理磁盘名称 挂载点路径 磁盘格式化的形式,脚本实现如下的功能
|
||||
#1.将物理磁盘的盘符修改为gpt格式
|
||||
#2.将物理磁盘全部空间创建一个分区,分区格式为lvm
|
||||
#3.将分区分配给逻辑卷datavg
|
||||
#4.将datavg所有可用的空间分配给逻辑卷lvdata
|
||||
#5.将逻辑卷格式化为变量磁盘格式化的形式(支持xfs和ext4的格式,默认为ext4)
|
||||
#6.创建变量挂载点路径
|
||||
#7.写入/etc/fatab,将逻辑卷挂载到变量挂载点,执行全部挂在操作
|
||||
#8.执行lsblk和df -TH查看分区是否正确挂载
|
||||
|
||||
|
||||
@@ -1,594 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# Metadata
|
||||
# ==============================================================================
|
||||
# Author : Smith Wang (Refactor by ChatGPT)
|
||||
# Version : 2.0.0
|
||||
# License : MIT
|
||||
# Description : Configure Docker APT repository (mirror) and install Docker on
|
||||
# Ubuntu (18.04/20.04/22.04/24.04) with robust offline handling.
|
||||
#
|
||||
# Modules :
|
||||
# - Logging & Error Handling
|
||||
# - Environment & Dependency Checks
|
||||
# - Public Network Reachability Detection
|
||||
# - Docker GPG Key Installation (Online/Offline)
|
||||
# - Docker APT Repo Configuration
|
||||
# - Docker Installation & Service Setup
|
||||
#
|
||||
# Notes :
|
||||
# - This script DOES NOT modify Ubuntu APT sources (/etc/apt/sources.list)
|
||||
# - This script DOES NOT set APT proxy (assumed handled elsewhere)
|
||||
# - If public network is NOT reachable and local GPG key is missing, script
|
||||
# will NOT proceed (per your requirement).
|
||||
#
|
||||
# ShellCheck : Intended clean for bash v5+ with: shellcheck -x <script>
|
||||
# ==============================================================================
|
||||
|
||||
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:-20.10}"
|
||||
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 "$@"
|
||||
@@ -1,24 +0,0 @@
|
||||
|
||||
|
||||
# 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"
|
||||
|
||||
132
998-常用脚本/a-部署脚本/b-高级磁盘-多物理盘.sh
Normal file
132
998-常用脚本/a-部署脚本/b-高级磁盘-多物理盘.sh
Normal file
@@ -0,0 +1,132 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
#----------------------------------------------------------
|
||||
# 用户配置部分
|
||||
#----------------------------------------------------------
|
||||
DISKS=("/dev/vdb" "/dev/vdc" "/dev/vdd" "/dev/vde") # 4块物理磁盘
|
||||
MOUNT_PATH="/var/lib/docker" # 挂载点路径(目录会自动创建)
|
||||
FS_TYPE="ext4" # 文件系统类型(支持 ext4/xfs,默认 ext4)
|
||||
|
||||
VG_NAME="datavg" # 卷组名
|
||||
LV_NAME="lvdata" # 逻辑卷名
|
||||
|
||||
#----------------------------------------------------------
|
||||
# 核心逻辑(建议非必要不修改)
|
||||
#----------------------------------------------------------
|
||||
|
||||
function check_prerequisites() {
|
||||
# 必须 root 权限运行检查
|
||||
[[ $EUID -ne 0 ]] && echo -e "\033[31m错误:必须使用 root 权限运行此脚本\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
|
||||
|
||||
# 磁盘存在性检查
|
||||
for disk in "${DISKS[@]}"; do
|
||||
[[ ! -b "$disk" ]] && echo -e "\033[31m错误:磁盘 $disk 不存在\033[0m" && exit 1
|
||||
done
|
||||
|
||||
# 检查 VG / LV 是否已存在,避免误操作
|
||||
if vgdisplay "$VG_NAME" >/dev/null 2>&1; then
|
||||
echo -e "\033[31m错误:卷组 $VG_NAME 已存在,请先检查环境\033[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if lvdisplay "/dev/${VG_NAME}/${LV_NAME}" >/dev/null 2>&1; then
|
||||
echo -e "\033[31m错误:逻辑卷 /dev/${VG_NAME}/${LV_NAME} 已存在,请先检查环境\033[0m"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function prepare_disks() {
|
||||
PARTITIONS=()
|
||||
|
||||
echo -e "\033[34m正在初始化磁盘分区...\033[0m"
|
||||
for disk in "${DISKS[@]}"; do
|
||||
echo -e "\033[34m处理磁盘: $disk\033[0m"
|
||||
|
||||
parted "$disk" --script mklabel gpt
|
||||
parted "$disk" --script mkpart primary 0% 100%
|
||||
parted "$disk" --script set 1 lvm on
|
||||
partprobe "$disk"
|
||||
|
||||
# 兼容 nvme 和普通 sd/vd 设备命名
|
||||
if [[ "$disk" =~ nvme ]]; then
|
||||
partition="${disk}p1"
|
||||
else
|
||||
partition="${disk}1"
|
||||
fi
|
||||
|
||||
# 等待分区节点出现
|
||||
udevadm settle
|
||||
sleep 1
|
||||
|
||||
[[ ! -b "$partition" ]] && echo -e "\033[31m错误:分区 $partition 未识别成功\033[0m" && exit 1
|
||||
|
||||
PARTITIONS+=("$partition")
|
||||
done
|
||||
}
|
||||
|
||||
function create_lvm() {
|
||||
echo -e "\033[34m正在创建 LVM 结构...\033[0m"
|
||||
|
||||
pvcreate "${PARTITIONS[@]}"
|
||||
vgcreate "$VG_NAME" "${PARTITIONS[@]}"
|
||||
lvcreate -y -l 100%FREE -n "$LV_NAME" "$VG_NAME"
|
||||
}
|
||||
|
||||
function format_and_mount() {
|
||||
local lv_path="/dev/${VG_NAME}/${LV_NAME}"
|
||||
|
||||
echo -e "\033[34m格式化逻辑卷...\033[0m"
|
||||
if [[ "$FS_TYPE" == "ext4" ]]; then
|
||||
mkfs.ext4 -F "$lv_path"
|
||||
else
|
||||
mkfs.xfs -f "$lv_path"
|
||||
fi
|
||||
|
||||
echo -e "\033[34m设置挂载配置...\033[0m"
|
||||
mkdir -p "$MOUNT_PATH"
|
||||
|
||||
UUID=$(blkid -s UUID -o value "$lv_path")
|
||||
[[ -z "$UUID" ]] && echo -e "\033[31m错误:未获取到逻辑卷 UUID\033[0m" && exit 1
|
||||
|
||||
# 避免重复写入 fstab
|
||||
if ! grep -q "$UUID" /etc/fstab; then
|
||||
echo "UUID=$UUID $MOUNT_PATH $FS_TYPE defaults 0 0" >> /etc/fstab
|
||||
else
|
||||
echo -e "\033[33m提示:/etc/fstab 中已存在该 UUID,跳过写入\033[0m"
|
||||
fi
|
||||
|
||||
mount -a
|
||||
}
|
||||
|
||||
function verify_result() {
|
||||
echo -e "\n\033[1;36m最终验证结果:\033[0m"
|
||||
|
||||
echo -e "\n\033[1;36m1. 查看块设备和 LVM 结构:\033[0m"
|
||||
lsblk -f
|
||||
|
||||
echo -e "\n\033[1;36m2. 查看挂载结果:\033[0m"
|
||||
df -hT "$MOUNT_PATH"
|
||||
|
||||
echo -e "\n\033[1;36m3. 查看 VG/LV 信息:\033[0m"
|
||||
vgs
|
||||
lvs
|
||||
pvs
|
||||
}
|
||||
|
||||
#----------------------------------------------------------
|
||||
# 主执行流程
|
||||
#----------------------------------------------------------
|
||||
check_prerequisites
|
||||
prepare_disks
|
||||
create_lvm
|
||||
format_and_mount
|
||||
verify_result
|
||||
|
||||
echo -e "\n\033[32m操作执行完毕,请仔细核查上述输出信息\033[0m"
|
||||
@@ -1,23 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,767 +0,0 @@
|
||||
#!/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 $?
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,32 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
upstream proxy_server {
|
||||
ip_hash;
|
||||
server 192.168.1.4:30500;
|
||||
server 192.168.1.3:30500;
|
||||
server 192.168.1.5: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.sc-my-uav-260202.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 /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 ~ ^/\w*/actuator/ {
|
||||
return 403;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
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;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
cmii-nginx:
|
||||
image: 172.16.100.55:8033/cmii/nginx:1.27.0
|
||||
volumes:
|
||||
- /etc/nginx/conf.d:/etc/nginx/conf.d
|
||||
- /etc/nginx/nginx.conf:/etc/nginx/nginx.conf
|
||||
- /root/offline_map:/root/offline_map
|
||||
ports:
|
||||
- "8088:8088"
|
||||
- "8089:8089"
|
||||
restart: always
|
||||
|
||||
|
||||
# mkdir -p /etc/nginx/conf.d
|
||||
# touch /etc/nginx/nginx.conf
|
||||
@@ -1,45 +0,0 @@
|
||||
#!/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
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ export tenant_name=outside
|
||||
export inner_master_ip=Master节点的内网IP
|
||||
export minio_host_ip=MINIO的内网IP
|
||||
|
||||
mc alias set ${tenant_name} http://${minio_host_ip}:9000 cmii B#923fC7mk
|
||||
mc alias set ${tenant_name} http://${minio_host_ip}:39000 cmii B#923fC7mk
|
||||
|
||||
|
||||
mc mb ${tenant_name}/jadenq ${tenant_name}/tus ${tenant_name}/thumbnail ${tenant_name}/pub-cms ${tenant_name}/live-srs-hls/ ${tenant_name}/mission/ ${tenant_name}/surveillance ${tenant_name}/playback ${tenant_name}/tower ${tenant_name}/modelprocess ${tenant_name}/srs-hls ${tenant_name}/live-cluster-hls ${tenant_name}/geodata ${tenant_name}/ilm-detect ${tenant_name}/ilm-geodata
|
||||
|
||||
@@ -31,11 +31,12 @@ kubectl delete -f k8s-nfs-test.yaml
|
||||
cd /var/lib/docker/nfs_data
|
||||
|
||||
|
||||
kubectl create ns sc-my-uav-260202
|
||||
kubectl create ns cq-ws-260319
|
||||
|
||||
kubectl apply -f k8s-pvc.yaml
|
||||
kubectl delete -f k8s-pvc.yaml
|
||||
|
||||
#飞行服务不需要
|
||||
kubectl apply -f k8s-mongo.yaml
|
||||
kubectl delete -f k8s-mongo.yaml
|
||||
|
||||
@@ -49,6 +50,7 @@ kubectl delete -f k8s-rabbitmq.yaml
|
||||
kubectl apply -f k8s-redis.yaml
|
||||
kubectl delete -f k8s-redis.yaml
|
||||
|
||||
# 监管平台不需要
|
||||
kubectl apply -f k8s-influxdb.yaml
|
||||
kubectl delete -f k8s-influxdb.yaml
|
||||
|
||||
@@ -57,7 +59,7 @@ kubectl delete -f k8s-mysql.yaml
|
||||
|
||||
|
||||
----
|
||||
doris部署
|
||||
doris部署-监管
|
||||
---
|
||||
kubectl apply -f doris-pvc.yaml
|
||||
kubectl apply -f doris-fe-configmap.yaml
|
||||
@@ -76,12 +78,15 @@ kubectl delete -f doris-be-statusfulset.yaml
|
||||
|
||||
---
|
||||
数据库初始化
|
||||
|
||||
参照 999-数据库脚本/a_rmdc-db-operator.sh
|
||||
---
|
||||
|
||||
|
||||
--- 飞服务不需要
|
||||
kubectl apply -f k8s-nacos.yaml
|
||||
kubectl delete -f k8s-nacos.yaml
|
||||
|
||||
|
||||
vim k8s-configmap.yaml
|
||||
kubectl apply -f k8s-configmap.yaml
|
||||
kubectl delete -f k8s-configmap.yaml
|
||||
@@ -90,6 +95,10 @@ vi k8s-ingress.yaml
|
||||
kubectl apply -f k8s-ingress.yaml
|
||||
kubectl delete -f k8s-ingress.yaml
|
||||
|
||||
vi k8s-minio.yaml
|
||||
kubectl apply -f k8s-minio.yaml
|
||||
kubectl delete -f k8s-minio.yaml
|
||||
|
||||
vi k8s-frontend.yaml
|
||||
kubectl apply -f k8s-frontend.yaml
|
||||
kubectl delete -f k8s-frontend.yaml
|
||||
@@ -98,7 +107,6 @@ vi k8s-backend.yaml
|
||||
kubectl apply -f k8s-backend.yaml
|
||||
kubectl delete -f k8s-backend.yaml
|
||||
|
||||
|
||||
kubectl -n kube-system get pods -o jsonpath='{.items[*].metadata.name}'
|
||||
|
||||
vi k8s-srs.yaml
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
export harbor_host=192.168.1.4:8033
|
||||
export harbor_host=harbor.wdd.io:8033
|
||||
|
||||
curl -X POST -u "admin:V2ryStr@ngPss" -H "authorization: Basic YWRtaW46VjJyeVN0ckBuZ1Bzcw==" -H "Content-Type: application/json" -d '{"project_name":"cmii","registry_id":null,"metadata":{"public":"true"},"storage_limit":-1}' http://$harbor_host/api/v2.0/projects
|
||||
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
#!/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.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 docker pull --platform linux/arm64 "${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 --platform linux/arm64 "${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
|
||||
@@ -1,154 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,168 +0,0 @@
|
||||
#!/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="/root/octopus-image"
|
||||
|
||||
DockerRegisterDomain="192.168.0.2:8033" # 需要根据实际修改
|
||||
HarborAdminPass=V2ryStr@ngPss # 需要跟第一脚本中的密码保持一致
|
||||
|
||||
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/rke/"
|
||||
dltu
|
||||
shift # past argument
|
||||
;;
|
||||
middle)
|
||||
local_gzip_path="$local_gzip_path/middle"
|
||||
mkdir -p $local_gzip_path
|
||||
oss_prefix_url="$oss_prefix_url/middle/"
|
||||
dltu
|
||||
shift # past argument
|
||||
;;
|
||||
cmii)
|
||||
local_gzip_path="$local_gzip_path/uavms-2.0"
|
||||
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/rke"
|
||||
mkdir -p ${local_gzip_path}
|
||||
oss_prefix_url="$oss_prefix_url/rke/"
|
||||
ltu
|
||||
shift # past argument
|
||||
;;
|
||||
middle)
|
||||
local_gzip_path="$local_gzip_path/middle"
|
||||
mkdir -p $local_gzip_path
|
||||
oss_prefix_url="$oss_prefix_url/middle/"
|
||||
ltu
|
||||
shift # past argument
|
||||
;;
|
||||
cmii)
|
||||
local_gzip_path="$local_gzip_path/cmii"
|
||||
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 "cmii"
|
||||
@@ -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
|
||||
@@ -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
|
||||
29
998-常用脚本/b-镜像同步/fly-amd64-260312/镜像包备份脚本.md
Normal file
29
998-常用脚本/b-镜像同步/fly-amd64-260312/镜像包备份脚本.md
Normal 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都有默认值,可以写入脚本中
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,438 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,15 +0,0 @@
|
||||
|
||||
# https://dl.min.io/client/mc/release/windows-amd64/mc.exe
|
||||
|
||||
& "C:\Users\makn\Downloads\mc.exe" alias set uav-demo https://oss.demo.uavcmlc.com cmii B#923fC7mk
|
||||
|
||||
|
||||
& "C:\Users\makn\Downloads\mc.exe" ls uav-demo/cmlc-installation/6.2.0-szgz-arm/ | ForEach-Object {
|
||||
$item=($_.Split()[-1])
|
||||
Write-Host "start to download $item "
|
||||
& "C:\Users\makn\Downloads\mc.exe" get uav-demo/cmlc-installation/6.2.0-szgz-arm/$item "D:\Desktop\cmii\cmii\"
|
||||
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
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 ""
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
busybox
|
||||
rancher/backup-restore-operator:v1.0.3
|
||||
rancher/calico-cni:v3.17.2
|
||||
rancher/calico-ctl:v3.17.2
|
||||
rancher/calico-kube-controllers:v3.17.2
|
||||
|
||||
rancher/calico-pod2daemon-flexvol:v3.17.2
|
||||
rancher/cis-operator:v1.0.3
|
||||
rancher/cluster-proportional-autoscaler:1.7.1
|
||||
rancher/coredns-coredns:1.8.0
|
||||
rancher/coreos-etcd:v3.4.14-rancher1
|
||||
rancher/coreos-kube-state-metrics:v1.9.7
|
||||
rancher/coreos-prometheus-config-reloader:v0.39.0
|
||||
rancher/coreos-prometheus-operator:v0.39.0
|
||||
rancher/externalip-webhook:v0.1.6
|
||||
rancher/flannel-cni:v0.3.0-rancher6
|
||||
rancher/coreos-flannel:v0.13.0-rancher1
|
||||
rancher/fleet-agent:v0.3.4
|
||||
rancher/fleet:v0.3.4
|
||||
rancher/fluentd:v0.1.24
|
||||
rancher/grafana-grafana:7.1.5
|
||||
rancher/hyperkube:v1.20.4-rancher1
|
||||
rancher/jimmidyson-configmap-reload:v0.3.0
|
||||
rancher/k8s-dns-dnsmasq-nanny:1.15.2
|
||||
rancher/k8s-dns-kube-dns:1.15.2
|
||||
rancher/k8s-dns-node-cache:1.15.13
|
||||
rancher/k8s-dns-sidecar:1.15.2
|
||||
rancher/klipper-lb:v0.1.2
|
||||
rancher/kube-api-auth:v0.1.4
|
||||
rancher/kubectl:v1.20.4
|
||||
rancher/kubernetes-external-dns:v0.7.3
|
||||
rancher/cluster-proportional-autoscaler:1.8.1
|
||||
rancher/library-busybox:1.31.1
|
||||
rancher/library-busybox:1.32.1
|
||||
rancher/library-nginx:1.19.2-alpine
|
||||
rancher/library-traefik:1.7.19
|
||||
rancher/local-path-provisioner:v0.0.11
|
||||
rancher/local-path-provisioner:v0.0.14
|
||||
rancher/local-path-provisioner:v0.0.19
|
||||
rancher/log-aggregator:v0.1.7
|
||||
rancher/istio-kubectl:1.5.10
|
||||
rancher/metrics-server:v0.4.1
|
||||
rancher/configmap-reload:v0.3.0-rancher4
|
||||
rancher/nginx-ingress-controller-defaultbackend:1.5-rancher1
|
||||
rancher/nginx-ingress-controller:nginx-0.43.0-rancher1
|
||||
rancher/opa-gatekeeper:v3.1.0-beta.7
|
||||
rancher/openzipkin-zipkin:2.14.2
|
||||
rancher/pause:3.2
|
||||
rancher/plugins-docker:18.09
|
||||
rancher/prom-alertmanager:v0.21.0
|
||||
rancher/prom-node-exporter:v1.0.1
|
||||
rancher/prom-prometheus:v2.18.2
|
||||
rancher/prometheus-auth:v0.2.1
|
||||
rancher/rancher-agent:v2.5.7
|
||||
rancher/rancher-webhook:v0.1.0-beta9
|
||||
rancher/rancher:v2.5.7
|
||||
rancher/rke-tools:v0.1.72
|
||||
rancher/security-scan:v0.1.14
|
||||
rancher/security-scan:v0.2.2
|
||||
rancher/shell:v0.1.6
|
||||
rancher/sonobuoy-sonobuoy:v0.16.3
|
||||
rancher/system-upgrade-controller:v0.6.2
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
bitnami/redis:6.2.14-debian-11-r1
|
||||
bitnami/mysql:8.1.0-debian-11-r42
|
||||
simonrupf/chronyd:0.4.3
|
||||
bitnami/bitnami-shell:11-debian-11-r136
|
||||
bitnami/rabbitmq:3.11.26-debian-11-r2
|
||||
ossrs/srs:v5.0.195
|
||||
emqx/emqx:4.4.19
|
||||
emqx/emqx:5.5.1
|
||||
nacos/nacos-server:v2.1.2-slim
|
||||
mongo:5.0
|
||||
bitnami/minio:2023.5.4
|
||||
kubernetesui/dashboard:v2.0.1
|
||||
kubernetesui/metrics-scraper:v1.0.4
|
||||
nginx:1.24.0
|
||||
redis:6.0.20-alpine
|
||||
dyrnq/nfs-subdir-external-provisioner:v4.0.2
|
||||
jerrychina2020/rke-tools:v0.175-linux
|
||||
jerrychina2020/rke-tools:v0.175
|
||||
busybox:latest
|
||||
1
998-常用脚本/b-镜像同步/wdd-operator配合的dltu脚本/demo环境-oss访问.md
Normal file
1
998-常用脚本/b-镜像同步/wdd-operator配合的dltu脚本/demo环境-oss访问.md
Normal file
@@ -0,0 +1 @@
|
||||
mc alias set demo http://192.168.11.33:9000 cmii B#923fC7mk
|
||||
@@ -1,23 +0,0 @@
|
||||
#!/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}"
|
||||
63
998-常用脚本/b-镜像同步/打包推送脚本.sh
Normal file
63
998-常用脚本/b-镜像同步/打包推送脚本.sh
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ============================================================
|
||||
# 配置区:修改以下变量
|
||||
# ============================================================
|
||||
REGISTRY="chongqingshcis-a189ec98.ecis.chongqing-1.cmecloud.cn" # 登录地址 / 目标仓库域名
|
||||
NAMESPACE="cmii" # 目标命名空间
|
||||
USERNAME="cqcmii" # 仓库登录用户名
|
||||
PASSWORD='pL8$kq9@m' # 仓库登录密码
|
||||
# ============================================================
|
||||
|
||||
# 参数校验
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: $0 <image>"
|
||||
echo "Example:"
|
||||
echo " $0 nginx:latest"
|
||||
echo " $0 harbor.cdcyy.com.cm/cmii/asdad:v1.2"
|
||||
echo " $0 harbor.cdcyy.com.cm/cmii/cmii-live/asdad:v1.2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SRC_IMAGE="$1"
|
||||
|
||||
# ---------- 解析 image name 和 tag ----------
|
||||
# 先分离 tag(冒号后面部分)
|
||||
if [[ "$SRC_IMAGE" =~ ^(.*):([^:/]+)$ ]]; then
|
||||
repo="${BASH_REMATCH[1]}"
|
||||
tag="${BASH_REMATCH[2]}"
|
||||
else
|
||||
repo="$SRC_IMAGE"
|
||||
tag="latest"
|
||||
fi
|
||||
|
||||
# 只取路径最后一段作为镜像名(去掉任意层级 namespace/domain)
|
||||
image_name="${repo##*/}"
|
||||
|
||||
DEST_IMAGE="${REGISTRY}/${NAMESPACE}/${image_name}:${tag}"
|
||||
# --------------------------------------------
|
||||
|
||||
echo ">>> Source : $SRC_IMAGE"
|
||||
echo ">>> Target : $DEST_IMAGE"
|
||||
echo ""
|
||||
|
||||
# 登录
|
||||
echo ">>> Logging in to $REGISTRY..."
|
||||
echo "$PASSWORD" | docker login "$REGISTRY" -u "$USERNAME" --password-stdin
|
||||
|
||||
# Pull
|
||||
echo ">>> [pull ] $SRC_IMAGE"
|
||||
docker pull "$SRC_IMAGE"
|
||||
|
||||
# Tag
|
||||
echo ">>> [tag ] $SRC_IMAGE → $DEST_IMAGE"
|
||||
docker tag "$SRC_IMAGE" "$DEST_IMAGE"
|
||||
|
||||
# Push
|
||||
echo ">>> [push ] $DEST_IMAGE"
|
||||
docker push "$DEST_IMAGE"
|
||||
|
||||
echo ""
|
||||
echo ">>> Done: $DEST_IMAGE"
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/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
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/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 "$@"
|
||||
52
998-常用脚本/b-镜像同步/高级-推动镜像-260312.sh
Normal file
52
998-常用脚本/b-镜像同步/高级-推动镜像-260312.sh
Normal file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ============================================================
|
||||
# 配置区:修改以下变量
|
||||
# ============================================================
|
||||
REGISTRY="chongqingshcis-a189ec98.ecis.chongqing-1.cmecloud.cn" # 登录地址 / 目标仓库域名
|
||||
NAMESPACE="cmii" # 目标命名空间
|
||||
USERNAME="cqcmii" # 仓库登录用户名
|
||||
PASSWORD='pL8$kq9@m' # 仓库登录密码
|
||||
INPUT_FILE="middleware-fly-amd64-260311.txt" # 镜像列表文件路径
|
||||
# ============================================================
|
||||
|
||||
# 登录到私有仓库
|
||||
echo ">>> Logging in to $REGISTRY..."
|
||||
echo "$PASSWORD" | docker login "$REGISTRY" -u "$USERNAME" --password-stdin
|
||||
|
||||
# 逐行处理镜像
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
# 跳过空行和注释行
|
||||
[[ -z "$line" || "$line" == \#* ]] && continue
|
||||
|
||||
# 拆分 repo 和 tag
|
||||
if [[ "$line" =~ (.*):(.*) ]]; then
|
||||
repo="${BASH_REMATCH[1]}"
|
||||
tag="${BASH_REMATCH[2]}"
|
||||
else
|
||||
repo="$line"
|
||||
tag="latest"
|
||||
fi
|
||||
|
||||
# 只保留镜像名最后一段(去掉原有 namespace/domain)
|
||||
image_name="${repo##*/}"
|
||||
|
||||
src_image="${repo}:${tag}"
|
||||
dest_image="${REGISTRY}/${NAMESPACE}/${image_name}:${tag}"
|
||||
|
||||
echo ""
|
||||
echo ">>> [pull ] $src_image"
|
||||
docker pull "$src_image"
|
||||
|
||||
echo ">>> [tag ] $src_image → $dest_image"
|
||||
docker tag "$src_image" "$dest_image"
|
||||
|
||||
echo ">>> [push ] $dest_image"
|
||||
docker push "$dest_image"
|
||||
|
||||
done < "$INPUT_FILE"
|
||||
|
||||
echo ""
|
||||
echo ">>> All done."
|
||||
10
998-常用脚本/c-k8s常用脚本/获取类型为NodePort的Service.sh
Normal file
10
998-常用脚本/c-k8s常用脚本/获取类型为NodePort的Service.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
|
||||
kubectl get svc -A -o json | jq -r '
|
||||
.items[]
|
||||
| select(.spec.type=="NodePort")
|
||||
| .metadata.namespace as $ns
|
||||
| .metadata.name as $name
|
||||
| .spec.ports[]
|
||||
| [$ns, $name, .port, .nodePort]
|
||||
| @tsv' | column -t
|
||||
85
998-常用脚本/c-k8s常用脚本/部署业务-镜像-分支.sh
Normal file
85
998-常用脚本/c-k8s常用脚本/部署业务-镜像-分支.sh
Normal file
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# 脚本功能:收集指定命名空间下副本数 > 0 的 Deployment 信息
|
||||
# 包含:Deployment 名称、镜像名称、GIT 相关环境变量
|
||||
# ============================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── 配置区 ──────────────────────────────────────────────────
|
||||
NAMESPACE="scydqlh"
|
||||
OUTPUT_FILE="deployment_info_$(date +%Y%m%d_%H%M%S).txt"
|
||||
# ────────────────────────────────────────────────────────────
|
||||
|
||||
echo "=========================================="
|
||||
echo " 命名空间 : $NAMESPACE"
|
||||
echo " 输出文件 : $OUTPUT_FILE"
|
||||
echo "=========================================="
|
||||
|
||||
# 创建(清空)输出文件
|
||||
> "$OUTPUT_FILE"
|
||||
|
||||
# 获取所有 Deployment 名称(换行分隔)
|
||||
DEPLOYMENTS=$(kubectl get deployments -n "$NAMESPACE" \
|
||||
-o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' 2>/dev/null)
|
||||
|
||||
if [[ -z "$DEPLOYMENTS" ]]; then
|
||||
echo "[ERROR] 命名空间 '$NAMESPACE' 下未发现任何 Deployment,请检查命名空间是否正确。"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PROCESSED=0
|
||||
SKIPPED=0
|
||||
|
||||
while IFS= read -r DEPLOY; do
|
||||
[[ -z "$DEPLOY" ]] && continue
|
||||
|
||||
# ── 1. 获取期望副本数 ──────────────────────────────────────
|
||||
REPLICAS=$(kubectl get deployment "$DEPLOY" -n "$NAMESPACE" \
|
||||
-o jsonpath='{.spec.replicas}' 2>/dev/null)
|
||||
REPLICAS="${REPLICAS:-0}"
|
||||
|
||||
if [[ "$REPLICAS" == 0 ]]; then
|
||||
echo "[SKIP] $DEPLOY (副本数=${REPLICAS},≤ 1,跳过)"
|
||||
(( SKIPPED++ )) || true
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "[INFO] 处理 Deployment: $DEPLOY (副本数=${REPLICAS})"
|
||||
|
||||
# ── 2. 获取第一个容器的镜像名称 ───────────────────────────
|
||||
IMAGE=$(kubectl get deployment "$DEPLOY" -n "$NAMESPACE" \
|
||||
-o jsonpath='{.spec.template.spec.containers[0].image}' 2>/dev/null)
|
||||
IMAGE="${IMAGE:-<未获取到镜像>}"
|
||||
|
||||
# ── 3. 在第一个副本 Pod 中执行 env | grep GIT ─────────────
|
||||
GIT_ENV=$(kubectl exec -n "$NAMESPACE" "deploy/$DEPLOY" \
|
||||
-- sh -c "env | grep GIT" 2>/dev/null || echo "")
|
||||
|
||||
# ── 4. 写入输出文件 ───────────────────────────────────────
|
||||
{
|
||||
echo "deployment名称:${DEPLOY}"
|
||||
echo "镜像名称:${IMAGE}"
|
||||
echo "环境变量:"
|
||||
if [[ -n "$GIT_ENV" ]]; then
|
||||
while IFS= read -r env_line; do
|
||||
echo " ${env_line}"
|
||||
done <<< "$GIT_ENV"
|
||||
else
|
||||
echo " (未发现 GIT 相关环境变量)"
|
||||
fi
|
||||
echo ""
|
||||
echo "------------------------------------------"
|
||||
echo ""
|
||||
} >> "$OUTPUT_FILE"
|
||||
|
||||
(( PROCESSED++ )) || true
|
||||
|
||||
done <<< "$DEPLOYMENTS"
|
||||
|
||||
# ── 汇总输出 ──────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo " 完成!已处理: ${PROCESSED} 个,已跳过: ${SKIPPED} 个"
|
||||
echo " 结果文件: $OUTPUT_FILE"
|
||||
echo "=========================================="
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
namespace=xafkapp
|
||||
namespace=命名空间
|
||||
|
||||
install_yq() {
|
||||
wget https://oss.demo.uavcmlc.com/cmlc-installation/downloadfile/amd/yq_linux_amd64 -O /usr/local/bin/yq
|
||||
|
||||
111
998-常用脚本/备份脚本/按APP切分备份命名空间.sh
Normal file
111
998-常用脚本/备份脚本/按APP切分备份命名空间.sh
Normal file
@@ -0,0 +1,111 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 定义命名空间
|
||||
namespace="命名空间"
|
||||
|
||||
# 创建一个带时间戳的备份目录,保持目录整洁
|
||||
backup_dir="backup_${namespace}_$(date +%Y%m%d%H%M%S)"
|
||||
mkdir -p "${backup_dir}"
|
||||
|
||||
# YQ 清理规则:去除指定的 metadata 字段以及整个 status 字段
|
||||
# 注意:加入了 .metadata.generation,这在 deployment/statefulset 中也很常见
|
||||
yq_filter='del(.metadata.managedFields, .metadata.annotations, .metadata.creationTimestamp, .metadata.uid, .metadata.resourceVersion, .metadata.selfLink, .metadata.generation, .status)'
|
||||
|
||||
install_yq() {
|
||||
echo "=> 检查并安装 yq 工具..."
|
||||
if ! command -v yq &> /dev/null; then
|
||||
wget https://oss.demo.uavcmlc.com/cmlc-installation/downloadfile/amd/yq_linux_amd64 -O /usr/local/bin/yq
|
||||
# wget https://oss.demo.uavcmlc.com/cmlc-installation/downloadfile/aarch/yq_linux_arm64 -O /usr/local/bin/yq
|
||||
chmod +x /usr/local/bin/yq
|
||||
echo "yq 安装完成!"
|
||||
else
|
||||
echo "yq 已安装,跳过。"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# 备份单个应用的函数
|
||||
backup_single_app() {
|
||||
local app_name=$1
|
||||
local target_file="${backup_dir}/${app_name}.yaml"
|
||||
|
||||
echo "=> 正在备份应用: ${app_name}"
|
||||
|
||||
# 创建空文件或清空已有文件
|
||||
> "${target_file}"
|
||||
|
||||
# 1. 备份 Deployment
|
||||
if kubectl get deployment "${app_name}" -n "${namespace}" &>/dev/null; then
|
||||
echo "---" >> "${target_file}"
|
||||
kubectl get deployment "${app_name}" -n "${namespace}" -o yaml | yq eval "${yq_filter}" - >> "${target_file}"
|
||||
fi
|
||||
|
||||
# 2. 备份 StatefulSet
|
||||
if kubectl get statefulset "${app_name}" -n "${namespace}" &>/dev/null; then
|
||||
echo "---" >> "${target_file}"
|
||||
kubectl get statefulset "${app_name}" -n "${namespace}" -o yaml | yq eval "${yq_filter}" - >> "${target_file}"
|
||||
fi
|
||||
|
||||
# 3. 备份 Service (假设 Service 名称与应用名称一致)
|
||||
if kubectl get service "${app_name}" -n "${namespace}" &>/dev/null; then
|
||||
echo "---" >> "${target_file}"
|
||||
kubectl get service "${app_name}" -n "${namespace}" -o yaml | yq eval "${yq_filter}" - >> "${target_file}"
|
||||
fi
|
||||
|
||||
# 4. 备份 ConfigMap (假设主 ConfigMap 名称与应用名称一致)
|
||||
if kubectl get configmap "${app_name}" -n "${namespace}" &>/dev/null; then
|
||||
echo "---" >> "${target_file}"
|
||||
kubectl get configmap "${app_name}" -n "${namespace}" -o yaml | yq eval "${yq_filter}" - >> "${target_file}"
|
||||
fi
|
||||
}
|
||||
|
||||
backup_ingress() {
|
||||
echo "=> 正在单独备份所有 Ingress 资源..."
|
||||
local ingress_file="${backup_dir}/all-ingress-${namespace}.yaml"
|
||||
|
||||
# 检查是否存在 ingress 资源
|
||||
if [ "$(kubectl get ingress -n "${namespace}" --no-headers 2>/dev/null | wc -l)" -gt 0 ]; then
|
||||
# 因为 get ingress 拿到的是一个 List,所以需要加 .items[] 遍历处理
|
||||
kubectl get ingress -n "${namespace}" -o yaml | yq eval '.items[] | '"${yq_filter}" - > "${ingress_file}"
|
||||
# 在每个 apiVersion 前面加上 --- 分隔符
|
||||
sed -i '/^apiVersion:/i ---' "${ingress_file}"
|
||||
echo "Ingress 备份完成: ${ingress_file}"
|
||||
else
|
||||
echo "命名空间 ${namespace} 下未找到 Ingress 资源。"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
main() {
|
||||
install_yq
|
||||
|
||||
echo "================================================="
|
||||
echo "开始执行命名空间 ${namespace} 的多应用切分备份"
|
||||
echo "备份目录: ${backup_dir}"
|
||||
echo "================================================="
|
||||
|
||||
# 获取该命名空间下所有的 Deployment 和 StatefulSet 的名称,作为应用的基准列表
|
||||
# 使用 sort -u 去重,防止某些同名情况
|
||||
app_list=$(kubectl get deployments,statefulsets -n "${namespace}" -o custom-columns=NAME:.metadata.name --no-headers | sort -u)
|
||||
|
||||
if [ -z "${app_list}" ]; then
|
||||
echo "未在命名空间中找到任何 Deployment 或 StatefulSet。"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 遍历每个应用名称,执行合并备份
|
||||
for app in ${app_list}; do
|
||||
backup_single_app "${app}"
|
||||
done
|
||||
|
||||
echo ""
|
||||
# 单独备份 Ingress
|
||||
backup_ingress
|
||||
|
||||
echo "================================================="
|
||||
echo "所有资源备份完毕!文件已存放在 ${backup_dir}/ 目录下。"
|
||||
echo "================================================="
|
||||
}
|
||||
|
||||
# 执行主流程
|
||||
main
|
||||
11
998-常用脚本/备份脚本/按照独立应用备份.md
Normal file
11
998-常用脚本/备份脚本/按照独立应用备份.md
Normal file
@@ -0,0 +1,11 @@
|
||||
请实现yq工具,使用kubectl工具,针对特定的命名空间进行完整的备份
|
||||
1. 需要去除metadata中的managedFields、annotations、creationTimestamp、uid、resourceVersion、status、selfLink等字段
|
||||
2. 去除status字段
|
||||
|
||||
|
||||
需要按照应用名称(按照deployment的名称作为应用名称)进行切分备份,即为一个命名空间下有多个应用,每个应用包含deployment、service、configmap、statefulset等资源,每个应用的备份文件需要独立出来,
|
||||
例如一个命名空间下的应用名称为app1、app2、app3,那么备份文件需要为app1.yaml、app2.yaml、app3.yaml,每个文件中包含对应的资源。
|
||||
|
||||
需要单独备份ingress部分的资源
|
||||
|
||||
请你参考现在的备份命名空间,实现一个新的shell脚本,实现上述的功能
|
||||
85
998-常用脚本/备份脚本/部署业务-镜像-分支.sh
Normal file
85
998-常用脚本/备份脚本/部署业务-镜像-分支.sh
Normal file
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# 脚本功能:收集指定命名空间下副本数 > 0 的 Deployment 信息
|
||||
# 包含:Deployment 名称、镜像名称、GIT 相关环境变量
|
||||
# ============================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ── 配置区 ──────────────────────────────────────────────────
|
||||
NAMESPACE="sd-wf-ga-fly-260327"
|
||||
OUTPUT_FILE="deployment_info_$(date +%Y%m%d_%H%M%S).txt"
|
||||
# ────────────────────────────────────────────────────────────
|
||||
|
||||
echo "=========================================="
|
||||
echo " 命名空间 : $NAMESPACE"
|
||||
echo " 输出文件 : $OUTPUT_FILE"
|
||||
echo "=========================================="
|
||||
|
||||
# 创建(清空)输出文件
|
||||
> "$OUTPUT_FILE"
|
||||
|
||||
# 获取所有 Deployment 名称(换行分隔)
|
||||
DEPLOYMENTS=$(kubectl get deployments -n "$NAMESPACE" \
|
||||
-o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' 2>/dev/null)
|
||||
|
||||
if [[ -z "$DEPLOYMENTS" ]]; then
|
||||
echo "[ERROR] 命名空间 '$NAMESPACE' 下未发现任何 Deployment,请检查命名空间是否正确。"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PROCESSED=0
|
||||
SKIPPED=0
|
||||
|
||||
while IFS= read -r DEPLOY; do
|
||||
[[ -z "$DEPLOY" ]] && continue
|
||||
|
||||
# ── 1. 获取期望副本数 ──────────────────────────────────────
|
||||
REPLICAS=$(kubectl get deployment "$DEPLOY" -n "$NAMESPACE" \
|
||||
-o jsonpath='{.spec.replicas}' 2>/dev/null)
|
||||
REPLICAS="${REPLICAS:-0}"
|
||||
|
||||
if [[ "$REPLICAS" == 0 ]]; then
|
||||
echo "[SKIP] $DEPLOY (副本数=${REPLICAS},≤ 1,跳过)"
|
||||
(( SKIPPED++ )) || true
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "[INFO] 处理 Deployment: $DEPLOY (副本数=${REPLICAS})"
|
||||
|
||||
# ── 2. 获取第一个容器的镜像名称 ───────────────────────────
|
||||
IMAGE=$(kubectl get deployment "$DEPLOY" -n "$NAMESPACE" \
|
||||
-o jsonpath='{.spec.template.spec.containers[0].image}' 2>/dev/null)
|
||||
IMAGE="${IMAGE:-<未获取到镜像>}"
|
||||
|
||||
# ── 3. 在第一个副本 Pod 中执行 env | grep GIT ─────────────
|
||||
GIT_ENV=$(kubectl exec -n "$NAMESPACE" "deploy/$DEPLOY" \
|
||||
-- sh -c "env | grep GIT" 2>/dev/null || echo "")
|
||||
|
||||
# ── 4. 写入输出文件 ───────────────────────────────────────
|
||||
{
|
||||
echo "deployment名称:${DEPLOY}"
|
||||
echo "镜像名称:${IMAGE}"
|
||||
echo "环境变量:"
|
||||
if [[ -n "$GIT_ENV" ]]; then
|
||||
while IFS= read -r env_line; do
|
||||
echo " ${env_line}"
|
||||
done <<< "$GIT_ENV"
|
||||
else
|
||||
echo " (未发现 GIT 相关环境变量)"
|
||||
fi
|
||||
echo ""
|
||||
echo "------------------------------------------"
|
||||
echo ""
|
||||
} >> "$OUTPUT_FILE"
|
||||
|
||||
(( PROCESSED++ )) || true
|
||||
|
||||
done <<< "$DEPLOYMENTS"
|
||||
|
||||
# ── 汇总输出 ──────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo " 完成!已处理: ${PROCESSED} 个,已跳过: ${SKIPPED} 个"
|
||||
echo " 结果文件: $OUTPUT_FILE"
|
||||
echo "=========================================="
|
||||
11
998-常用脚本/备份脚本/重启CMII应用.sh
Normal file
11
998-常用脚本/备份脚本/重启CMII应用.sh
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
export namespace=cq-ws-260319
|
||||
|
||||
kubectl rollout restart deployment -n "${namespace}" -l cmii.type=frontend,octopus.control=frontend-app-wdd
|
||||
|
||||
kubectl rollout restart deployment -n "${namespace}" -l cmii.type=backend,octopus/control=backend-app-1.0.0
|
||||
|
||||
kubectl rollout restart daemonset/nginx-ingress-controller -n ingress-nginx
|
||||
|
||||
kubectl rollout status daemonset/nginx-ingress-controller -n ingress-nginx
|
||||
# 等待输出: daemon set "nginx-ingress-controller" successfully rolled out
|
||||
@@ -2,4 +2,6 @@
|
||||
|
||||
|
||||
|
||||
https://github.com/wise2c-devops/build-harbor-aarch64
|
||||
https://github.com/wise2c-devops/build-harbor-aarch64
|
||||
|
||||
https://github.com/octohelm/harbor
|
||||
@@ -1,17 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
wget https://oss.demo.uavcmlc.com/cmlc-installation/downloadfile/amd/jq-linux-amd64 -O /usr/local/bin/jq
|
||||
wget https://oss.demo.uavcmlc.com/cmlc-installation/tmp/jq-linux-amd64 -O /usr/local/bin/jq
|
||||
#wget https://oss.demo.uavcmlc.com/cmlc-installation/downloadfile/aarch/jq-linux-arm64 -O /usr/local/bin/jq
|
||||
chmod +x /usr/local/bin/jq
|
||||
|
||||
|
||||
export name_space=xayd
|
||||
|
||||
kubectl delete pods -n $name_space --field-selector status.phase!=Running --force
|
||||
|
||||
kubectl get pods -n $name_space -o json | jq -r '.items[] | select(.status.containerStatuses[0].ready == false) | .metadata.name' | xargs -r kubectl delete pod -n $name_space --force
|
||||
export name_space_list=(kube-system kubernetes-dashboard ingress-nginx bj-sh-uas-260511)
|
||||
|
||||
export name_space_list=(bj-sh-uas-260511)
|
||||
for name_space in ${name_space_list[*]};do
|
||||
|
||||
kubectl delete pods -n $name_space --field-selector status.phase!=Running --force
|
||||
|
||||
kubectl get pods -n $name_space -o json | jq -r '.items[] | select(.status.containerStatuses[0].ready == false) | .metadata.name' | xargs -r kubectl delete pod -n $name_space --force
|
||||
|
||||
done
|
||||
|
||||
kubectl -n ${name_space} delete pod helm-nacos-0 --force
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
|
||||
name_space=zjyd
|
||||
|
||||
delete_all_fronted_cmii_pod(){
|
||||
|
||||
all_pod_list=($(kubectl get pods -n "$name_space" -o=jsonpath='{.items[*].metadata.name}' | tr " " "\n"))
|
||||
for pod in "${all_pod_list[@]}"; do
|
||||
if echo "$pod" | grep -q "platform"; then
|
||||
echo ""
|
||||
echo "current pod is $pod"
|
||||
kubectl -n "$name_space" delete pod "$pod" --force
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
delete_all_backend_cmii_pod(){
|
||||
all_pod_list=($(kubectl get pods -n "$name_space" -o=jsonpath='{.items[*].metadata.name}' | tr " " "\n"))
|
||||
for pod in "${all_pod_list[@]}"; do
|
||||
if echo "$pod" | grep -v "platform" | grep -q "cmii"; then
|
||||
echo ""
|
||||
echo "current pod is $pod"
|
||||
kubectl -n "$name_space" delete pod "$pod" --force
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
delete_all_backend_cmii_pod
|
||||
delete_all_fronted_cmii_pod
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
harbor_host=192.168.0.10:8033
|
||||
namespace=hbyd
|
||||
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 "$@"
|
||||
117
998-常用脚本/更新脚本/新更新脚本.md
Normal file
117
998-常用脚本/更新脚本/新更新脚本.md
Normal file
@@ -0,0 +1,117 @@
|
||||
### 1)先看这个 Deployment 对应的 ReplicaSet 列表
|
||||
|
||||
```bash
|
||||
kubectl -n cq-fly-260311 get rs -o wide | grep cmii-sky-converge
|
||||
```
|
||||
|
||||
更稳一点的方式,用 label 过滤:
|
||||
|
||||
```bash
|
||||
kubectl -n cq-fly-260311 get rs -l cmii.app=cmii-sky-converge
|
||||
```
|
||||
|
||||
如果你不确定 label,不妨先看 Deployment 的 selector:
|
||||
|
||||
```bash
|
||||
kubectl -n cq-fly-260311 get deploy cmii-sky-converge -o jsonpath='{.spec.selector.matchLabels}'
|
||||
echo
|
||||
```
|
||||
|
||||
### 2)从 ReplicaSet 里看 revision 和镜像
|
||||
|
||||
Deployment 的 revision 一般记录在 ReplicaSet 注解 `deployment.kubernetes.io/revision` 里。可以这样查:
|
||||
|
||||
```bash
|
||||
kubectl -n cq-fly-260311 get rs \
|
||||
-o custom-columns=NAME:.metadata.name,REVISION:.metadata.annotations.deployment\.kubernetes\.io/revision,REPLICAS:.spec.replicas,IMAGE:.spec.template.spec.containers[*].image \
|
||||
| grep cmii-sky-converge
|
||||
```
|
||||
|
||||
你会看到类似:
|
||||
|
||||
```bash
|
||||
cmii-sky-converge-6f7c8d9b4d 12 0 repo/app:v1.2.2
|
||||
cmii-sky-converge-7a8b9c0d1e 13 2 repo/app:v1.2.3
|
||||
```
|
||||
|
||||
这里通常:
|
||||
|
||||
* **最大的 revision** 是当前版本
|
||||
* **倒数第二大的 revision** 就是上一个版本
|
||||
这些历史配置是保存在 ReplicaSet 中的。([Kubernetes][1])
|
||||
|
||||
### 3)如果只是回滚到“上一个版本”
|
||||
|
||||
直接执行:
|
||||
|
||||
```bash
|
||||
kubectl -n cq-fly-260311 rollout undo deployment/cmii-sky-converge
|
||||
```
|
||||
|
||||
这是官方支持的标准写法,会把 Deployment 回滚到上一次部署状态。([Kubernetes][2])
|
||||
|
||||
### 4)如果你已经从 ReplicaSet 确认了上一个 revision,按 revision 回滚
|
||||
|
||||
例如上一个版本是 `revision=12`:
|
||||
|
||||
```bash
|
||||
kubectl -n cq-fly-260311 rollout undo deployment/cmii-sky-converge --to-revision=12
|
||||
```
|
||||
|
||||
`--to-revision` 就是官方提供的指定修订版本回滚参数。([Kubernetes][2])
|
||||
|
||||
### 5)回滚前先预览一下
|
||||
|
||||
如果你想先试运行:
|
||||
|
||||
```bash
|
||||
kubectl -n cq-fly-260311 rollout undo deployment/cmii-sky-converge --dry-run=server
|
||||
```
|
||||
|
||||
### 6)回滚后确认状态
|
||||
|
||||
```bash
|
||||
kubectl -n cq-fly-260311 rollout status deployment/cmii-sky-converge
|
||||
kubectl -n cq-fly-260311 get deploy cmii-sky-converge -o wide
|
||||
kubectl -n cq-fly-260311 get rs \
|
||||
-o custom-columns=NAME:.metadata.name,REVISION:.metadata.annotations.deployment\.kubernetes\.io/revision,REPLICAS:.spec.replicas,IMAGE:.spec.template.spec.containers[*].image \
|
||||
| grep cmii-sky-converge
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 一套可直接执行的命令
|
||||
|
||||
如果你就是想“先看上一个版本,再回滚”:
|
||||
|
||||
```bash
|
||||
# 1. 查看当前 deployment 的历史对应的 ReplicaSet 和镜像
|
||||
kubectl -n cq-fly-260311 get rs \
|
||||
-o custom-columns=NAME:.metadata.name,REVISION:.metadata.annotations.deployment\.kubernetes\.io/revision,REPLICAS:.spec.replicas,IMAGE:.spec.template.spec.containers[*].image \
|
||||
| grep cmii-sky-converge | sort -k2 -n
|
||||
|
||||
# 2. 回滚到上一个版本
|
||||
kubectl -n cq-fly-260311 rollout undo deployment/cmii-sky-converge
|
||||
|
||||
# 3. 查看回滚结果
|
||||
kubectl -n cq-fly-260311 rollout status deployment/cmii-sky-converge
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 如果你想精确拿到“上一个 ReplicaSet 的镜像”
|
||||
|
||||
可以用这个:
|
||||
|
||||
```bash
|
||||
kubectl -n cq-fly-260311 get rs \
|
||||
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.annotations.deployment\.kubernetes\.io/revision}{"\t"}{.spec.template.spec.containers[*].image}{"\n"}{end}' \
|
||||
| grep cmii-sky-converge | sort -k2 -n
|
||||
```
|
||||
|
||||
然后选倒数第二行,就是上一个版本的 revision 和镜像。
|
||||
|
||||
你要的话,我可以再给你一版 **一行 shell 命令**,自动找出 `cmii-sky-converge` 的上一个 revision 并直接执行回滚。
|
||||
|
||||
[1]: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/?utm_source=chatgpt.com "Deployments - Kubernetes"
|
||||
[2]: https://kubernetes.io/zh-cn/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_undo/?utm_source=chatgpt.com "kubectl rollout undo | Kubernetes"
|
||||
48
998-常用脚本/更新脚本/配合dltu的镜像更新脚本.sh
Normal file
48
998-常用脚本/更新脚本/配合dltu的镜像更新脚本.sh
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 1. 定义命名空间
|
||||
NAMESPACE="bj-sh-uas-260511"
|
||||
|
||||
IMAGE_NAME_PREFIX="192.168.3.31:8088/cmii"
|
||||
|
||||
# 检查输入文件是否存在
|
||||
if [ ! -f "$1" ]; then
|
||||
echo "使用方法: $0 <镜像列表文件>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "开始更新命名空间 ${NAMESPACE} 下的 Deployment..."
|
||||
|
||||
# 2. 逐行读取文件内容
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
# 忽略空行
|
||||
[ -z "$line" ] && continue
|
||||
|
||||
# 以 = 为分隔符提取:
|
||||
# 第3项为 Deployment 名称
|
||||
# 第4项为 镜像 Tag
|
||||
DEPLOY_NAME=$(echo "$line" | cut -d'=' -f3)
|
||||
IMAGE_TAG=$(echo "$line" | cut -d'=' -f4 | sed 's/.tar.gz//')
|
||||
|
||||
# 假设容器名称(Container Name)与 Deployment 名称一致
|
||||
# 这是 Kubernetes 部署中的常见规范。如果不一致,请修改 --image 后面的第一个参数。
|
||||
IMAGE_NAME="${IMAGE_NAME_PREFIX}/${DEPLOY_NAME}:${IMAGE_TAG}"
|
||||
|
||||
echo "------------------------------------------------"
|
||||
echo "正在更新: ${DEPLOY_NAME}"
|
||||
echo "目标版本: ${IMAGE_TAG}"
|
||||
|
||||
# 3. 使用 kubectl 执行更新
|
||||
# 格式:kubectl set image deployment/<name> <container_name>=<new_image> -n <ns>
|
||||
kubectl set image deployment/"${DEPLOY_NAME}" "${DEPLOY_NAME}"="${IMAGE_NAME}" -n "${NAMESPACE}"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ 提交成功"
|
||||
else
|
||||
echo "❌ 提交失败,请检查 Deployment 名称是否正确"
|
||||
fi
|
||||
|
||||
done < "$1"
|
||||
|
||||
echo "------------------------------------------------"
|
||||
echo "所有更新指令已发送完毕。"
|
||||
Reference in New Issue
Block a user