完成 72绵阳项目 71雄安集团监管平台 大量优化更新

This commit is contained in:
zeaslity
2026-02-03 17:07:28 +08:00
parent d962ace967
commit a8f6bda703
93 changed files with 21632 additions and 185 deletions

View File

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

View File

@@ -0,0 +1,504 @@
#!/usr/bin/env bash
#==============================================================================
# APT Source Switcher - Ubuntu -> TUNA (Tsinghua University) Mirror
#
# Author: Smith Wang
# Version: 1.0.0
# License: MIT
#==============================================================================
# Module Dependencies:
# - bash (>= 5.0)
# - coreutils: cp, mv, mkdir, date, id, chmod, chown
# - util-linux / distro tools: (optional) lsb_release
# - text tools: sed, awk, grep
# - apt: apt-get
#
# Notes:
# - Ubuntu 24.04 typically uses Deb822 sources file: /etc/apt/sources.list.d/ubuntu.sources
# - Ubuntu 20.04/22.04 often uses traditional /etc/apt/sources.list
#==============================================================================
set -euo pipefail
IFS=$'\n\t'
umask 022
#------------------------------------------------------------------------------
# Global Constants
#------------------------------------------------------------------------------
readonly SCRIPT_NAME="$(basename "$0")"
readonly SCRIPT_VERSION="1.0.0"
readonly TUNA_UBUNTU_URI="https://mirrors.tuna.tsinghua.edu.cn/ubuntu/"
readonly DEFAULT_BACKUP_DIR="/etc/apt/backup"
readonly APT_SOURCES_LIST="/etc/apt/sources.list"
readonly APT_DEB822_SOURCES="/etc/apt/sources.list.d/ubuntu.sources"
# Log levels: DEBUG=0, INFO=1, WARN=2, ERROR=3
readonly LOG_LEVEL_DEBUG=0
readonly LOG_LEVEL_INFO=1
readonly LOG_LEVEL_WARN=2
readonly LOG_LEVEL_ERROR=3
#------------------------------------------------------------------------------
# Runtime Variables (defaults)
#------------------------------------------------------------------------------
log_level="$LOG_LEVEL_INFO"
backup_dir="$DEFAULT_BACKUP_DIR"
do_update="false"
assume_yes="false"
ubuntu_codename=""
ubuntu_version_id=""
sources_mode="" # "deb822" or "list"
#------------------------------------------------------------------------------
# Function Call Graph (ASCII)
#
# main
# |
# +--> parse_args
# +--> setup_traps
# +--> require_root
# +--> detect_ubuntu
# | |
# | +--> read_os_release
# |
# +--> choose_sources_mode
# +--> ensure_backup_dir
# +--> backup_sources
# +--> confirm_action
# +--> apply_tuna_sources
# | |
# | +--> write_sources_list_tuna
# | +--> patch_deb822_sources_tuna
# |
# +--> apt_update (optional)
# +--> summary
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Logging
#------------------------------------------------------------------------------
### Log message with level.
# @param level int Numeric log level (0=DEBUG,1=INFO,2=WARN,3=ERROR)
# @param message string Message to print
# @return 0 success
# @require date printf
log() {
local level="$1"
local message="$2"
if [[ "$level" -lt "$log_level" ]]; then
return 0
fi
local level_name="INFO"
case "$level" in
0) level_name="DEBUG" ;;
1) level_name="INFO" ;;
2) level_name="WARN" ;;
3) level_name="ERROR" ;;
*) level_name="INFO" ;;
esac
# > Use RFC3339-ish timestamp to help operations & auditing
printf '%s [%s] %s: %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$level_name" "$SCRIPT_NAME" "$message" >&2
}
### Convenience wrappers.
# @return 0
log_debug() { log "$LOG_LEVEL_DEBUG" "$1"; }
log_info() { log "$LOG_LEVEL_INFO" "$1"; }
log_warn() { log "$LOG_LEVEL_WARN" "$1"; }
log_error() { log "$LOG_LEVEL_ERROR" "$1"; }
#------------------------------------------------------------------------------
# Error handling / traps
#------------------------------------------------------------------------------
### Trap handler for unexpected errors.
# @param exit_code int Exit code
# @param line_no int Line number where error occurred
# @param cmd string The command that failed
# @return 0
# @require printf
on_err() {
local exit_code="$1"
local line_no="$2"
local cmd="$3"
log_error "Script failed (exit=${exit_code}) at line ${line_no}: ${cmd}"
}
### Cleanup handler (reserved for future extension).
# @return 0
# @require true
on_exit() {
true
}
### Setup traps for ERR and EXIT.
# @return 0
# @require trap
setup_traps() {
# > Preserve error context with BASH_LINENO and BASH_COMMAND
trap 'on_err "$?" "${LINENO}" "${BASH_COMMAND}"' ERR
trap 'on_exit' EXIT
}
#------------------------------------------------------------------------------
# Utility / validation
#------------------------------------------------------------------------------
### Print usage.
# @return 0
# @require cat
usage() {
cat <<'EOF'
Usage:
sudo ./apt_tuna_switch.sh [options]
Options:
-y, --yes Non-interactive; do not prompt.
-u, --update Run "apt-get update" after switching.
-b, --backup-dir Backup directory (default: /etc/apt/backup)
-d, --debug Enable DEBUG logs.
-h, --help Show help.
Examples:
sudo ./apt_tuna_switch.sh -y -u
sudo ./apt_tuna_switch.sh --backup-dir /root/apt-bak --update
EOF
}
### Parse CLI arguments.
# @param args string[] CLI args
# @return 0 success
# @require printf
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
-y|--yes)
assume_yes="true"
shift
;;
-u|--update)
do_update="true"
shift
;;
-b|--backup-dir)
if [[ $# -lt 2 ]]; then
log_error "Missing value for --backup-dir"
usage
exit 2
fi
backup_dir="$2"
shift 2
;;
-d|--debug)
log_level="$LOG_LEVEL_DEBUG"
shift
;;
-h|--help)
usage
exit 0
;;
*)
log_error "Unknown argument: $1"
usage
exit 2
;;
esac
done
}
### Ensure running as root.
# @return 0 if root; exit otherwise
# @require id
require_root() {
if [[ "$(id -u)" -ne 0 ]]; then
log_error "This script must be run as root. Try: sudo ./${SCRIPT_NAME}"
exit 1
fi
}
### Read /etc/os-release fields.
# @return 0
# @require awk grep
read_os_release() {
if [[ ! -r /etc/os-release ]]; then
log_error "Cannot read /etc/os-release"
exit 1
fi
# > Parse key fields safely
local os_id
os_id="$(awk -F= '$1=="ID"{gsub(/"/,"",$2); print $2}' /etc/os-release | head -n1 || true)"
ubuntu_version_id="$(awk -F= '$1=="VERSION_ID"{gsub(/"/,"",$2); print $2}' /etc/os-release | head -n1 || true)"
ubuntu_codename="$(awk -F= '$1=="VERSION_CODENAME"{gsub(/"/,"",$2); print $2}' /etc/os-release | head -n1 || true)"
if [[ "$os_id" != "ubuntu" ]]; then
log_error "Unsupported OS ID: ${os_id:-unknown}. This script supports Ubuntu only."
exit 1
fi
if [[ -z "$ubuntu_version_id" ]]; then
log_error "Failed to detect Ubuntu VERSION_ID from /etc/os-release"
exit 1
fi
# > For some environments, VERSION_CODENAME may be empty; try UBUNTU_CODENAME
if [[ -z "$ubuntu_codename" ]]; then
ubuntu_codename="$(awk -F= '$1=="UBUNTU_CODENAME"{gsub(/"/,"",$2); print $2}' /etc/os-release | head -n1 || true)"
fi
}
### Detect supported Ubuntu version and codename.
# @return 0 success; exit otherwise
# @require awk
detect_ubuntu() {
read_os_release
case "$ubuntu_version_id" in
"20.04") ubuntu_codename="${ubuntu_codename:-focal}" ;;
"22.04") ubuntu_codename="${ubuntu_codename:-jammy}" ;;
"24.04") ubuntu_codename="${ubuntu_codename:-noble}" ;;
*)
log_error "Unsupported Ubuntu version: ${ubuntu_version_id}. Supported: 20.04/22.04/24.04"
exit 1
;;
esac
if [[ -z "$ubuntu_codename" ]]; then
log_error "Failed to determine Ubuntu codename."
exit 1
fi
log_info "Detected Ubuntu ${ubuntu_version_id} (${ubuntu_codename})"
}
### Decide which sources format to manage.
# @return 0
# @require test
choose_sources_mode() {
if [[ -f "$APT_DEB822_SOURCES" ]]; then
sources_mode="deb822"
elif [[ -f "$APT_SOURCES_LIST" ]]; then
sources_mode="list"
else
# > Defensive: if neither exists, still proceed by creating sources.list
sources_mode="list"
fi
log_info "Sources mode: ${sources_mode}"
}
### Ensure backup directory exists.
# @param backup_dir string Directory path
# @return 0
# @require mkdir
ensure_backup_dir() {
local dir="$1"
if [[ -z "$dir" ]]; then
log_error "Backup directory is empty."
exit 1
fi
mkdir -p "$dir"
log_debug "Backup directory ensured: $dir"
}
### Backup an APT sources file if it exists.
# @param src_path string File path to backup
# @param backup_dir string Backup directory
# @return 0
# @require cp date
backup_file_if_exists() {
local src_path="$1"
local dir="$2"
if [[ ! -e "$src_path" ]]; then
log_warn "Skip backup (not found): $src_path"
return 0
fi
local ts
ts="$(date '+%Y%m%d-%H%M%S')"
local base
base="$(basename "$src_path")"
local dst="${dir}/${base}.${ts}.bak"
cp -a "$src_path" "$dst"
log_info "Backed up: $src_path -> $dst"
}
### Backup relevant source files.
# @return 0
# @require cp
backup_sources() {
backup_file_if_exists "$APT_SOURCES_LIST" "$backup_dir"
backup_file_if_exists "$APT_DEB822_SOURCES" "$backup_dir"
}
### Ask for confirmation unless --yes is given.
# @return 0 if confirmed; exit otherwise
# @require read
confirm_action() {
if [[ "$assume_yes" == "true" ]]; then
log_info "Non-interactive mode: --yes"
return 0
fi
log_warn "About to replace APT sources with TUNA mirror:"
log_warn " ${TUNA_UBUNTU_URI}"
log_warn "This will modify system APT source configuration."
printf "Continue? [y/N]: " >&2
local ans=""
read -r ans
case "$ans" in
y|Y|yes|YES) return 0 ;;
*) log_info "Cancelled by user."; exit 0 ;;
esac
}
#------------------------------------------------------------------------------
# Core actions
#------------------------------------------------------------------------------
### Write traditional /etc/apt/sources.list using TUNA mirror.
# @param codename string Ubuntu codename (focal/jammy/noble)
# @return 0
# @require cat chmod chown mv
write_sources_list_tuna() {
local codename="$1"
local tmp_file
tmp_file="$(mktemp)"
# > Provide standard suites: release, updates, backports, security
cat >"$tmp_file" <<EOF
#------------------------------------------------------------------------------#
# Ubuntu ${codename} - TUNA Mirror
# Generated by: ${SCRIPT_NAME} v${SCRIPT_VERSION}
# Mirror: ${TUNA_UBUNTU_URI}
#------------------------------------------------------------------------------#
deb ${TUNA_UBUNTU_URI} ${codename} main restricted universe multiverse
deb ${TUNA_UBUNTU_URI} ${codename}-updates main restricted universe multiverse
deb ${TUNA_UBUNTU_URI} ${codename}-backports main restricted universe multiverse
deb ${TUNA_UBUNTU_URI} ${codename}-security main restricted universe multiverse
# If you want source packages, uncomment the following lines:
# deb-src ${TUNA_UBUNTU_URI} ${codename} main restricted universe multiverse
# deb-src ${TUNA_UBUNTU_URI} ${codename}-updates main restricted universe multiverse
# deb-src ${TUNA_UBUNTU_URI} ${codename}-backports main restricted universe multiverse
# deb-src ${TUNA_UBUNTU_URI} ${codename}-security main restricted universe multiverse
EOF
chmod 0644 "$tmp_file"
chown root:root "$tmp_file"
# > Atomic replace
mkdir -p "$(dirname "$APT_SOURCES_LIST")"
mv -f "$tmp_file" "$APT_SOURCES_LIST"
log_info "Updated: $APT_SOURCES_LIST"
}
### Patch Deb822 ubuntu.sources to use TUNA mirror.
# @param deb822_file string Path to ubuntu.sources
# @param tuna_uri string The TUNA mirror base URI
# @return 0
# @require sed cp mktemp chmod chown mv grep
patch_deb822_sources_tuna() {
local deb822_file="$1"
local tuna_uri="$2"
if [[ ! -f "$deb822_file" ]]; then
log_warn "Deb822 sources file not found: $deb822_file"
return 0
fi
local tmp_file
tmp_file="$(mktemp)"
cp -a "$deb822_file" "$tmp_file"
# > Replace any "URIs:" line to TUNA; keep other Deb822 fields unchanged.
# > Some systems may have multiple stanzas; this applies globally.
sed -i -E "s|^URIs:[[:space:]]+.*$|URIs: ${tuna_uri}|g" "$tmp_file"
# > Defensive check: ensure we still have at least one URIs line
if ! grep -qE '^URIs:[[:space:]]+' "$tmp_file"; then
log_error "Deb822 patch failed: no 'URIs:' line found after edit."
exit 1
fi
chmod 0644 "$tmp_file"
chown root:root "$tmp_file"
mv -f "$tmp_file" "$deb822_file"
log_info "Patched Deb822 sources: $deb822_file"
}
### Apply TUNA sources according to detected mode.
# @return 0
# @require true
apply_tuna_sources() {
case "$sources_mode" in
deb822)
patch_deb822_sources_tuna "$APT_DEB822_SOURCES" "$TUNA_UBUNTU_URI"
;;
list)
write_sources_list_tuna "$ubuntu_codename"
;;
*)
log_error "Unknown sources mode: $sources_mode"
exit 1
;;
esac
}
### Run apt-get update if requested.
# @return 0
# @require apt-get
apt_update() {
if [[ "$do_update" != "true" ]]; then
log_info "Skip apt-get update (use --update to enable)."
return 0
fi
log_info "Running: apt-get update"
# > Use noninteractive frontend to reduce prompts in some envs
DEBIAN_FRONTEND=noninteractive apt-get update
log_info "apt-get update completed."
}
### Print summary.
# @return 0
summary() {
log_info "Done."
log_info "Backup directory: ${backup_dir}"
log_info "Mirror applied: ${TUNA_UBUNTU_URI}"
log_info "Ubuntu: ${ubuntu_version_id} (${ubuntu_codename}), mode: ${sources_mode}"
}
#------------------------------------------------------------------------------
# Main
#------------------------------------------------------------------------------
### Main entry.
# @param args string[] CLI args
# @return 0 success; non-zero otherwise
# @require bash
main() {
parse_args "$@"
setup_traps
require_root
detect_ubuntu
choose_sources_mode
ensure_backup_dir "$backup_dir"
backup_sources
confirm_action
apply_tuna_sources
apt_update
summary
}
main "$@"

