#!/bin/bash ################################################################################ # Linux 系统初始化脚本 v1.2 # 功能: 镜像源切换 | 基础工具安装 | 系统优化配置 # 支持: Ubuntu/Debian, CentOS/RHEL, Rocky Linux, AlmaLinux # 作者: 自动化运维工具 # 使用: sudo ./init_system.sh [--auto] [--mirror=aliyun] [--non-interactive] ################################################################################ set -euo pipefail # 颜色定义 - 用于终端彩色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' PURPLE='\033[0;35m' NC='\033[0m' # No Color # 日志文件路径 - 使用用户可写目录 LOG_DIR="$HOME/.system-init-logs" LOG_FILE="$LOG_DIR/system-init-$(date +%Y%m%d-%H%M%S).log" # 初始化日志系统 init_logging() { # 创建日志目录 mkdir -p "$LOG_DIR" # 设置日志文件 exec > >(tee -a "$LOG_FILE") 2>&1 } # 输出函数定义 print_info() { echo -e "${BLUE}[INFO]${NC} $1" } print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # 错误处理函数 error_exit() { print_error "$1" echo "详细日志请查看: $LOG_FILE" exit 1 } # 脚本横幅显示 print_banner() { clear echo -e "${PURPLE}" echo "==================================================" echo " Linux 系统初始化脚本 v1.2" echo "==================================================" echo "功能: 镜像源切换 | 基础工具安装 | 系统优化配置" echo "支持: Ubuntu/Debian, CentOS/RHEL, Rocky, AlmaLinux" echo "==================================================" echo -e "${NC}" } # 检查脚本运行权限 check_permissions() { print_info "检查运行权限..." # 检查是否可以使用 sudo if [[ $EUID -eq 0 ]]; then print_success "当前为 root 用户" return 0 fi # 检查是否有 sudo 权限 if sudo -n true 2>/dev/null; then print_success "当前用户有 sudo 权限" return 0 fi # 如果没有 root 权限也没有 sudo 权限,尝试获取 print_info "尝试获取 sudo 权限..." if ! sudo -v; then error_exit "此脚本需要 root 权限或 sudo 权限\n请使用: sudo $0" fi print_success "权限检查通过" } # 检查命令是否存在 check_command() { if ! command -v "$1" &> /dev/null; then print_warning "命令 $1 未找到" return 1 fi return 0 } # 检测操作系统类型和版本 detect_os() { print_info "正在检测操作系统..." # 检查 /etc/os-release 文件是否存在 if [[ ! -f /etc/os-release ]]; then error_exit "无法检测操作系统: /etc/os-release 文件不存在" fi # 加载操作系统信息 . /etc/os-release # 设置全局变量 OS="$ID" OS_NAME="$NAME" OS_VERSION="${VERSION_ID:-unknown}" # 显示检测结果 print_success "操作系统: $OS_NAME $OS_VERSION" # 检测网络环境 detect_network } # 检测网络环境(国内/国际) detect_network() { print_info "正在检测网络环境..." # 测试多个网站,增加检测准确性 local test_sites=("www.baidu.com" "mirrors.aliyun.com") local china_count=0 for site in "${test_sites[@]}"; do if timeout 3 curl -s --head "$site" > /dev/null 2>&1; then ((china_count++)) fi done # 根据检测结果判断网络环境 if [[ $china_count -gt 0 ]]; then NETWORK_ENV="china" print_info "检测到国内网络环境,建议使用国内镜像源" else NETWORK_ENV="international" print_info "检测到国际网络环境" fi } # 备份原始软件源 backup_sources() { print_info "正在备份原始软件源..." local backup_dir="$LOG_DIR/backup-$(date +%Y%m%d)" mkdir -p "$backup_dir" case $OS in ubuntu|debian) # 备份 sources.list if [[ -f /etc/apt/sources.list ]]; then sudo cp /etc/apt/sources.list "$backup_dir/sources.list.bak" print_success "已备份到 $backup_dir/sources.list.bak" fi # 备份 sources.list.d 目录 if [[ -d /etc/apt/sources.list.d ]]; then sudo cp -r /etc/apt/sources.list.d "$backup_dir/" print_success "已备份 sources.list.d 目录" fi ;; centos|rhel|rocky|almalinux) # 备份所有 .repo 文件 if ls /etc/yum.repos.d/*.repo &> /dev/null; then sudo cp /etc/yum.repos.d/*.repo "$backup_dir/" print_success "已备份到 $backup_dir/" else print_warning "未找到 .repo 文件,跳过备份" fi ;; *) print_warning "不支持的操作系统,跳过备份" ;; esac } # 配置 Ubuntu/Debian 镜像源 configure_ubuntu_mirrors() { print_info "正在配置 Ubuntu/Debian 镜像源..." # 获取 Ubuntu 版本代号 local ubuntu_codename if command -v lsb_release &> /dev/null; then ubuntu_codename=$(lsb_release -cs) else # 根据版本号推测代号 case "$OS_VERSION" in "22.04") ubuntu_codename="jammy" ;; "20.04") ubuntu_codename="focal" ;; "18.04") ubuntu_codename="bionic" ;; "16.04") ubuntu_codename="xenial" ;; *) ubuntu_codename="jammy" ;; esac fi # 选择镜像源 local mirror_url="" local mirror_name="" if [[ -n "${MIRROR_ARG:-}" ]]; then case "${MIRROR_ARG}" in aliyun) mirror_url="http://mirrors.aliyun.com" mirror_name="阿里云" ;; tsinghua) mirror_url="https://mirrors.tuna.tsinghua.edu.cn" mirror_name="清华大学" ;; ustc) mirror_url="https://mirrors.ustc.edu.cn" mirror_name="中国科技大学" ;; *) print_warning "未知的镜像源参数,使用交互式选择" MIRROR_ARG="" ;; esac fi # 交互式选择镜像源 if [[ -z "$mirror_url" ]] && [[ -z "${NON_INTERACTIVE:-}" ]]; then echo "" echo "请选择镜像源:" echo "1) 阿里云 (推荐国内用户)" echo "2) 清华大学" echo "3) 中国科技大学" echo "4) 官方源 (推荐国际用户)" echo "" read -rp "请选择 [1-4, 默认: 1]: " mirror_choice mirror_choice=${mirror_choice:-1} case $mirror_choice in 1) mirror_url="http://mirrors.aliyun.com" mirror_name="阿里云" ;; 2) mirror_url="https://mirrors.tuna.tsinghua.edu.cn" mirror_name="清华大学" ;; 3) mirror_url="https://mirrors.ustc.edu.cn" mirror_name="中国科技大学" ;; 4) mirror_url="http://archive.ubuntu.com" mirror_name="官方源" ;; *) mirror_url="http://mirrors.aliyun.com" mirror_name="阿里云" ;; esac elif [[ -z "$mirror_url" ]]; then # 非交互模式默认使用阿里云 mirror_url="http://mirrors.aliyun.com" mirror_name="阿里云" fi print_info "正在配置 $mirror_name 镜像源..." # 生成新的 sources.list if [[ "$mirror_url" == "http://archive.ubuntu.com" ]]; then sudo tee /etc/apt/sources.list > /dev/null < /dev/null < /dev/null < /dev/null < /dev/null; then print_warning "SSH 服务未安装" case $OS in ubuntu|debian) sudo apt-get install -y openssh-server ;; centos|rhel|rocky|almalinux) sudo yum install -y openssh-server ;; esac fi if [[ -z "${NON_INTERACTIVE:-}" ]]; then read -rp "是否优化 SSH 配置? [y/N]: " config_ssh config_ssh=${config_ssh:-N} if [[ ! $config_ssh =~ ^[Yy]$ ]]; then print_info "跳过 SSH 配置" return fi fi # 备份 SSH 配置 sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak # 优化 SSH 配置 sudo sed -i 's/#UseDNS yes/UseDNS no/' /etc/ssh/sshd_config sudo sed -i 's/GSSAPIAuthentication yes/GSSAPIAuthentication no/' /etc/ssh/sshd_config if ! grep -q "ClientAliveInterval" /etc/ssh/sshd_config; then echo "ClientAliveInterval 60" | sudo tee -a /etc/ssh/sshd_config echo "ClientAliveCountMax 3" | sudo tee -a /etc/ssh/sshd_config fi # 重启 SSH 服务 if command -v systemctl &> /dev/null; then sudo systemctl restart sshd 2>/dev/null || sudo systemctl restart ssh 2>/dev/null else sudo service sshd restart 2>/dev/null || sudo service ssh restart 2>/dev/null fi print_success "SSH 配置优化完成" } # 配置时区 configure_timezone() { print_info "正在配置时区..." if [[ -z "${NON_INTERACTIVE:-}" ]]; then read -rp "是否设置为中国时区 (Asia/Shanghai)? [Y/n]: " set_tz set_tz=${set_tz:-Y} else set_tz="Y" fi if [[ $set_tz =~ ^[Yy]$ ]]; then if command -v timedatectl &> /dev/null; then sudo timedatectl set-timezone Asia/Shanghai else sudo ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime fi print_success "时区已设置为 Asia/Shanghai" fi } # 系统优化配置 optimize_system() { print_info "正在应用系统优化配置..." if [[ -z "${NON_INTERACTIVE:-}" ]]; then read -rp "是否应用系统优化配置? [Y/n]: " do_optimize do_optimize=${do_optimize:-Y} if [[ ! $do_optimize =~ ^[Yy]$ ]]; then print_info "跳过系统优化" return fi fi # 优化文件描述符限制 if ! grep -q "^* soft nofile 65535" /etc/security/limits.conf; then echo "* soft nofile 65535" | sudo tee -a /etc/security/limits.conf echo "* hard nofile 65535" | sudo tee -a /etc/security/limits.conf fi # 优化内核参数 sudo tee /etc/sysctl.d/99-custom.conf > /dev/null </dev/null || true print_success "系统优化配置完成" } # 清理系统 clean_system() { print_info "正在清理系统..." if [[ -z "${NON_INTERACTIVE:-}" ]]; then read -rp "是否清理系统缓存和无用包? [Y/n]: " do_clean do_clean=${do_clean:-Y} if [[ ! $do_clean =~ ^[Yy]$ ]]; then print_info "跳过系统清理" return fi fi case $OS in ubuntu|debian) sudo apt-get autoremove -y sudo apt-get autoclean -y ;; centos|rhel|rocky|almalinux) sudo yum autoremove -y sudo yum clean all ;; esac print_success "系统清理完成" } # 显示系统信息 show_system_info() { echo "" print_success "==================== 系统信息 ====================" echo "" echo "操作系统: $(cat /etc/os-release | grep PRETTY_NAME | cut -d'"' -f2)" echo "内核版本: $(uname -r)" echo "系统架构: $(uname -m)" if command -v nproc &> /dev/null; then echo "CPU 核心: $(nproc)" fi if command -v free &> /dev/null; then echo "内存大小: $(free -h | awk '/^Mem:/ {print $2}')" fi if command -v df &> /dev/null; then echo "磁盘空间: $(df -h / | awk 'NR==2 {print $2}')" fi echo "当前用户: $(whoami)" echo "主机名称: $(hostname)" if command -v timedatectl &> /dev/null; then echo "时区设置: $(timedatectl | grep "Time zone" | awk '{print $3}')" fi echo "" print_success "==================================================" } # 显示主菜单 show_menu() { echo "" echo "请选择要执行的操作:" echo "" echo "1) 完整初始化 (推荐)" echo " - 更换镜像源" echo " - 安装基础工具" echo " - 系统优化" echo " - SSH 配置" echo " - 时区设置" echo " - 系统清理" echo "" echo "2) 仅更换镜像源" echo "3) 仅安装基础工具" echo "4) 仅系统优化" echo "5) 显示系统信息" echo "6) 退出" echo "" } # 完整初始化流程 full_initialization() { print_info "开始完整系统初始化..." # 1. 备份原始配置 backup_sources # 2. 配置镜像源 case $OS in ubuntu|debian) configure_ubuntu_mirrors || { print_warning "镜像源配置失败,继续其他步骤..." } ;; centos|rhel|rocky|almalinux) configure_centos_mirrors || { print_warning "镜像源配置失败,继续其他步骤..." } ;; *) print_warning "暂不支持该系统的镜像源配置" ;; esac # 3. 安装基础工具 install_basic_tools # 4. 配置时区 configure_timezone # 5. 配置 SSH configure_ssh # 6. 系统优化 optimize_system # 7. 系统清理 clean_system print_success "系统初始化完成!" # 显示系统信息 show_system_info echo "" print_info "日志文件: $LOG_FILE" print_info "建议重启系统使所有配置生效" echo "" } # 显示帮助信息 show_help() { echo "" echo "Linux 系统初始化脚本 v1.2" echo "" echo "用法: $0 [选项]" echo "" echo "选项:" echo " --auto 自动模式 (非交互式,使用默认配置)" echo " --mirror=SOURCE 指定镜像源 (aliyun, tsinghua, ustc)" echo " --non-interactive 非交互模式 (跳过所有确认)" echo " --help 显示此帮助信息" echo "" echo "示例:" echo " sudo $0" echo " sudo $0 --auto" echo " sudo $0 --mirror=aliyun --non-interactive" echo "" } # 解析命令行参数 parse_arguments() { while [[ $# -gt 0 ]]; do case $1 in --auto) AUTO_MODE=1 NON_INTERACTIVE=1 MIRROR_ARG="aliyun" shift ;; --mirror=*) MIRROR_ARG="${1#*=}" shift ;; --non-interactive) NON_INTERACTIVE=1 shift ;; --help|-h) show_help exit 0 ;; *) print_error "未知参数: $1" show_help exit 1 ;; esac done } # 主函数 main() { # 初始化日志系统 init_logging print_info "脚本开始执行" print_info "日志文件: $LOG_FILE" print_info "开始时间: $(date)" # 解析命令行参数 parse_arguments "$@" # 显示横幅 print_banner # 检查权限 check_permissions # 检测操作系统 detect_os # 自动模式直接执行完整初始化 if [[ -n "${AUTO_MODE:-}" ]]; then full_initialization exit 0 fi # 交互式菜单 while true; do show_menu read -rp "请选择操作 [1-6]: " choice case $choice in 1) full_initialization break ;; 2) backup_sources case $OS in ubuntu|debian) configure_ubuntu_mirrors ;; centos|rhel|rocky|almalinux) configure_centos_mirrors ;; esac ;; 3) install_basic_tools ;; 4) optimize_system ;; 5) show_system_info ;; 6) print_info "退出脚本" echo "详细日志请查看: $LOG_FILE" exit 0 ;; *) print_warning "无效选择,请重新输入" ;; esac # 询问是否继续 if [[ $choice -ne 6 ]]; then echo "" read -rp "是否继续其他操作? [Y/n]: " continue_choice continue_choice=${continue_choice:-Y} if [[ ! $continue_choice =~ ^[Yy]$ ]]; then print_info "退出脚本" echo "详细日志请查看: $LOG_FILE" exit 0 fi fi done } # 脚本入口点 main "$@"