eth0

create-bridge-eth0.sh
#!/bin/bash
#===============================================================================
# Script Name: create-bridge-eth0.sh
# Description: Create bridge configuration using NetworkManager 
#===============================================================================

#-------------------------------------------------------------------------------
# Configuration Area - Modify according to your environment
#-------------------------------------------------------------------------------
BRIDGE_NAME="br-lan"
BRIDGE_IP="192.168.2.99/24"
BRIDGE_GATEWAY="192.168.2.1"
BRIDGE_DNS="192.168.2.1"
PHYSICAL_IFACE="eth0"
SLAVE_CONN_NAME="eth0-bridge-port"

# Bridge Advanced Options
BRIDGE_STP="no"
BRIDGE_FORWARD_DELAY="0"

# Background Execution Options
BACKGROUND_MODE="yes"
LOG_FILE=""

#-------------------------------------------------------------------------------
# Color Definitions
#-------------------------------------------------------------------------------
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

#-------------------------------------------------------------------------------
# Logging Functions
#-------------------------------------------------------------------------------
log_info()    { echo -e "${BLUE}[INFO]${NC} $1"; [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1" >> "$LOG_FILE"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1" >> "$LOG_FILE"; }
log_warn()    { echo -e "${YELLOW}[WARN]${NC} $1";  [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $1" >> "$LOG_FILE"; }
log_error()   { echo -e "${RED}[ERROR]${NC} $1";   [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1" >> "$LOG_FILE"; }

#-------------------------------------------------------------------------------
# Background Mode Functions
#-------------------------------------------------------------------------------
init_background_mode() {
    if [[ "$BACKGROUND_MODE" == "yes" ]]; then
        LOG_FILE="$(dirname "$0")/bridge-setup-$(date +%Y%m%d-%H%M%S).log"
        exec > >(tee -a "$LOG_FILE")
        exec 2>&1
        log_info "Running in background mode, log file: $LOG_FILE"
    fi
}

write_error_exit() {
    local exit_code=$1
    local error_msg=$2
    if [[ -n "$LOG_FILE" ]]; then
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] [FATAL] Script failed with exit code $exit_code" >> "$LOG_FILE"
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] [FATAL] Error: $error_msg" >> "$LOG_FILE"
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] [FATAL] Failed at: ${BASH_SOURCE[1]}:${BASH_LINENO[0]}" >> "$LOG_FILE"
        echo "" >> "$LOG_FILE"
        echo "=== Last 20 lines of NetworkManager log ===" >> "$LOG_FILE"
        journalctl -u NetworkManager -n 20 --no-pager 2>/dev/null >> "$LOG_FILE" || true
        echo "" >> "$LOG_FILE"
        echo "=== Current network status ===" >> "$LOG_FILE"
        ip addr >> "$LOG_FILE" 2>&1
        echo "" >> "$LOG_FILE"
        echo "=== NetworkManager connections ===" >> "$LOG_FILE"
        nmcli connection show >> "$LOG_FILE" 2>&1
    fi
    exit $exit_code
}

#-------------------------------------------------------------------------------
# Check Root Privileges
#-------------------------------------------------------------------------------
check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "This script requires root privileges"
        log_error "Please run: sudo $0"
        exit 1
    fi
}

#-------------------------------------------------------------------------------
# Check Physical Interface Exists
#-------------------------------------------------------------------------------
check_physical_iface() {
    log_info "Checking physical interface: $PHYSICAL_IFACE"
    if ! ip link show "$PHYSICAL_IFACE" &>/dev/null; then
        log_error "Physical interface $PHYSICAL_IFACE does not exist!"
        log_error "Available interfaces:"
        ip link show | grep -E '^[0-9]+:' | awk -F': ' '{print "  - " $2}'
        exit 1
    fi
    log_success "Physical interface $PHYSICAL_IFACE exists"
}

#-------------------------------------------------------------------------------
# Validate Configuration Parameters
#-------------------------------------------------------------------------------
validate_params() {
    log_info "Validating configuration parameters..."
    
    if ! echo "$BRIDGE_IP" | grep -qE '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$'; then
        log_error "Invalid BRIDGE_IP format! Must be CIDR (e.g., 192.168.2.99/24)"
        exit 1
    fi
    
    BRIDGE_STP=$(echo "$BRIDGE_STP" | tr '[:upper:]' '[:lower:]')
    if [[ "$BRIDGE_STP" != "yes" && "$BRIDGE_STP" != "no" ]]; then
        log_error "Invalid BRIDGE_STP value! Must be 'yes' or 'no'"
        exit 1
    fi
    
    if ! echo "$BRIDGE_FORWARD_DELAY" | grep -qE '^[0-9]+$'; then
        log_error "Invalid BRIDGE_FORWARD_DELAY value! Must be a number"
        exit 1
    fi
    
    log_success "Configuration parameters validation passed"
}

#-------------------------------------------------------------------------------
# Check NetworkManager Service
#-------------------------------------------------------------------------------
check_nm() {
    if ! systemctl is-active --quiet NetworkManager; then
        log_error "NetworkManager service is not running"
        log_error "Please start: systemctl start NetworkManager"
        exit 1
    fi
    log_success "NetworkManager service is running"
}

#-------------------------------------------------------------------------------
# Check nmcli Tool
#-------------------------------------------------------------------------------
check_nmcli() {
    if ! command -v nmcli &> /dev/null; then
        log_error "nmcli command not found, please install network-manager"
        exit 1
    fi
    log_success "nmcli tool is available"
}

#-------------------------------------------------------------------------------
# Disable Competing Services
#-------------------------------------------------------------------------------
disable_competing_services() {
    log_info "Disabling competing network services..."
    
    if systemctl is-active --quiet systemd-networkd 2>/dev/null; then
        log_warn "systemd-networkd is running. Disabling it..."
        if ! systemctl stop systemd-networkd 2>/dev/null || 
           ! systemctl disable systemd-networkd 2>/dev/null || 
           ! systemctl mask systemd-networkd 2>/dev/null; then
            log_error "Failed to disable systemd-networkd"
            exit 1
        fi
        log_success "systemd-networkd disabled"
    else
        log_info "systemd-networkd is not running"
    fi

    if [[ -f /etc/network/interfaces ]]; then
        log_info "Checking /etc/network/interfaces for conflicts..."
        cp /etc/network/interfaces /etc/network/interfaces.bak.$(date +%s) 2>/dev/null
        
        grep -v "^auto $PHYSICAL_IFACE" /etc/network/interfaces 2>/dev/null | \
        grep -v "^iface $PHYSICAL_IFACE" | \
        grep -v "^auto $BRIDGE_NAME" | \
        grep -v "^iface $BRIDGE_NAME" > /etc/network/interfaces.tmp 2>/dev/null
        
        if ! diff -q /etc/network/interfaces /etc/network/interfaces.tmp &>/dev/null; then
            mv /etc/network/interfaces.tmp /etc/network/interfaces
            log_warn "Cleaned /etc/network/interfaces (backup saved)"
        else
            rm -f /etc/network/interfaces.tmp 2>/dev/null
            log_info "/etc/network/interfaces is clean"
        fi
    fi
    
    log_success "Competing services disabled/cleaned"
}

#-------------------------------------------------------------------------------
# Detect and Remove Conflicting Connections
#-------------------------------------------------------------------------------
cleanup_conflicts() {
    log_info "Checking and cleaning up conflicting network connections..."
    
    local all_conns=""
    while read conn; do
        if nmcli connection show "$conn" 2>/dev/null | grep -q "interface-name: $PHYSICAL_IFACE"; then
            all_conns="$all_conns $conn"
        fi
    done < <(nmcli -g NAME connection show 2>/dev/null)
    
    for conn in $all_conns; do
        if [[ "$conn" != "$SLAVE_CONN_NAME" ]]; then
            log_warn "Found conflicting connection: $conn (manages $PHYSICAL_IFACE)"
            log_info "Deleting conflicting connection..."
            
            if ! nmcli connection delete "$conn" &>/dev/null; then
                log_error "Failed to delete conflicting connection: $conn"
                return 1
            fi
            log_success "Deleted conflicting connection: $conn"
        fi
    done
    
    if nmcli connection show 2>/dev/null | grep -qE "^$BRIDGE_NAME"; then
        log_warn "Found existing bridge connection: $BRIDGE_NAME"
        log_info "Deleting old bridge connection..."
        
        if ! nmcli connection delete "$BRIDGE_NAME" &>/dev/null; then
            log_error "Failed to delete old bridge connection"
            return 1
        fi
        log_success "Deleted old bridge connection"
    fi
    
    if nmcli connection show 2>/dev/null | grep -q "^$SLAVE_CONN_NAME "; then
        log_warn "Found existing slave connection: $SLAVE_CONN_NAME"
        log_info "Deleting old slave connection..."
        
        if ! nmcli connection delete "$SLAVE_CONN_NAME" &>/dev/null; then
            log_error "Failed to delete old slave connection"
            return 1
        fi
        log_success "Deleted old slave connection"
    fi
    
    return 0
}

#-------------------------------------------------------------------------------
# Create Bridge
#-------------------------------------------------------------------------------
create_bridge() {
    log_info "Creating bridge: $BRIDGE_NAME"
    
    if ! nmcli connection add type bridge ifname "$BRIDGE_NAME" con-name "$BRIDGE_NAME" \
        ip4 "$BRIDGE_IP" gw4 "$BRIDGE_GATEWAY" \
        ipv4.dns "$BRIDGE_DNS" \
        bridge.stp "$BRIDGE_STP" \
        bridge.forward-delay "$BRIDGE_FORWARD_DELAY" \
        connection.autoconnect yes \
        connection.autoconnect-priority 100 &>/dev/null; then
        log_error "Failed to create bridge"
        return 1
    fi
    
    log_success "Bridge created successfully"
    return 0
}

#-------------------------------------------------------------------------------
# Create Slave Interface
#-------------------------------------------------------------------------------
create_slave() {
    log_info "Creating slave interface: $SLAVE_CONN_NAME (binding $PHYSICAL_IFACE to $BRIDGE_NAME)"
    
    if ! nmcli connection add \
        type bridge-slave \
        con-name "$SLAVE_CONN_NAME" \
        ifname "$PHYSICAL_IFACE" \
        master "$BRIDGE_NAME" \
        connection.autoconnect yes \
        connection.autoconnect-priority 200 &>/dev/null; then
        log_error "Failed to create slave connection (detailed error below):"
        nmcli connection add type bridge-slave con-name "$SLAVE_CONN_NAME" ifname "$PHYSICAL_IFACE" master "$BRIDGE_NAME"
        return 1
    fi
    
    log_success "Slave connection created"
    return 0
}

#-------------------------------------------------------------------------------
# Activate Connections
#-------------------------------------------------------------------------------
activate_connections() {
    log_info "Activating network connections..."
    
    ip link set "$PHYSICAL_IFACE" down 2>/dev/null
    sleep 1
    
    log_info "Activating bridge: $BRIDGE_NAME"
    if ! nmcli connection up "$BRIDGE_NAME" &>/dev/null; then
        log_error "Failed to activate bridge connection"
        return 1
    fi
    sleep 2
    
    log_info "Activating slave interface: $SLAVE_CONN_NAME"
    if ! nmcli connection up "$SLAVE_CONN_NAME" &>/dev/null; then
        log_error "Failed to activate slave connection"
        return 1
    fi
    sleep 3
    
    log_success "All connections activated successfully"
    return 0
}

#-------------------------------------------------------------------------------
# Verify Configuration
#-------------------------------------------------------------------------------
verify_config() {
    log_info "Verifying network configuration..."
    local errors=0
    
    if nmcli connection show 2>/dev/null | grep -q "^$BRIDGE_NAME "; then
        log_success "✓ Bridge connection exists"
    else
        log_error "✗ Bridge connection does not exist"
        ((errors++))
    fi
    
    if nmcli connection show "$SLAVE_CONN_NAME" 2>/dev/null | grep -q "$PHYSICAL_IFACE"; then
        log_success "✓ Slave connection exists and bound to device"
    else
        log_error "✗ Slave connection not properly bound"
        ((errors++))
    fi
    
    if ip link show "$BRIDGE_NAME" 2>/dev/null | grep -q "state UP"; then
        log_success "✓ Bridge state is UP"
    else
        log_error "✗ Bridge state is not UP"
        ((errors++))
    fi
    
    if ip addr show "$BRIDGE_NAME" 2>/dev/null | grep -q "inet $BRIDGE_IP"; then
        log_success "✓ Bridge IP address is correct"
    else
        log_error "✗ Bridge IP address is incorrect"
        ((errors++))
    fi
    
    if ! ip addr show "$PHYSICAL_IFACE" 2>/dev/null | grep -qE "inet [0-9.]+"; then
        log_success "✓ Physical interface has no independent IP"
    else
        log_error "✗ Physical interface still has independent IP"
        ((errors++))
    fi
    
    if bridge link show 2>/dev/null | grep -q "$PHYSICAL_IFACE.*master $BRIDGE_NAME"; then
        log_success "✓ Physical interface joined bridge"
    else
        log_error "✗ Physical interface not joined bridge"
        ((errors++))
    fi
    
    log_info "Testing network connectivity..."
    if ping -c 2 -W 2 "$BRIDGE_GATEWAY" &>/dev/null; then
        log_success "✓ Gateway connectivity normal"
    else
        log_warn "⚠ Gateway connectivity test failed (may be temporary)"
    fi
    
    echo ""
    if [[ $errors -eq 0 ]]; then
        log_success "========================================="
        log_success "All verifications passed! Bridge configured successfully!"
        log_success "========================================="
        return 0
    else
        log_error "========================================="
        log_error "Found $errors issues, please check configuration"
        log_error "========================================="
        return 1
    fi
}

#-------------------------------------------------------------------------------
# Display Summary
#-------------------------------------------------------------------------------
show_summary() {
    echo ""
    log_info "========== Network Configuration Summary =========="
    echo ""
    echo "Bridge Name:      $BRIDGE_NAME"
    echo "Bridge IP:        $BRIDGE_IP"
    echo "Gateway:          $BRIDGE_GATEWAY"
    echo "DNS:              $BRIDGE_DNS"
    echo "Physical Interface: $PHYSICAL_IFACE"
    echo "Slave Connection: $SLAVE_CONN_NAME"
    echo ""
    echo "Current Connection Status:"
    nmcli connection show 2>/dev/null | grep -E "$BRIDGE_NAME|$SLAVE_CONN_NAME|$PHYSICAL_IFACE" || echo "  No relevant connections found"
    echo ""
    echo "Bridge Interface Info:"
    ip addr show "$BRIDGE_NAME" 2>/dev/null | head -6 || echo "  No info available"
    echo ""
    echo "Physical Interface Info:"
    ip addr show "$PHYSICAL_IFACE" 2>/dev/null | head -6 || echo "  No info available"
    echo ""
    echo "Bridge Ports:"
    bridge link show 2>/dev/null | grep "$PHYSICAL_IFACE" || echo "  None"
    echo ""
    log_info "========================================="
}

#-------------------------------------------------------------------------------
# Reboot Guide
#-------------------------------------------------------------------------------
show_reboot_guide() {
    echo ""
    log_warn "========== IMPORTANT: Post-Reboot Verification =========="
    echo ""
    echo "After reboot, please verify:"
    echo "  1. Run: ip addr show $BRIDGE_NAME → Should show IP: $BRIDGE_IP"
    echo "  2. Run: ip addr show $PHYSICAL_IFACE → Should NOT show any IPv4 address"
    echo "  3. Run: bridge link show → $PHYSICAL_IFACE should show master $BRIDGE_NAME"
    echo "  4. Run: nmcli connection show → Both connections should be 'connected'"
    echo ""
    echo "If physical interface gets IP after reboot:"
    echo "  - Check: systemctl status systemd-networkd"
    echo "  - Check /etc/network/interfaces for static configs"
    echo "  - Re-run this script to reapply configuration"
    echo ""
    log_warn "========================================="
}

#-------------------------------------------------------------------------------
# Main Function
#-------------------------------------------------------------------------------
main() {
    init_background_mode
    
    echo ""
    echo "========================================="
    echo "  NetworkManager Bridge Configuration Script"
    echo "========================================="
    echo ""
    
    if [[ "$BACKGROUND_MODE" != "yes" ]]; then
        log_info "Tip: Run with -b to execute in background"
        log_info "Usage: sudo $0 -b"
        echo ""
    fi
    
    check_root || write_error_exit 1 "Root check failed"
    check_nm || write_error_exit 1 "NetworkManager check failed"
    check_nmcli || write_error_exit 1 "nmcli check failed"
    check_physical_iface || write_error_exit 1 "Physical interface check failed"
    validate_params || write_error_exit 1 "Parameter validation failed"
    
    disable_competing_services || write_error_exit 1 "Disable competing services failed"
    
    if [[ "$BACKGROUND_MODE" != "yes" ]]; then
        echo ""
        log_warn "========================================="
        log_warn "WARNING: This operation will interrupt network for 10-30 seconds"
        log_warn "Ensure you have physical access (HDMI/Serial)"
        log_warn "========================================="
        echo ""
        
        read -p "Continue? (y/N): " -n 1 -r
        echo ""
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "Operation cancelled"
            exit 0
        fi
    else
        log_warn "Running in background mode - proceeding automatically"
    fi
    
    if ! cleanup_conflicts; then
        log_error "Cleanup failed - exiting"
        write_error_exit 1 "Cleanup conflicts failed"
    fi
    
    if ! create_bridge; then
        log_error "Bridge creation failed - exiting"
        write_error_exit 1 "Bridge creation failed"
    fi
    
    if ! create_slave; then
        log_error "Slave interface creation failed - exiting"
        write_error_exit 1 "Slave creation failed"
    fi
    
    if ! activate_connections; then
        log_error "Connection activation failed - exiting"
        write_error_exit 1 "Connection activation failed"
    fi
    
    sleep 5
    verify_config
    local verify_result=$?
    
    show_summary
    show_reboot_guide
    
    echo ""
    if [[ $verify_result -eq 0 ]]; then
        log_success "========================================="
        log_success "Bridge configuration completed!"
        log_success "========================================="
        [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] Bridge setup completed successfully" >> "$LOG_FILE"
        exit 0
    else
        log_error "========================================="
        log_error "Configuration completed but verification failed"
        log_error "Please check network configuration"
        log_error "========================================="
        write_error_exit 1 "Verification failed"
    fi
}

#-------------------------------------------------------------------------------
# Parse Command Line Arguments
#-------------------------------------------------------------------------------
parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -b|--background)
                BACKGROUND_MODE="yes"
                shift
                ;;
            -h|--help)
                echo "Usage: sudo $0 [OPTIONS]"
                echo ""
                echo "Options:"
                echo "  -b, --background           Run in background mode (no interaction required)"
                echo "  -h, --help                 Show this help message"
                echo ""
                echo "Background mode is recommended for SSH connections to prevent network interruption issues."
                exit 0
                ;;
            *)
                echo "Unknown option: $1"
                echo "Use -h or --help for usage information"
                exit 1
                ;;
        esac
    done
}