View File

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

View File

@@ -1,9 +1,8 @@
upstream proxy_server {
ip_hash;
server 192.168.0.2:30500;
server 192.168.0.4:30500;
server 192.168.0.5:30500;
server 192.168.0.6:30500;
server 192.168.1.4:30500;
server 192.168.1.3:30500;
server 192.168.1.5:30500;
}
server {
@@ -22,7 +21,7 @@ server {
proxy_buffering off;
proxy_buffer_size 4k;
proxy_buffers 4 12k;
proxy_set_header Host fake-domain.xakny.io;
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";

View File

@@ -6,7 +6,18 @@ cp kube_config_cluster.yml /root/.kube/config
kubectl apply -f k8s-dashboard.yaml
kubectl delete -f k8s-dashboard.yaml
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')
kubectl create token admin-user -n kubernetes-dashboard --duration=26280h
kubectl create token read-only-user -n kubernetes-dashboard --duration=26280h 1 token的管控
# 删除旧的绑定(为了保险起见,避免残留)
kubectl delete clusterrolebinding admin-user
# 重新创建绑定
kubectl create clusterrolebinding admin-user \
--clusterrole=cluster-admin \
--serviceaccount=kubernetes-dashboard:admin-user 3 重新生成token
kubectl create token admin-user -n kubernetes-dashboard --duration=26280h
## 你无法查看已经生成的 Token 列表。
kubectl apply -f k8s-nfs.yaml
kubectl delete -f k8s-nfs.yaml
@@ -16,10 +27,11 @@ kubectl -n kube-system describe pod $(kubectl -n kube-system get pods | grep nfs
kubectl apply -f k8s-nfs-test.yaml
kubectl delete -f k8s-nfs-test.yaml
# 在NFS-Server机器上执行
cd /var/lib/docker/nfs_data
kubectl create ns xakny
kubectl create ns sc-my-uav-260202
kubectl apply -f k8s-pvc.yaml
kubectl delete -f k8s-pvc.yaml
@@ -37,6 +49,9 @@ 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
kubectl apply -f k8s-mysql.yaml
kubectl delete -f k8s-mysql.yaml

View File

@@ -1,6 +1,6 @@
export harbor_host=192.168.0.2:8033
export harbor_host=192.168.1.4: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