Python開發(fā)一個(gè)實(shí)用的網(wǎng)絡(luò)連通性檢查工具
簡介
網(wǎng)絡(luò)連通性是現(xiàn)代計(jì)算機(jī)系統(tǒng)正常運(yùn)行的基礎(chǔ)。無論是訪問互聯(lián)網(wǎng)、連接內(nèi)部網(wǎng)絡(luò)還是與其他設(shè)備通信,網(wǎng)絡(luò)連接的穩(wěn)定性都至關(guān)重要。當(dāng)網(wǎng)絡(luò)出現(xiàn)問題時(shí),快速診斷和定位故障點(diǎn)是解決問題的關(guān)鍵。本文將介紹一個(gè)實(shí)用的Python腳本——網(wǎng)絡(luò)連通性檢查工具,它可以全面檢查網(wǎng)絡(luò)連接狀態(tài),幫助用戶快速診斷網(wǎng)絡(luò)問題。
功能介紹
這個(gè)網(wǎng)絡(luò)連通性檢查工具具有以下核心功能:
- Ping測(cè)試:測(cè)試與目標(biāo)主機(jī)的ICMP連通性
- 端口檢查:檢查指定主機(jī)的端口是否開放
- DNS解析測(cè)試:驗(yàn)證域名解析功能
- HTTP連通性測(cè)試:測(cè)試Web服務(wù)的可達(dá)性
- 多目標(biāo)批量測(cè)試:支持同時(shí)測(cè)試多個(gè)目標(biāo)
- 詳細(xì)報(bào)告生成:提供詳細(xì)的測(cè)試結(jié)果報(bào)告
- 定時(shí)監(jiān)控:支持定期檢查網(wǎng)絡(luò)連通性
- 告警通知:在網(wǎng)絡(luò)故障時(shí)發(fā)送告警通知
應(yīng)用場(chǎng)景
這個(gè)工具適用于以下場(chǎng)景:
- 網(wǎng)絡(luò)故障排查:快速診斷網(wǎng)絡(luò)連接問題
- 系統(tǒng)監(jiān)控:監(jiān)控關(guān)鍵網(wǎng)絡(luò)服務(wù)的可用性
- 運(yùn)維自動(dòng)化:集成到運(yùn)維流程中自動(dòng)檢查網(wǎng)絡(luò)狀態(tài)
- 網(wǎng)絡(luò)性能測(cè)試:評(píng)估網(wǎng)絡(luò)連接的質(zhì)量和延遲
- 安全審計(jì):檢查網(wǎng)絡(luò)服務(wù)的開放狀態(tài)
- 災(zāi)難恢復(fù):在網(wǎng)絡(luò)恢復(fù)后驗(yàn)證連接狀態(tài)
報(bào)錯(cuò)處理
腳本包含了完善的錯(cuò)誤處理機(jī)制:
- 超時(shí)處理:合理設(shè)置網(wǎng)絡(luò)操作的超時(shí)時(shí)間
- 異常捕獲:捕獲并處理網(wǎng)絡(luò)操作中的各種異常
- 權(quán)限驗(yàn)證:檢查是否有足夠的權(quán)限執(zhí)行網(wǎng)絡(luò)測(cè)試
- DNS解析保護(hù):處理DNS解析失敗的情況
- 連接重試:在網(wǎng)絡(luò)不穩(wěn)定時(shí)自動(dòng)重試連接
- 資源清理:確保網(wǎng)絡(luò)連接和資源得到正確釋放
代碼實(shí)現(xiàn)
import os
import sys
import subprocess
import socket
import argparse
import json
import time
from datetime import datetime
import threading
import requests
from urllib.parse import urlparse
class NetworkConnectivityChecker:
def __init__(self):
self.results = []
self.errors = []
self.monitoring = False
def ping_host(self, host, count=4, timeout=3):
"""Ping測(cè)試"""
try:
# 根據(jù)操作系統(tǒng)選擇ping命令
if os.name == 'nt': # Windows
cmd = ['ping', '-n', str(count), '-w', str(timeout * 1000), host]
else: # Linux/macOS
cmd = ['ping', '-c', str(count), '-W', str(timeout), host]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout * count + 5)
if result.returncode == 0:
# 解析ping輸出獲取統(tǒng)計(jì)信息
output = result.stdout
packet_loss = 0
avg_rtt = 0
if os.name == 'nt': # Windows
# Windows ping輸出解析
for line in output.split('\n'):
if 'Lost' in line:
# 匹配 "Lost = X (X% loss)"
import re
match = re.search(r'\((\d+)% loss\)', line)
if match:
packet_loss = int(match.group(1))
elif 'Average' in line:
# 匹配 "Average = Xms"
import re
match = re.search(r'Average = (\d+)ms', line)
if match:
avg_rtt = int(match.group(1))
else: # Linux/macOS
# Unix-like系統(tǒng)ping輸出解析
for line in output.split('\n'):
if 'packet loss' in line:
# 匹配 "X packets transmitted, Y received, Z% packet loss"
import re
match = re.search(r'(\d+)% packet loss', line)
if match:
packet_loss = int(match.group(1))
elif 'rtt' in line:
# 匹配 "rtt min/avg/max/mdev = X/Y/Z/W ms"
import re
match = re.search(r'rtt [^=]+= [^/]+/([^/]+)/', line)
if match:
avg_rtt = float(match.group(1))
return {
'host': host,
'status': 'reachable',
'packet_loss': packet_loss,
'avg_rtt': avg_rtt,
'output': output
}
else:
return {
'host': host,
'status': 'unreachable',
'error': result.stderr or 'Host unreachable',
'output': result.stdout
}
except subprocess.TimeoutExpired:
return {
'host': host,
'status': 'timeout',
'error': f'Ping timeout after {timeout * count + 5} seconds'
}
except Exception as e:
return {
'host': host,
'status': 'error',
'error': str(e)
}
def check_port(self, host, port, timeout=3):
"""端口檢查"""
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
result = sock.connect_ex((host, port))
sock.close()
if result == 0:
return {
'host': host,
'port': port,
'status': 'open'
}
else:
return {
'host': host,
'port': port,
'status': 'closed',
'error': f'Connection refused (code: {result})'
}
except socket.gaierror as e:
return {
'host': host,
'port': port,
'status': 'dns_error',
'error': f'DNS resolution failed: {e}'
}
except Exception as e:
return {
'host': host,
'port': port,
'status': 'error',
'error': str(e)
}
def resolve_dns(self, hostname):
"""DNS解析測(cè)試"""
try:
ip_addresses = socket.getaddrinfo(hostname, None)
ips = []
for addr_info in ip_addresses:
ip = addr_info[4][0]
if ip not in ips:
ips.append(ip)
return {
'hostname': hostname,
'status': 'resolved',
'ip_addresses': ips
}
except socket.gaierror as e:
return {
'hostname': hostname,
'status': 'unresolved',
'error': str(e)
}
except Exception as e:
return {
'hostname': hostname,
'status': 'error',
'error': str(e)
}
def http_check(self, url, timeout=10):
"""HTTP連通性測(cè)試"""
try:
parsed_url = urlparse(url)
if not parsed_url.scheme:
url = 'http://' + url
response = requests.get(url, timeout=timeout)
return {
'url': url,
'status': 'accessible',
'status_code': response.status_code,
'response_time': response.elapsed.total_seconds(),
'content_length': len(response.content)
}
except requests.exceptions.Timeout:
return {
'url': url,
'status': 'timeout',
'error': f'Request timeout after {timeout} seconds'
}
except requests.exceptions.ConnectionError as e:
return {
'url': url,
'status': 'connection_error',
'error': str(e)
}
except requests.exceptions.RequestException as e:
return {
'url': url,
'status': 'error',
'error': str(e)
}
except Exception as e:
return {
'url': url,
'status': 'error',
'error': str(e)
}
def check_target(self, target):
"""檢查單個(gè)目標(biāo)"""
result = {
'target': target,
'timestamp': datetime.now().isoformat(),
'tests': {}
}
# 判斷目標(biāo)類型
if target.startswith('http://') or target.startswith('https://'):
# HTTP測(cè)試
result['tests']['http'] = self.http_check(target)
elif ':' in target and not target.replace(':', '').replace('.', '').isdigit():
# 主機(jī)名:端口格式
host, port = target.rsplit(':', 1)
if port.isdigit():
result['tests']['ping'] = self.ping_host(host)
result['tests']['port'] = self.check_port(host, int(port))
result['tests']['dns'] = self.resolve_dns(host)
else:
result['tests']['ping'] = self.ping_host(target)
result['tests']['dns'] = self.resolve_dns(target)
elif target.replace('.', '').isdigit() or not target.replace('-', '').replace('.', '').isdigit():
# IP地址或主機(jī)名
result['tests']['ping'] = self.ping_host(target)
result['tests']['dns'] = self.resolve_dns(target)
else:
# 默認(rèn)進(jìn)行ping測(cè)試
result['tests']['ping'] = self.ping_host(target)
return result
def check_multiple_targets(self, targets):
"""檢查多個(gè)目標(biāo)"""
print(f"開始檢查 {len(targets)} 個(gè)目標(biāo)")
print("=" * 60)
self.results = []
for target in targets:
print(f"檢查目標(biāo): {target}")
result = self.check_target(target)
self.results.append(result)
# 顯示結(jié)果
tests = result['tests']
for test_type, test_result in tests.items():
status_icons = {
'reachable': '?',
'open': '?',
'resolved': '?',
'accessible': '?',
'unreachable': '?',
'closed': '?',
'unresolved': '?',
'timeout': '?',
'error': '??',
'connection_error': '?',
'dns_error': '?'
}
icon = status_icons.get(test_result['status'], '?')
print(f" {test_type.upper()}: {icon} {test_result['status']}")
if 'error' in test_result:
print(f" 錯(cuò)誤: {test_result['error']}")
elif test_type == 'ping':
if 'packet_loss' in test_result:
print(f" 丟包率: {test_result['packet_loss']}%")
if 'avg_rtt' in test_result and test_result['avg_rtt'] > 0:
print(f" 平均延遲: {test_result['avg_rtt']}ms")
elif test_type == 'port':
print(f" 端口: {test_result['port']}")
elif test_type == 'http':
if 'status_code' in test_result:
print(f" 狀態(tài)碼: {test_result['status_code']}")
if 'response_time' in test_result:
print(f" 響應(yīng)時(shí)間: {test_result['response_time']:.3f}s")
elif test_type == 'dns':
if 'ip_addresses' in test_result:
print(f" IP地址: {', '.join(test_result['ip_addresses'])}")
print()
return self.results
def generate_report(self):
"""生成檢查報(bào)告"""
report = []
report.append("=" * 80)
report.append("網(wǎng)絡(luò)連通性檢查報(bào)告")
report.append("=" * 80)
report.append(f"檢查時(shí)間: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
report.append(f"檢查目標(biāo)數(shù): {len(self.results)}")
report.append("")
# 統(tǒng)計(jì)信息
stats = {
'reachable': 0,
'unreachable': 0,
'timeout': 0,
'error': 0
}
for result in self.results:
for test_result in result['tests'].values():
status = test_result['status']
if status in stats:
stats[status] += 1
elif status not in ['open', 'resolved', 'accessible']:
stats['error'] += 1
report.append("狀態(tài)統(tǒng)計(jì):")
report.append(f" 可達(dá): {stats['reachable']}")
report.append(f" 不可達(dá): {stats['unreachable']}")
report.append(f" 超時(shí): {stats['timeout']}")
report.append(f" 錯(cuò)誤: {stats['error']}")
report.append("")
# 詳細(xì)結(jié)果
report.append("詳細(xì)檢查結(jié)果:")
report.append("-" * 50)
for result in self.results:
report.append(f"目標(biāo): {result['target']}")
for test_type, test_result in result['tests'].items():
status_display = {
'reachable': '? 可達(dá)',
'open': '? 開放',
'resolved': '? 已解析',
'accessible': '? 可訪問',
'unreachable': '? 不可達(dá)',
'closed': '? 關(guān)閉',
'unresolved': '? 未解析',
'timeout': '? 超時(shí)',
'error': '?? 錯(cuò)誤',
'connection_error': '? 連接錯(cuò)誤',
'dns_error': '? DNS錯(cuò)誤'
}
status_text = status_display.get(test_result['status'], test_result['status'])
report.append(f" {test_type.upper()}: {status_text}")
if 'error' in test_result:
report.append(f" 錯(cuò)誤: {test_result['error']}")
elif test_type == 'ping':
if 'packet_loss' in test_result:
report.append(f" 丟包率: {test_result['packet_loss']}%")
if 'avg_rtt' in test_result and test_result['avg_rtt'] > 0:
report.append(f" 平均延遲: {test_result['avg_rtt']}ms")
elif test_type == 'port':
report.append(f" 端口: {test_result['port']}")
elif test_type == 'http':
if 'status_code' in test_result:
report.append(f" 狀態(tài)碼: {test_result['status_code']}")
if 'response_time' in test_result:
report.append(f" 響應(yīng)時(shí)間: {test_result['response_time']:.3f}s")
elif test_type == 'dns':
if 'ip_addresses' in test_result:
report.append(f" IP地址: {', '.join(test_result['ip_addresses'])}")
report.append("")
# 錯(cuò)誤信息
if self.errors:
report.append("錯(cuò)誤信息:")
report.append("-" * 50)
for error in self.errors[:10]: # 只顯示前10個(gè)錯(cuò)誤
report.append(f" {error}")
if len(self.errors) > 10:
report.append(f" ... 還有 {len(self.errors) - 10} 個(gè)錯(cuò)誤")
report.append("")
report.append("=" * 80)
return "\n".join(report)
def save_report(self, filename):
"""保存報(bào)告到文件"""
try:
report = self.generate_report()
with open(filename, 'w', encoding='utf-8') as f:
f.write(report)
print(f"報(bào)告已保存到: {filename}")
return True
except Exception as e:
print(f"保存報(bào)告時(shí)出錯(cuò): {e}")
return False
def save_json_report(self, filename):
"""保存JSON格式報(bào)告"""
try:
report_data = {
'check_time': datetime.now().isoformat(),
'results': self.results,
'errors': self.errors
}
with open(filename, 'w', encoding='utf-8') as f:
json.dump(report_data, f, indent=2, ensure_ascii=False)
print(f"JSON報(bào)告已保存到: {filename}")
return True
except Exception as e:
print(f"保存JSON報(bào)告時(shí)出錯(cuò): {e}")
return False
def continuous_monitor(self, targets, interval=60, max_checks=None):
"""持續(xù)監(jiān)控網(wǎng)絡(luò)連通性"""
check_count = 0
try:
while True:
print(f"\n[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 開始第 {check_count + 1} 次檢查")
self.check_multiple_targets(targets)
# 顯示簡要狀態(tài)
success_count = 0
total_tests = 0
for result in self.results:
for test_result in result['tests'].values():
total_tests += 1
if test_result['status'] in ['reachable', 'open', 'resolved', 'accessible']:
success_count += 1
print(f"成功測(cè)試: {success_count}/{total_tests}")
check_count += 1
# 檢查是否達(dá)到最大檢查次數(shù)
if max_checks and check_count >= max_checks:
break
# 等待下次檢查
time.sleep(interval)
except KeyboardInterrupt:
print("\n\n停止監(jiān)控...")
def main():
parser = argparse.ArgumentParser(description="網(wǎng)絡(luò)連通性檢查工具")
parser.add_argument("targets", nargs='*', help="要檢查的目標(biāo)(主機(jī)名、IP地址、URL等)")
parser.add_argument("-f", "--file", help="從文件讀取目標(biāo)列表")
parser.add_argument("-o", "--output", help="保存報(bào)告到文件")
parser.add_argument("-j", "--json", help="保存JSON報(bào)告到文件")
parser.add_argument("-m", "--monitor", type=int, help="持續(xù)監(jiān)控間隔(秒)")
parser.add_argument("--max-checks", type=int, help="最大檢查次數(shù)")
parser.add_argument("--timeout", type=int, default=3, help="網(wǎng)絡(luò)操作超時(shí)時(shí)間(秒,默認(rèn):3)")
args = parser.parse_args()
# 檢查目標(biāo)
targets = []
if args.targets:
targets.extend(args.targets)
if args.file:
try:
with open(args.file, 'r', encoding='utf-8') as f:
file_targets = [line.strip() for line in f if line.strip()]
targets.extend(file_targets)
except Exception as e:
print(f"讀取目標(biāo)文件時(shí)出錯(cuò): {e}")
sys.exit(1)
if not targets:
print("請(qǐng)指定要檢查的目標(biāo)")
parser.print_help()
sys.exit(1)
# 檢查requests庫
try:
import requests
except ImportError:
print("警告: 缺少requests庫,HTTP測(cè)試功能將不可用")
print("安裝命令: pip install requests")
try:
checker = NetworkConnectivityChecker()
# 檢查網(wǎng)絡(luò)連通性
if args.monitor:
# 持續(xù)監(jiān)控模式
checker.continuous_monitor(targets, args.monitor, args.max_checks)
else:
# 單次檢查模式
checker.check_multiple_targets(targets)
# 生成報(bào)告
if args.output:
checker.save_report(args.output)
elif args.json:
checker.save_json_report(args.json)
else:
print(checker.generate_report())
except KeyboardInterrupt:
print("\n\n用戶中斷操作")
except Exception as e:
print(f"程序執(zhí)行出錯(cuò): {e}")
sys.exit(1)
if __name__ == "__main__":
main()
使用方法
安裝依賴
在使用此腳本之前,需要安裝必要的庫:
# HTTP測(cè)試需要 pip install requests
基本使用
# 檢查單個(gè)目標(biāo) python network_checker.py google.com # 檢查多個(gè)目標(biāo) python network_checker.py google.com github.com 8.8.8.8 # 檢查特定端口 python network_checker.py google.com:443 github.com:22 # 檢查HTTP服務(wù) python network_checker.py https://www.google.com http://github.com # 從文件讀取目標(biāo)列表 python network_checker.py -f targets.txt # 保存報(bào)告到文件 python network_checker.py google.com github.com -o network_report.txt # 保存JSON報(bào)告 python network_checker.py google.com github.com -j network_report.json # 持續(xù)監(jiān)控(每30秒檢查一次) python network_checker.py google.com github.com -m 30 # 持續(xù)監(jiān)控最多10次 python network_checker.py google.com github.com -m 30 --max-checks 10
目標(biāo)文件示例
創(chuàng)建目標(biāo)文件 targets.txt:
google.com
github.com
8.8.8.8
1.1.1.1
https://www.baidu.com
google.com:443
github.com:22
命令行參數(shù)說明
targets: 要檢查的目標(biāo)(可多個(gè))-f, --file: 從文件讀取目標(biāo)列表-o, --output: 保存報(bào)告到指定文件-j, --json: 保存JSON報(bào)告到指定文件-m, --monitor: 持續(xù)監(jiān)控間隔(秒)--max-checks: 最大檢查次數(shù)--timeout: 網(wǎng)絡(luò)操作超時(shí)時(shí)間(秒,默認(rèn):3)
使用示例
基本檢查:
python network_checker.py google.com github.com 8.8.8.8
持續(xù)監(jiān)控:
python network_checker.py google.com github.com -m 60 --max-checks 10 -o status.log
綜合測(cè)試:
python network_checker.py -f targets.txt -o full_report.txt -j report.json
總結(jié)
這個(gè)網(wǎng)絡(luò)連通性檢查工具提供了一個(gè)全面的網(wǎng)絡(luò)診斷解決方案,能夠測(cè)試Ping連通性、端口開放狀態(tài)、DNS解析和HTTP服務(wù)可達(dá)性。它支持批量測(cè)試多個(gè)目標(biāo),提供詳細(xì)的測(cè)試報(bào)告,并可以持續(xù)監(jiān)控網(wǎng)絡(luò)狀態(tài)。工具適用于網(wǎng)絡(luò)故障排查、系統(tǒng)監(jiān)控和運(yùn)維自動(dòng)化等多種場(chǎng)景。通過這個(gè)工具,用戶可以快速診斷網(wǎng)絡(luò)問題,確保網(wǎng)絡(luò)服務(wù)的穩(wěn)定運(yùn)行。
以上就是Python開發(fā)一個(gè)實(shí)用的網(wǎng)絡(luò)連通性檢查工具的詳細(xì)內(nèi)容,更多關(guān)于Python網(wǎng)絡(luò)連通性檢查的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
pycharm安裝深度學(xué)習(xí)pytorch的d2l包失敗問題解決
當(dāng)新生在學(xué)習(xí)pytorch時(shí),導(dǎo)入d2l_pytorch包總會(huì)遇到問題,下面這篇文章主要給大家介紹了關(guān)于pycharm安裝深度學(xué)習(xí)pytorch的d2l包失敗問題的解決方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-03-03
Python讀取英文文件并記錄每個(gè)單詞出現(xiàn)次數(shù)后降序輸出示例
這篇文章主要介紹了Python讀取英文文件并記錄每個(gè)單詞出現(xiàn)次數(shù)后降序輸出,涉及Python文件讀取、字符串替換、分割以及字典遍歷、排序等相關(guān)操作技巧,需要的朋友可以參考下2018-06-06
Python使用BeautifulSoup實(shí)現(xiàn)網(wǎng)頁鏈接的提取與分析
本文將詳細(xì)介紹如何使用Python的BeautifulSoup庫實(shí)現(xiàn)網(wǎng)頁鏈接的提取與分析,我們將從基礎(chǔ)概念講起,逐步深入到實(shí)際應(yīng)用場(chǎng)景,包括HTML解析原理、鏈接提取技術(shù)、數(shù)據(jù)分析方法等,通過本文,讀者將學(xué)習(xí)如何對(duì)提取的鏈接數(shù)據(jù)進(jìn)行有價(jià)值的分析,需要的朋友可以參考下2025-07-07
Python在實(shí)時(shí)數(shù)據(jù)流處理中集成Flink與Kafka
隨著大數(shù)據(jù)和實(shí)時(shí)計(jì)算的興起,實(shí)時(shí)數(shù)據(jù)流處理變得越來越重要,Flink和Kafka是實(shí)時(shí)數(shù)據(jù)流處理領(lǐng)域的兩個(gè)關(guān)鍵技術(shù),下面我們就來看看如何使用Python將Flink和Kafka集成在一起吧2025-03-03
python分析inkscape路徑數(shù)據(jù)方案簡單介紹
這篇文章主要介紹了python分析inkscape路徑數(shù)據(jù)方案簡單介紹,文章通過圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-09-09
在flask中使用python-dotenv+flask-cli自定義命令(推薦)
這篇文章主要介紹了在flask中使用python-dotenv+flask-cli自定義命令的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-01-01