parse_args "$@"
main "$@"

enp1s0

create-bridge-enp1s0.sh
#!/bin/bash
#===============================================================================
# Script Name: create-bridge-enp1s0.sh
# Description: Create bridge configuration using NetworkManager 
#===============================================================================

#-------------------------------------------------------------------------------
# Configuration Area - Modify according to your environment
#-------------------------------------------------------------------------------
BRIDGE_NAME="br-lan"
BRIDGE_IP="192.168.2.99/24"
BRIDGE_GATEWAY="192.168.2.1"
BRIDGE_DNS="192.168.2.1"
PHYSICAL_IFACE="enp1s0"
SLAVE_CONN_NAME="enp1s0-bridge-port"

# Bridge Advanced Options
BRIDGE_STP="no"
BRIDGE_FORWARD_DELAY="0"

# Background Execution Options
BACKGROUND_MODE="yes"
LOG_FILE=""

#-------------------------------------------------------------------------------
# Color Definitions
#-------------------------------------------------------------------------------
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

#-------------------------------------------------------------------------------
# Logging Functions
#-------------------------------------------------------------------------------
log_info()    { echo -e "${BLUE}[INFO]${NC} $1"; [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1" >> "$LOG_FILE"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1" >> "$LOG_FILE"; }
log_warn()    { echo -e "${YELLOW}[WARN]${NC} $1";  [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $1" >> "$LOG_FILE"; }
log_error()   { echo -e "${RED}[ERROR]${NC} $1";   [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1" >> "$LOG_FILE"; }

#-------------------------------------------------------------------------------
# Background Mode Functions
#-------------------------------------------------------------------------------
init_background_mode() {
    if [[ "$BACKGROUND_MODE" == "yes" ]]; then
        LOG_FILE="$(dirname "$0")/bridge-setup-$(date +%Y%m%d-%H%M%S).log"
        exec > >(tee -a "$LOG_FILE")
        exec 2>&1
        log_info "Running in background mode, log file: $LOG_FILE"
    fi
}

write_error_exit() {
    local exit_code=$1
    local error_msg=$2
    if [[ -n "$LOG_FILE" ]]; then
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] [FATAL] Script failed with exit code $exit_code" >> "$LOG_FILE"
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] [FATAL] Error: $error_msg" >> "$LOG_FILE"
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] [FATAL] Failed at: ${BASH_SOURCE[1]}:${BASH_LINENO[0]}" >> "$LOG_FILE"
        echo "" >> "$LOG_FILE"
        echo "=== Last 20 lines of NetworkManager log ===" >> "$LOG_FILE"
        journalctl -u NetworkManager -n 20 --no-pager 2>/dev/null >> "$LOG_FILE" || true
        echo "" >> "$LOG_FILE"
        echo "=== Current network status ===" >> "$LOG_FILE"
        ip addr >> "$LOG_FILE" 2>&1
        echo "" >> "$LOG_FILE"
        echo "=== NetworkManager connections ===" >> "$LOG_FILE"
        nmcli connection show >> "$LOG_FILE" 2>&1
    fi
    exit $exit_code
}

#-------------------------------------------------------------------------------
# Check Root Privileges
#-------------------------------------------------------------------------------
check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "This script requires root privileges"
        log_error "Please run: sudo $0"
        exit 1
    fi
}

#-------------------------------------------------------------------------------
# Check Physical Interface Exists
#-------------------------------------------------------------------------------
check_physical_iface() {
    log_info "Checking physical interface: $PHYSICAL_IFACE"
    if ! ip link show "$PHYSICAL_IFACE" &>/dev/null; then
        log_error "Physical interface $PHYSICAL_IFACE does not exist!"
        log_error "Available interfaces:"
        ip link show | grep -E '^[0-9]+:' | awk -F': ' '{print "  - " $2}'
        exit 1
    fi
    log_success "Physical interface $PHYSICAL_IFACE exists"
}

#-------------------------------------------------------------------------------
# Validate Configuration Parameters
#-------------------------------------------------------------------------------
validate_params() {
    log_info "Validating configuration parameters..."
    
    if ! echo "$BRIDGE_IP" | grep -qE '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$'; then
        log_error "Invalid BRIDGE_IP format! Must be CIDR (e.g., 192.168.2.99/24)"
        exit 1
    fi
    
    BRIDGE_STP=$(echo "$BRIDGE_STP" | tr '[:upper:]' '[:lower:]')
    if [[ "$BRIDGE_STP" != "yes" && "$BRIDGE_STP" != "no" ]]; then
        log_error "Invalid BRIDGE_STP value! Must be 'yes' or 'no'"
        exit 1
    fi
    
    if ! echo "$BRIDGE_FORWARD_DELAY" | grep -qE '^[0-9]+$'; then
        log_error "Invalid BRIDGE_FORWARD_DELAY value! Must be a number"
        exit 1
    fi
    
    log_success "Configuration parameters validation passed"
}

#-------------------------------------------------------------------------------
# Check NetworkManager Service
#-------------------------------------------------------------------------------
check_nm() {
    if ! systemctl is-active --quiet NetworkManager; then
        log_error "NetworkManager service is not running"
        log_error "Please start: systemctl start NetworkManager"
        exit 1
    fi
    log_success "NetworkManager service is running"
}

#-------------------------------------------------------------------------------
# Check nmcli Tool
#-------------------------------------------------------------------------------
check_nmcli() {
    if ! command -v nmcli &> /dev/null; then
        log_error "nmcli command not found, please install network-manager"
        exit 1
    fi
    log_success "nmcli tool is available"
}

#-------------------------------------------------------------------------------
# Disable Competing Services
#-------------------------------------------------------------------------------
disable_competing_services() {
    log_info "Disabling competing network services..."
    
    if systemctl is-active --quiet systemd-networkd 2>/dev/null; then
        log_warn "systemd-networkd is running. Disabling it..."
        if ! systemctl stop systemd-networkd 2>/dev/null || 
           ! systemctl disable systemd-networkd 2>/dev/null || 
           ! systemctl mask systemd-networkd 2>/dev/null; then
            log_error "Failed to disable systemd-networkd"
            exit 1
        fi
        log_success "systemd-networkd disabled"
    else
        log_info "systemd-networkd is not running"
    fi

    if [[ -f /etc/network/interfaces ]]; then
        log_info "Checking /etc/network/interfaces for conflicts..."
        cp /etc/network/interfaces /etc/network/interfaces.bak.$(date +%s) 2>/dev/null
        
        grep -v "^auto $PHYSICAL_IFACE" /etc/network/interfaces 2>/dev/null | \
        grep -v "^iface $PHYSICAL_IFACE" | \
        grep -v "^auto $BRIDGE_NAME" | \
        grep -v "^iface $BRIDGE_NAME" > /etc/network/interfaces.tmp 2>/dev/null
        
        if ! diff -q /etc/network/interfaces /etc/network/interfaces.tmp &>/dev/null; then
            mv /etc/network/interfaces.tmp /etc/network/interfaces
            log_warn "Cleaned /etc/network/interfaces (backup saved)"
        else
            rm -f /etc/network/interfaces.tmp 2>/dev/null
            log_info "/etc/network/interfaces is clean"
        fi
    fi
    
    log_success "Competing services disabled/cleaned"
}

#-------------------------------------------------------------------------------
# Detect and Remove Conflicting Connections
#-------------------------------------------------------------------------------
cleanup_conflicts() {
    log_info "Checking and cleaning up conflicting network connections..."
    
    local all_conns=""
    while read conn; do
        if nmcli connection show "$conn" 2>/dev/null | grep -q "interface-name: $PHYSICAL_IFACE"; then
            all_conns="$all_conns $conn"
        fi
    done < <(nmcli -g NAME connection show 2>/dev/null)
    
    for conn in $all_conns; do
        if [[ "$conn" != "$SLAVE_CONN_NAME" ]]; then
            log_warn "Found conflicting connection: $conn (manages $PHYSICAL_IFACE)"
            log_info "Deleting conflicting connection..."
            
            if ! nmcli connection delete "$conn" &>/dev/null; then
                log_error "Failed to delete conflicting connection: $conn"
                return 1
            fi
            log_success "Deleted conflicting connection: $conn"
        fi
    done
    
    if nmcli connection show 2>/dev/null | grep -qE "^$BRIDGE_NAME"; then
        log_warn "Found existing bridge connection: $BRIDGE_NAME"
        log_info "Deleting old bridge connection..."
        
        if ! nmcli connection delete "$BRIDGE_NAME" &>/dev/null; then
            log_error "Failed to delete old bridge connection"
            return 1
        fi
        log_success "Deleted old bridge connection"
    fi
    
    if nmcli connection show 2>/dev/null | grep -q "^$SLAVE_CONN_NAME "; then
        log_warn "Found existing slave connection: $SLAVE_CONN_NAME"
        log_info "Deleting old slave connection..."
        
        if ! nmcli connection delete "$SLAVE_CONN_NAME" &>/dev/null; then
            log_error "Failed to delete old slave connection"
            return 1
        fi
        log_success "Deleted old slave connection"
    fi
    
    return 0
}

#-------------------------------------------------------------------------------
# Create Bridge
#-------------------------------------------------------------------------------
create_bridge() {
    log_info "Creating bridge: $BRIDGE_NAME"
    
    if ! nmcli connection add type bridge ifname "$BRIDGE_NAME" con-name "$BRIDGE_NAME" \
        ip4 "$BRIDGE_IP" gw4 "$BRIDGE_GATEWAY" \
        ipv4.dns "$BRIDGE_DNS" \
        bridge.stp "$BRIDGE_STP" \
        bridge.forward-delay "$BRIDGE_FORWARD_DELAY" \
        connection.autoconnect yes \
        connection.autoconnect-priority 100 &>/dev/null; then
        log_error "Failed to create bridge"
        return 1
    fi
    
    log_success "Bridge created successfully"
    return 0
}

#-------------------------------------------------------------------------------
# Create Slave Interface
#-------------------------------------------------------------------------------
create_slave() {
    log_info "Creating slave interface: $SLAVE_CONN_NAME (binding $PHYSICAL_IFACE to $BRIDGE_NAME)"
    
    if ! nmcli connection add \
        type bridge-slave \
        con-name "$SLAVE_CONN_NAME" \
        ifname "$PHYSICAL_IFACE" \
        master "$BRIDGE_NAME" \
        connection.autoconnect yes \
        connection.autoconnect-priority 200 &>/dev/null; then
        log_error "Failed to create slave connection (detailed error below):"
        nmcli connection add type bridge-slave con-name "$SLAVE_CONN_NAME" ifname "$PHYSICAL_IFACE" master "$BRIDGE_NAME"
        return 1
    fi
    
    log_success "Slave connection created"
    return 0
}

#-------------------------------------------------------------------------------
# Activate Connections
#-------------------------------------------------------------------------------
activate_connections() {
    log_info "Activating network connections..."
    
    ip link set "$PHYSICAL_IFACE" down 2>/dev/null
    sleep 1
    
    log_info "Activating bridge: $BRIDGE_NAME"
    if ! nmcli connection up "$BRIDGE_NAME" &>/dev/null; then
        log_error "Failed to activate bridge connection"
        return 1
    fi
    sleep 2
    
    log_info "Activating slave interface: $SLAVE_CONN_NAME"
    if ! nmcli connection up "$SLAVE_CONN_NAME" &>/dev/null; then
        log_error "Failed to activate slave connection"
        return 1
    fi
    sleep 3
    
    log_success "All connections activated successfully"
    return 0
}

#-------------------------------------------------------------------------------
# Verify Configuration
#-------------------------------------------------------------------------------
verify_config() {
    log_info "Verifying network configuration..."
    local errors=0
    
    if nmcli connection show 2>/dev/null | grep -q "^$BRIDGE_NAME "; then
        log_success "✓ Bridge connection exists"
    else
        log_error "✗ Bridge connection does not exist"
        ((errors++))
    fi
    
    if nmcli connection show "$SLAVE_CONN_NAME" 2>/dev/null | grep -q "$PHYSICAL_IFACE"; then
        log_success "✓ Slave connection exists and bound to device"
    else
        log_error "✗ Slave connection not properly bound"
        ((errors++))
    fi
    
    if ip link show "$BRIDGE_NAME" 2>/dev/null | grep -q "state UP"; then
        log_success "✓ Bridge state is UP"
    else
        log_error "✗ Bridge state is not UP"
        ((errors++))
    fi
    
    if ip addr show "$BRIDGE_NAME" 2>/dev/null | grep -q "inet $BRIDGE_IP"; then
        log_success "✓ Bridge IP address is correct"
    else
        log_error "✗ Bridge IP address is incorrect"
        ((errors++))
    fi
    
    if ! ip addr show "$PHYSICAL_IFACE" 2>/dev/null | grep -qE "inet [0-9.]+"; then
        log_success "✓ Physical interface has no independent IP"
    else
        log_error "✗ Physical interface still has independent IP"
        ((errors++))
    fi
    
    if bridge link show 2>/dev/null | grep -q "$PHYSICAL_IFACE.*master $BRIDGE_NAME"; then
        log_success "✓ Physical interface joined bridge"
    else
        log_error "✗ Physical interface not joined bridge"
        ((errors++))
    fi
    
    log_info "Testing network connectivity..."
    if ping -c 2 -W 2 "$BRIDGE_GATEWAY" &>/dev/null; then
        log_success "✓ Gateway connectivity normal"
    else
        log_warn "⚠ Gateway connectivity test failed (may be temporary)"
    fi
    
    echo ""
    if [[ $errors -eq 0 ]]; then
        log_success "========================================="
        log_success "All verifications passed! Bridge configured successfully!"
        log_success "========================================="
        return 0
    else
        log_error "========================================="
        log_error "Found $errors issues, please check configuration"
        log_error "========================================="
        return 1
    fi
}

#-------------------------------------------------------------------------------
# Display Summary
#-------------------------------------------------------------------------------
show_summary() {
    echo ""
    log_info "========== Network Configuration Summary =========="
    echo ""
    echo "Bridge Name:      $BRIDGE_NAME"
    echo "Bridge IP:        $BRIDGE_IP"
    echo "Gateway:          $BRIDGE_GATEWAY"
    echo "DNS:              $BRIDGE_DNS"
    echo "Physical Interface: $PHYSICAL_IFACE"
    echo "Slave Connection: $SLAVE_CONN_NAME"
    echo ""
    echo "Current Connection Status:"
    nmcli connection show 2>/dev/null | grep -E "$BRIDGE_NAME|$SLAVE_CONN_NAME|$PHYSICAL_IFACE" || echo "  No relevant connections found"
    echo ""
    echo "Bridge Interface Info:"
    ip addr show "$BRIDGE_NAME" 2>/dev/null | head -6 || echo "  No info available"
    echo ""
    echo "Physical Interface Info:"
    ip addr show "$PHYSICAL_IFACE" 2>/dev/null | head -6 || echo "  No info available"
    echo ""
    echo "Bridge Ports:"
    bridge link show 2>/dev/null | grep "$PHYSICAL_IFACE" || echo "  None"
    echo ""
    log_info "========================================="
}

#-------------------------------------------------------------------------------
# Reboot Guide
#-------------------------------------------------------------------------------
show_reboot_guide() {
    echo ""
    log_warn "========== IMPORTANT: Post-Reboot Verification =========="
    echo ""
    echo "After reboot, please verify:"
    echo "  1. Run: ip addr show $BRIDGE_NAME → Should show IP: $BRIDGE_IP"
    echo "  2. Run: ip addr show $PHYSICAL_IFACE → Should NOT show any IPv4 address"
    echo "  3. Run: bridge link show → $PHYSICAL_IFACE should show master $BRIDGE_NAME"
    echo "  4. Run: nmcli connection show → Both connections should be 'connected'"
    echo ""
    echo "If physical interface gets IP after reboot:"
    echo "  - Check: systemctl status systemd-networkd"
    echo "  - Check /etc/network/interfaces for static configs"
    echo "  - Re-run this script to reapply configuration"
    echo ""
    log_warn "========================================="
}

#-------------------------------------------------------------------------------
# Main Function
#-------------------------------------------------------------------------------
main() {
    init_background_mode
    
    echo ""
    echo "========================================="
    echo "  NetworkManager Bridge Configuration Script"
    echo "========================================="
    echo ""
    
    if [[ "$BACKGROUND_MODE" != "yes" ]]; then
        log_info "Tip: Run with -b to execute in background"
        log_info "Usage: sudo $0 -b"
        echo ""
    fi
    
    check_root || write_error_exit 1 "Root check failed"
    check_nm || write_error_exit 1 "NetworkManager check failed"
    check_nmcli || write_error_exit 1 "nmcli check failed"
    check_physical_iface || write_error_exit 1 "Physical interface check failed"
    validate_params || write_error_exit 1 "Parameter validation failed"
    
    disable_competing_services || write_error_exit 1 "Disable competing services failed"
    
    if [[ "$BACKGROUND_MODE" != "yes" ]]; then
        echo ""
        log_warn "========================================="
        log_warn "WARNING: This operation will interrupt network for 10-30 seconds"
        log_warn "Ensure you have physical access (HDMI/Serial)"
        log_warn "========================================="
        echo ""
        
        read -p "Continue? (y/N): " -n 1 -r
        echo ""
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "Operation cancelled"
            exit 0
        fi
    else
        log_warn "Running in background mode - proceeding automatically"
    fi
    
    if ! cleanup_conflicts; then
        log_error "Cleanup failed - exiting"
        write_error_exit 1 "Cleanup conflicts failed"
    fi
    
    if ! create_bridge; then
        log_error "Bridge creation failed - exiting"
        write_error_exit 1 "Bridge creation failed"
    fi
    
    if ! create_slave; then
        log_error "Slave interface creation failed - exiting"
        write_error_exit 1 "Slave creation failed"
    fi
    
    if ! activate_connections; then
        log_error "Connection activation failed - exiting"
        write_error_exit 1 "Connection activation failed"
    fi
    
    sleep 5
    verify_config
    local verify_result=$?
    
    show_summary
    show_reboot_guide
    
    echo ""
    if [[ $verify_result -eq 0 ]]; then
        log_success "========================================="
        log_success "Bridge configuration completed!"
        log_success "========================================="
        [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] Bridge setup completed successfully" >> "$LOG_FILE"
        exit 0
    else
        log_error "========================================="
        log_error "Configuration completed but verification failed"
        log_error "Please check network configuration"
        log_error "========================================="
        write_error_exit 1 "Verification failed"
    fi
}

#-------------------------------------------------------------------------------
# Parse Command Line Arguments
#-------------------------------------------------------------------------------
parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -b|--background)
                BACKGROUND_MODE="yes"
                shift
                ;;
            -h|--help)
                echo "Usage: sudo $0 [OPTIONS]"
                echo ""
                echo "Options:"
                echo "  -b, --background           Run in background mode (no interaction required)"
                echo "  -h, --help                 Show this help message"
                echo ""
                echo "Background mode is recommended for SSH connections to prevent network interruption issues."
                exit 0
                ;;
            *)
                echo "Unknown option: $1"
                echo "Use -h or --help for usage information"
                exit 1
                ;;
        esac
    done
}

