首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Linux Python 自動切換閘道腳本:網路偵測、介面配置修改與服務重啟實戰

     編輯:更多程式設計知識

針對多閘道環境,撰寫 Python 腳本定期偵測網路連通性,失敗時自動切換 /etc/network/interfaces 中的閘道 IP 並重啟網路服務。適用於雙 WAN、備援閘道場景。

核心邏輯流程

  1. Ping 測試目標主機 (預設 www.baidu.com)
  2. 失敗時:讀取介面配置檔 → 正則替換 gateway 行 → 寫回檔案
  3. 執行 /etc/init.d/networking restart 套用變更
  4. 例外捕獲防止腳本崩潰

完整腳本 (已修正語法與安全性)


#!/usr/bin/env python3
import os
import re
import random
import subprocess
import sys
import time

GATEWAY_BASE = 'gateway 192.168.1.'
TEST_HOST = 'www.baidu.com'
PING_CMD = ['ping', '-c', '3', TEST_HOST]
RESTART_CMD = ['/etc/init.d/networking', 'restart']
INTERFACES_FILE = '/etc/network/interfaces'
GATEWAY_OPTIONS = [1, 2, 3]  # 可用閘道尾碼

def test_connectivity():
    """回傳 True 若 ping 成功"""
    try:
        result = subprocess.run(PING_CMD, capture_output=True, timeout=10)
        return result.returncode == 0
    except subprocess.TimeoutExpired:
        return False
    except Exception:
        return False

def switch_gateway(current_last_octet):
    """切換到不同閘道,回傳新尾碼"""
    available = [g for g in GATEWAY_OPTIONS if g != current_last_octet]
    if not available:
        return current_last_octet
    new_octet = random.choice(available)
    
    try:
        with open(INTERFACES_FILE, 'r') as f:
            content = f.read()
        
        # 替換 gateway 行
        new_content = re.sub(
            r'gateway\s+192\.168\.1\.\d+',
            f'gateway 192.168.1.{new_octet}',
            content
        )
        
        with open(INTERFACES_FILE, 'w') as f:
            f.write(new_content)
        
        print(f'已切換閘道至 192.168.1.{new_octet}')
        return new_octet
    except Exception as e:
        print(f'修改配置失敗: {e}', file=sys.stderr)
        return current_last_octet

def restart_networking():
    try:
        subprocess.run(RESTART_CMD, check=True, timeout=30)
        print('網路服務重啟完成')
        return True
    except subprocess.CalledProcessError as e:
        print(f'重啟失敗: {e}', file=sys.stderr)
        return False
    except Exception as e:
        print(f'重啟異常: {e}', file=sys.stderr)
        return False

def main():
    if os.geteuid() != 0:
        print('需 root 權限執行', file=sys.stderr)
        sys.exit(1)
    
    # 讀取當前閘道
    current = 1
    try:
        with open(INTERFACES_FILE) as f:
            for line in f:
                m = re.search(r'gateway\s+192\.168\.1\.(\d+)', line)
                if m:
                    current = int(m.group(1))
                    break
    except Exception:
        pass
    
    print(f'當前閘道: 192.168.1.{current}')
    
    if not test_connectivity():
        print('連通性測試失敗,嘗試切換閘道...')
        new_gw = switch_gateway(current)
        if new_gw != current:
            restart_networking()
            # 等待網路穩定後再測試
            time.sleep(5)
            if test_connectivity():
                print('切換成功,網路恢復')
            else:
                print('切換後仍失敗,請人工介入')
        else:
            print('無可用備援閘道')
    else:
        print('網路正常')

if __name__ == '__main__':
    main()

關鍵技術點解析

技術點說明
subprocess.run取代 os.system,支援 timeout、capture_output、錯誤碼檢查
正則替換re.sub(r'gateway\s+192\.168\.1\.\d+', ...) 精準匹配閘道行
權限檢查os.geteuid() != 0 確保 root 執行
隨機備援random.choice 從可用閘道中隨機挑選,避免單點故障

部署建議

  • 放入 /usr/local/bin/auto_gateway.py,chmod +x
  • 加入 crontab -e 定期執行:*/5 * * * * /usr/local/bin/auto_gateway.py >> /var/log/auto_gateway.log 2>&1
  • systemd 服務化:建立 /etc/systemd/system/auto-gateway.service + .timer
  • 日誌輪轉:logrotate 管理 /var/log/auto_gateway.log

現代 Linux 替代方案

  • NetworkManager:內建連線設定檔優先級、自動切換
  • systemd-networkd:.network 檔案 Gateway= 多行 + RouteMetric
  • keepalived / VRRP:企業級高可用閘道備援

此腳本適用於傳統 ifupdown 環境,現代發行版建議優先使用原生網路管理工具。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved