針對多閘道環境,撰寫 Python 腳本定期偵測網路連通性,失敗時自動切換 /etc/network/interfaces 中的閘道 IP 並重啟網路服務。適用於雙 WAN、備援閘道場景。
www.baidu.com)gateway 行 → 寫回檔案/etc/init.d/networking restart 套用變更
#!/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 +xcrontab -e 定期執行:*/5 * * * * /usr/local/bin/auto_gateway.py >> /var/log/auto_gateway.log 2>&1/etc/systemd/system/auto-gateway.service + .timerlogrotate 管理 /var/log/auto_gateway.log.network 檔案 Gateway= 多行 + RouteMetric此腳本適用於傳統 ifupdown 環境,現代發行版建議優先使用原生網路管理工具。