parse_args "$@"
main "$@"

eth0 恢复

rollback-network-eth0.sh
#!/bin/bash
#===============================================================================
# Script Name: rollback-network-eth0.sh
# Description: Rollback bridge network configuration to restore original state
#===============================================================================

BRIDGE_NAME="br-lan"
PHYSICAL_IFACE="eth0"
SLAVE_CONN_NAME="eth0-bridge-port"

#-------------------------------------------------------------------------------
# Physical Interface Configuration - Configure before rolling back
#-------------------------------------------------------------------------------
# Set to "dhcp" for automatic IP, or "static" for manual configuration
PHYSICAL_IFACE_METHOD="static"

# Static IP configuration (only used when PHYSICAL_IFACE_METHOD="static")
PHYSICAL_IFACE_IP="192.168.2.99/24"
PHYSICAL_IFACE_GATEWAY="192.168.2.1"
PHYSICAL_IFACE_DNS="192.168.2.1"

# Background Execution Options
BACKGROUND_MODE="yes"
LOG_FILE=""

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_info()    { echo -e "${BLUE}[INFO]${NC} $1"; [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1" >> "$LOG_FILE"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1" >> "$LOG_FILE"; }
log_warn()    { echo -e "${YELLOW}[WARN]${NC} $1";  [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $1"  >> "$LOG_FILE"; }
log_error()   { echo -e "${RED}[ERROR]${NC} $1";   [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1"  >> "$LOG_FILE"; }

init_background_mode() {
    if [[ "$BACKGROUND_MODE" == "yes" ]]; then
        LOG_FILE="$(dirname "$0")/rollback-$(date +%Y%m%d-%H%M%S).log"
        exec > >(tee -a "$LOG_FILE")
        exec 2>&1
        log_info "Running in background mode, log file: $LOG_FILE"
    fi
}

check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "This script requires root privileges"
        log_error "Please run: sudo $0"
        exit 1
    fi
}

rollback_bridge() {
    log_info "Rolling back bridge configuration..."

    log_info "Deleting bridge connection: $BRIDGE_NAME"
    if nmcli connection show "$BRIDGE_NAME" &>/dev/null; then
        nmcli connection down "$BRIDGE_NAME" &>/dev/null || true
        nmcli connection delete "$BRIDGE_NAME" &>/dev/null && \
            log_success "Bridge connection deleted" || \
            log_warn "Failed to delete bridge connection"
    else
        log_info "Bridge connection does not exist"
    fi

    log_info "Deleting slave connection: $SLAVE_CONN_NAME"
    if nmcli connection show "$SLAVE_CONN_NAME" &>/dev/null; then
        nmcli connection down "$SLAVE_CONN_NAME" &>/dev/null || true
        nmcli connection delete "$SLAVE_CONN_NAME" &>/dev/null && \
            log_success "Slave connection deleted" || \
            log_warn "Failed to delete slave connection"
    else
        log_info "Slave connection does not exist"
    fi
}

cleanup_bridge_interface() {
    log_info "Cleaning up bridge interface..."

    if ip link show "$BRIDGE_NAME" &>/dev/null; then
        ip link set "$BRIDGE_NAME" down &>/dev/null || true
        ip link delete "$BRIDGE_NAME" &>/dev/null && \
            log_success "Bridge interface deleted" || \
            log_warn "Failed to delete bridge interface"
    else
        log_info "Bridge interface does not exist"
    fi
}

restore_physical_interface() {
    log_info "Restoring physical interface: $PHYSICAL_IFACE"

    ip link set "$PHYSICAL_IFACE" down &>/dev/null || true
    sleep 1

    log_info "Cleaning up existing connections for $PHYSICAL_IFACE..."
    local existing_conns=$(nmcli connection show 2>/dev/null | grep -E "ethernet.*$PHYSICAL_IFACE" | awk '{print $1}')
    for conn in $existing_conns; do
        log_info "Deleting existing connection: $conn"
        nmcli connection down "$conn" &>/dev/null || true
        nmcli connection delete "$conn" &>/dev/null && \
            log_success "Deleted: $conn" || \
            log_warn "Failed to delete: $conn"
    done

    log_info "Creating new connection for physical interface: $PHYSICAL_IFACE"
    local conn_name="Wired connection 1"
    nmcli connection add \
        type ethernet \
        con-name "$conn_name" \
        ifname "$PHYSICAL_IFACE" \
        connection.autoconnect yes &>/dev/null && \
        log_success "Connection created: $conn_name" || \
        log_warn "Failed to create connection"

    if [[ "$PHYSICAL_IFACE_METHOD" == "static" ]]; then
        log_info "Configuring static IP: $PHYSICAL_IFACE_IP"
        nmcli connection modify "$conn_name" \
            ipv4.method manual \
            ipv4.address "$PHYSICAL_IFACE_IP" \
            ipv4.gateway "$PHYSICAL_IFACE_GATEWAY" \
            ipv4.dns "$PHYSICAL_IFACE_DNS" &>/dev/null && \
            log_success "Static IP configured" || \
            log_warn "Failed to configure static IP"
    else
        log_info "Configuring DHCP"
        nmcli connection modify "$conn_name" \
            ipv4.method auto &>/dev/null && \
            log_success "DHCP configured" || \
            log_warn "Failed to configure DHCP"
    fi

    nmcli connection up "$conn_name" &>/dev/null && \
        log_success "Physical interface activated" || \
        log_warn "Failed to activate physical interface"

    ip link set "$PHYSICAL_IFACE" up &>/dev/null || true
    sleep 2
}

verify_restore() {
    log_info "Verifying restoration..."

    local has_bridge=false
    if ip link show "$BRIDGE_NAME" &>/dev/null; then
        log_warn "Bridge interface still exists: $BRIDGE_NAME"
        has_bridge=true
    else
        log_success "Bridge interface removed"
    fi

    local has_slave=false
    if nmcli connection show 2>/dev/null | grep -q "^$SLAVE_CONN_NAME"; then
        log_warn "Slave connection still exists: $SLAVE_CONN_NAME"
        has_slave=true
    else
        log_success "Slave connection removed"
    fi

    if ip link show "$PHYSICAL_IFACE" &>/dev/null; then
        log_success "Physical interface exists: $PHYSICAL_IFACE"
        if ip link show "$PHYSICAL_IFACE" | grep -q "state UP"; then
            log_success "Physical interface is UP"
        fi
    else
        log_error "Physical interface not found: $PHYSICAL_IFACE"
    fi

    if [[ "$has_bridge" == "false" && "$has_slave" == "false" ]]; then
        return 0
    else
        return 1
    fi
}

show_status() {
    echo ""
    echo "========================================="
    echo "  Network Configuration Status"
    echo "========================================="
    echo ""
    echo "Bridge:       $BRIDGE_NAME"
    echo "Physical:     $PHYSICAL_IFACE"
    echo "Slave Conn:   $SLAVE_CONN_NAME"
    echo ""
    echo "=== Active NetworkManager Connections ==="
    nmcli connection show 2>/dev/null | grep -E "^[^-]" | head -10 || echo "  No connections"
    echo ""
    echo "=== Physical Interface Status ==="
    ip addr show "$PHYSICAL_IFACE" 2>/dev/null | head -6 || echo "  Not available"
    echo ""
    echo "=== Bridge Interface Status ==="
    ip addr show "$BRIDGE_NAME" 2>/dev/null | head -6 || echo "  Not available"
}

main() {
    init_background_mode
    check_root

    echo ""
    echo "========================================="
    echo "  Network Configuration Rollback"
    echo "========================================="
    echo ""

    if [[ "$BACKGROUND_MODE" != "yes" ]]; then
        log_info "Tip: Run with -b to execute in background"
        log_info "Usage: sudo $0 -b"
        echo ""
    fi

    log_warn "This will remove bridge configuration and restore original network"
    log_warn "Network will be temporarily interrupted"

    if [[ "$BACKGROUND_MODE" != "yes" ]]; then
        echo ""
        read -p "Continue? (y/N): " -n 1 -r
        echo ""
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "Operation cancelled"
            exit 0
        fi
    else
        log_warn "Running in background mode - proceeding automatically"
    fi

    rollback_bridge
    cleanup_bridge_interface
    restore_physical_interface
    show_status

    echo ""
    if verify_restore; then
        log_success "========================================="
        log_success "Rollback completed successfully!"
        log_success "Physical interface should be restored"
        log_success "========================================="
        exit 0
    else
        log_error "========================================="
        log_error "Rollback completed with warnings"
        log_error "Please check network configuration manually"
        log_error "========================================="
        exit 1
    fi
}

parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -b|--background)
                BACKGROUND_MODE="yes"
                shift
                ;;
            -h|--help)
                echo "Usage: sudo $0 [OPTIONS]"
                echo ""
                echo "Options:"
                echo "  -b, --background           Run in background mode (no interaction required)"
                echo "  -h, --help                 Show this help message"
                echo ""
                exit 0
                ;;
            *)
                echo "Unknown option: $1"
                echo "Use -h or --help for usage information"
                exit 1
                ;;
        esac
    done
}

