更新时间:2024-09-14 GMT+08:00
分享

配置update_hosts_linux.sh脚本

根据提供的脚本示例,结合实际情况,修改示例中的相关配置。

前提条件

已完成准备工作

操作步骤

  1. 在执行脚本的主机上创建一个名为“update_hosts_linux.sh”的文件,然后将以下脚本示例的内容复制到文件中。如果您已经通过SSH连接到源端Linux主机,可以直接使用vim创建和编辑脚本文件,步骤如下:

    1. 在Vim编辑器中按 i 进入插入模式。
    2. 复制并粘贴脚本代码,完成后按 Esc。
    3. 输入 :wq 保存并退出。
    #!/bin/bash
     
    # Configuration
    # Log directory path: Used to store run logs, error logs, and summary logs.
    # If the directory doesn't exist, the script will create it automatically.
    LOG_DIR="/var/log/update_hosts"
     
    # Run log file path: Records detailed information about the script's execution.
    RUN_LOG="$LOG_DIR/run.log"
     
    # Error log file path: Records any errors that occur during the script's execution.
    ERROR_LOG="$LOG_DIR/error.log"
     
    # Summary log file path: Records a summary of the script's execution, including the number of successful and failed servers.
    SUMMARY_LOG="$LOG_DIR/summary.log"
     
    # CSV file path: Contains information about the target hosts (must be manually created and configured).
    CSV_FILE="target_servers.csv"
     
    # Hosts content file path: Contains the content to be appended to each target host's /etc/hosts file (must be manually created and configured).
    HOSTS_FILE="hosts_content.txt"
    DEFAULT_PORT=22
    SSH_TIMEOUT=10
     
    # Initialize log directory and files
    initialize_logs() {
        mkdir -p "$LOG_DIR"
        echo "========================================" >> "$RUN_LOG"
        echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') - Starting new update execution" >> "$RUN_LOG"
        echo "========================================" >> "$RUN_LOG"
     
        echo "========================================" >> "$ERROR_LOG"
        echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') - Starting new update execution" >> "$ERROR_LOG"
        echo "========================================" >> "$ERROR_LOG"
     
        echo "========================================" > "$SUMMARY_LOG"
        echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') - Starting new update execution" >> "$SUMMARY_LOG"
        echo "========================================" >> "$SUMMARY_LOG"
    }
     
    # Log info function
    log_info() {
        echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$RUN_LOG"
    }
     
    # Log error function
    log_error() {
        echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$RUN_LOG" "$ERROR_LOG"
    }
     
    # Read server information from CSV file
    read_servers_from_csv() {
        local csv_file="$1"
        local servers=()
        local header_skipped=false
     
        if [ ! -f "$csv_file" ]; then
            log_error "CSV file '$csv_file' not found."
            exit 1
        fi
     
        # Ensure file ends with a newline character
        sed -i -e '$a\' "$csv_file"
     
        while IFS=, read -r username ip port password; do
            # Skip header row
            if [ "$header_skipped" = false ]; then
                header_skipped=true
                continue
            fi
            # Skip empty and invalid rows
            if [[ -z "$username" || -z "$ip" ]]; then
                continue
            fi
            port=${port:-$DEFAULT_PORT} # Use default port 22
            # Ensure port is numeric
            if ! [[ "$port" =~ ^[0-9]+$ ]]; then
                log_error "Invalid port '$port' for $username@$ip. Skipping this server."
                continue
            fi
            servers+=("$username@$ip:$port:$password")
        done < "$csv_file"
     
        echo "${servers[@]}"
    }
     
    # Read hosts content from TXT file
    read_hosts_content_from_txt() {
        local txt_file="$1"
        if [ -f "$txt_file" ]; then
            cat "$txt_file"
        else
            log_error "Hosts content file '$txt_file' not found."
            exit 1
        fi
    }
     
    # Initialize log files
    initialize_logs
     
    # Read server information from CSV file
    servers=($(read_servers_from_csv "$CSV_FILE"))
     
    # Read hosts content from TXT file
    hosts_content=$(read_hosts_content_from_txt "$HOSTS_FILE")
     
    # Counters for success and failure
    success_count=0
    failure_count=0
    failed_servers=()
     
    # Iterate over each server and push hosts content
    for server in "${servers[@]}"; do
      # Extract user, IP, port, and password information
      IFS=':' read -r user_host port pass <<< "$server"
      IFS='@' read -r user ip <<< "$user_host"
      
      log_info "Starting update for $user@$ip:$port"
     
      # Create temporary script and SSH_ASKPASS script
      tmp_script=$(mktemp)
      askpass_script=$(mktemp)
     
      cat <<EOF > "$tmp_script"
    #!/bin/bash
    # Backup hosts file
    if [ ! -f /etc/hosts.bak ]; then
      cp /etc/hosts /etc/hosts.bak
    fi
     
    # Remove old Migration-proxy section
    sed -i '/#Migration-proxy-start/,/#Migration-proxy-end/d' /etc/hosts
     
    # Append new Migration-proxy section
    echo "$hosts_content" >> /etc/hosts
    EOF
     
      cat <<EOF > "$askpass_script"
    #!/bin/bash
    echo "$pass"
    EOF
     
      chmod +x "$tmp_script" "$askpass_script"
     
      # Set SSH_ASKPASS environment variable and use ssh to connect to the target machine and execute the temporary script
      export SSH_ASKPASS="$askpass_script"
      export DISPLAY=:0
     
      ssh_output=$(mktemp)
      setsid ssh -o BatchMode=no -o ConnectTimeout=$SSH_TIMEOUT -o StrictHostKeyChecking=no -p "$port" "$user@$ip" 'bash -s' < "$tmp_script" 2> "$ssh_output"
      ssh_status=$?
     
      if [ $ssh_status -eq 0 ]; then
        log_info "Updated hosts on $ip:$port successfully"
        ((success_count++))
      else
        ssh_error=$(cat "$ssh_output")
        case $ssh_status in
          1)
            log_error "General error occurred while updating hosts on $ip:$port: $ssh_error"
            ;;
          2)
            log_error "Misuse of shell builtins while updating hosts on $ip:$port: $ssh_error"
            ;;
          255)
            if [[ "$ssh_error" == *"Permission denied"* ]]; then
              log_error "SSH login failed for $user@$ip:$port: Permission denied (password may be incorrect or username is wrong)"
            elif [[ "$ssh_error" == *"Connection refused"* ]]; then
              log_error "SSH login failed for $user@$ip:$port: Connection refused (port may be incorrect or SSH service not running on target)"
            elif [[ "$ssh_error" == *"No route to host"* ]]; then
              log_error "SSH login failed for $user@$ip:$port: No route to host (network unreachable)"
            elif [[ "$ssh_error" == *"Host key verification failed"* ]]; then
              log_error "SSH login failed for $user@$ip:$port: Host key verification failed"
            elif [[ "$ssh_error" == *"Connection timed out"* ]]; then
              log_error "SSH login failed for $user@$ip:$port: Connection timed out"
            else
              log_error "SSH login failed for $user@$ip:$port: $ssh_error"
            fi
            ;;
          *)
            log_error "An unknown error occurred while updating hosts on $ip:$port: $ssh_error"
            ;;
        esac
        failed_servers+=("$user@$ip:$port")
        ((failure_count++))
      fi
     
      # Remove temporary scripts and SSH output file
      rm -f "$tmp_script" "$askpass_script" "$ssh_output"
    done
     
    # Calculate failure and success percentages
    total_count=${#servers[@]}
    failure_percentage=$(echo "scale=2; ($failure_count / $total_count) * 100" | bc)
    success_percentage=$(echo "scale=2; ($success_count / $total_count) * 100" | bc)
     
    # Output summary result and log to file
    summary_content=$(cat <<EOF
    ========================================
    [SUMMARY] $(date '+%Y-%m-%d %H:%M:%S') - Execution Update Summary
    ========================================
    Total number of servers: $total_count
    Number of successful updates: $success_count
    Number of failed updates: $failure_count
    Success rate: $success_percentage%
    Failure rate: $failure_percentage%
    ----------------------------------------
    EOF
    )
     
    if [ $failure_count -gt 0 ]; then
        summary_content+="Failed servers:\n"
        for server in "${failed_servers[@]}"; do
            summary_content+="  - $server\n"
        done
    fi
    summary_content+="========================================"
     
    # Output summary result to log file and terminal
    echo -e "$summary_content" | tee -a "$SUMMARY_LOG"
     
    log_info "Script execution completed. Check $SUMMARY_LOG for summary."

  2. 根据实际情况,修改脚本中的以下配置项参数:

    • LOG_DIR="/var/log/update_hosts"
      • 描述:日志目录路径,用于存放运行日志、错误日志和总结日志的文件夹路径。
      • 参数默认值: /var/log/update_hosts
      • 修改建议:修改为当前用户具有写入权限的目录路径。
      • 修改示例:LOG_DIR="/home/username/update_hosts_logs"
    • CSV_FILE="target_servers.csv"
      • 描述CSV文件路径,包含源端主机信息。
      • 参数默认值:target_servers.csv
      • 修改建议:使用绝对路径,或确保相对路径是正确的。
      • 修改示例:CSV_FILE="/home/username/configs/servers.csv"
    • HOSTS_FILE="hosts_content.txt"
      • 描述Hosts文件存放路径,包含要追加到源端主机 /etc/hosts 文件中的内容。
      • 参数默认值:hosts_content.txt
      • 修改建议:使用绝对路径,或确保相对路径是正确的。
      • 修改示例:HOSTS_FILE="/home/username/configs/hosts_content.txt"

  3. 配置项参数修改完成并保存后,在终端窗口(如果有图形化界面可以按Ctrl+Alt+T打开终端)执行脚本:

    ./update_hosts_linux.sh

    脚本会在终端窗口中输出日志信息,并在执行完毕后生成一个执行结果报告,可以在LOG_DIR 指定目录中的 summary.log 文件中查看。

相关文档