parse_args "$@"
main "$@"

enp1s0 恢复

rollback-network-enp1s0.sh
#!/bin/bash
#===============================================================================
# Script Name: rollback-network-enp1s0.sh
# Description: Rollback bridge network configuration to restore original state
#===============================================================================

BRIDGE_NAME="br-lan"
PHYSICAL_IFACE="enp1s0"
SLAVE_CONN_NAME="enp1s0-bridge-port"

#-------------------------------------------------------------------------------
# Physical Interface Configuration - Configure before rolling back
#-------------------------------------------------------------------------------
# Set to "dhcp" for automatic IP, or "static" for manual configuration
PHYSICAL_IFACE_METHOD="static"

# Static IP configuration (only used when PHYSICAL_IFACE_METHOD="static")
PHYSICAL_IFACE_IP="192.168.2.99/24"
PHYSICAL_IFACE_GATEWAY="192.168.2.1"
PHYSICAL_IFACE_DNS="192.168.2.1"

# Background Execution Options
BACKGROUND_MODE="yes"
LOG_FILE=""

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log_info()    { echo -e "${BLUE}[INFO]${NC} $1"; [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1" >> "$LOG_FILE"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1" >> "$LOG_FILE"; }
log_warn()    { echo -e "${YELLOW}[WARN]${NC} $1";  [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARN] $1"  >> "$LOG_FILE"; }
log_error()   { echo -e "${RED}[ERROR]${NC} $1";   [[ -n "$LOG_FILE" ]] && echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1"  >> "$LOG_FILE"; }

init_background_mode() {
    if [[ "$BACKGROUND_MODE" == "yes" ]]; then
        LOG_FILE="$(dirname "$0")/rollback-$(date +%Y%m%d-%H%M%S).log"
        exec > >(tee -a "$LOG_FILE")
        exec 2>&1
        log_info "Running in background mode, log file: $LOG_FILE"
    fi
}

check_root() {
    if [[ $EUID -ne 0 ]]; then
        log_error "This script requires root privileges"
        log_error "Please run: sudo $0"
        exit 1
    fi
}

rollback_bridge() {
    log_info "Rolling back bridge configuration..."

    log_info "Deleting bridge connection: $BRIDGE_NAME"
    if nmcli connection show "$BRIDGE_NAME" &>/dev/null; then
        nmcli connection down "$BRIDGE_NAME" &>/dev/null || true
        nmcli connection delete "$BRIDGE_NAME" &>/dev/null && \
            log_success "Bridge connection deleted" || \
            log_warn "Failed to delete bridge connection"
    else
        log_info "Bridge connection does not exist"
    fi

    log_info "Deleting slave connection: $SLAVE_CONN_NAME"
    if nmcli connection show "$SLAVE_CONN_NAME" &>/dev/null; then
        nmcli connection down "$SLAVE_CONN_NAME" &>/dev/null || true
        nmcli connection delete "$SLAVE_CONN_NAME" &>/dev/null && \
            log_success "Slave connection deleted" || \
            log_warn "Failed to delete slave connection"
    else
        log_info "Slave connection does not exist"
    fi
}

cleanup_bridge_interface() {
    log_info "Cleaning up bridge interface..."

    if ip link show "$BRIDGE_NAME" &>/dev/null; then
        ip link set "$BRIDGE_NAME" down &>/dev/null || true
        ip link delete "$BRIDGE_NAME" &>/dev/null && \
            log_success "Bridge interface deleted" || \
            log_warn "Failed to delete bridge interface"
    else
        log_info "Bridge interface does not exist"
    fi
}

restore_physical_interface() {
    log_info "Restoring physical interface: $PHYSICAL_IFACE"

    ip link set "$PHYSICAL_IFACE" down &>/dev/null || true
    sleep 1

    log_info "Cleaning up existing connections for $PHYSICAL_IFACE..."
    local existing_conns=$(nmcli connection show 2>/dev/null | grep -E "ethernet.*$PHYSICAL_IFACE" | awk '{print $1}')
    for conn in $existing_conns; do
        log_info "Deleting existing connection: $conn"
        nmcli connection down "$conn" &>/dev/null || true
        nmcli connection delete "$conn" &>/dev/null && \
            log_success "Deleted: $conn" || \
            log_warn "Failed to delete: $conn"
    done

    log_info "Creating new connection for physical interface: $PHYSICAL_IFACE"
    local conn_name="Wired connection 1"
    nmcli connection add \
        type ethernet \
        con-name "$conn_name" \
        ifname "$PHYSICAL_IFACE" \
        connection.autoconnect yes &>/dev/null && \
        log_success "Connection created: $conn_name" || \
        log_warn "Failed to create connection"

    if [[ "$PHYSICAL_IFACE_METHOD" == "static" ]]; then
        log_info "Configuring static IP: $PHYSICAL_IFACE_IP"
        nmcli connection modify "$conn_name" \
            ipv4.method manual \
            ipv4.address "$PHYSICAL_IFACE_IP" \
            ipv4.gateway "$PHYSICAL_IFACE_GATEWAY" \
            ipv4.dns "$PHYSICAL_IFACE_DNS" &>/dev/null && \
            log_success "Static IP configured" || \
            log_warn "Failed to configure static IP"
    else
        log_info "Configuring DHCP"
        nmcli connection modify "$conn_name" \
            ipv4.method auto &>/dev/null && \
            log_success "DHCP configured" || \
            log_warn "Failed to configure DHCP"
    fi

    nmcli connection up "$conn_name" &>/dev/null && \
        log_success "Physical interface activated" || \
        log_warn "Failed to activate physical interface"

    ip link set "$PHYSICAL_IFACE" up &>/dev/null || true
    sleep 2
}

verify_restore() {
    log_info "Verifying restoration..."

    local has_bridge=false
    if ip link show "$BRIDGE_NAME" &>/dev/null; then
        log_warn "Bridge interface still exists: $BRIDGE_NAME"
        has_bridge=true
    else
        log_success "Bridge interface removed"
    fi

    local has_slave=false
    if nmcli connection show 2>/dev/null | grep -q "^$SLAVE_CONN_NAME"; then
        log_warn "Slave connection still exists: $SLAVE_CONN_NAME"
        has_slave=true
    else
        log_success "Slave connection removed"
    fi

    if ip link show "$PHYSICAL_IFACE" &>/dev/null; then
        log_success "Physical interface exists: $PHYSICAL_IFACE"
        if ip link show "$PHYSICAL_IFACE" | grep -q "state UP"; then
            log_success "Physical interface is UP"
        fi
    else
        log_error "Physical interface not found: $PHYSICAL_IFACE"
    fi

    if [[ "$has_bridge" == "false" && "$has_slave" == "false" ]]; then
        return 0
    else
        return 1
    fi
}

show_status() {
    echo ""
    echo "========================================="
    echo "  Network Configuration Status"
    echo "========================================="
    echo ""
    echo "Bridge:       $BRIDGE_NAME"
    echo "Physical:     $PHYSICAL_IFACE"
    echo "Slave Conn:   $SLAVE_CONN_NAME"
    echo ""
    echo "=== Active NetworkManager Connections ==="
    nmcli connection show 2>/dev/null | grep -E "^[^-]" | head -10 || echo "  No connections"
    echo ""
    echo "=== Physical Interface Status ==="
    ip addr show "$PHYSICAL_IFACE" 2>/dev/null | head -6 || echo "  Not available"
    echo ""
    echo "=== Bridge Interface Status ==="
    ip addr show "$BRIDGE_NAME" 2>/dev/null | head -6 || echo "  Not available"
}

main() {
    init_background_mode
    check_root

    echo ""
    echo "========================================="
    echo "  Network Configuration Rollback"
    echo "========================================="
    echo ""

    if [[ "$BACKGROUND_MODE" != "yes" ]]; then
        log_info "Tip: Run with -b to execute in background"
        log_info "Usage: sudo $0 -b"
        echo ""
    fi

    log_warn "This will remove bridge configuration and restore original network"
    log_warn "Network will be temporarily interrupted"

    if [[ "$BACKGROUND_MODE" != "yes" ]]; then
        echo ""
        read -p "Continue? (y/N): " -n 1 -r
        echo ""
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            log_info "Operation cancelled"
            exit 0
        fi
    else
        log_warn "Running in background mode - proceeding automatically"
    fi

    rollback_bridge
    cleanup_bridge_interface
    restore_physical_interface
    show_status

    echo ""
    if verify_restore; then
        log_success "========================================="
        log_success "Rollback completed successfully!"
        log_success "Physical interface should be restored"
        log_success "========================================="
        exit 0
    else
        log_error "========================================="
        log_error "Rollback completed with warnings"
        log_error "Please check network configuration manually"
        log_error "========================================="
        exit 1
    fi
}

parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -b|--background)
                BACKGROUND_MODE="yes"
                shift
                ;;
            -h|--help)
                echo "Usage: sudo $0 [OPTIONS]"
                echo ""
                echo "Options:"
                echo "  -b, --background           Run in background mode (no interaction required)"
                echo "  -h, --help                 Show this help message"
                echo ""
                exit 0
                ;;
            *)
                echo "Unknown option: $1"
                echo "Use -h or --help for usage information"
                exit 1
                ;;
        esac
    done
}

parse_args "$@"
main "$@"