import requests
from concurrent.futures import ThreadPoolExecutor
import ipaddress
import netifaces
import argparse
import socket
from datetime import datetime
def get_local_network():
"""获取本机所在的局域网网段"""
for interface in netifaces.interfaces():
addrs = netifaces.ifaddresses(interface)
if netifaces.AF_INET in addrs:
for addr_info in addrs[netifaces.AF_INET]:
ip = addr_info['addr']
if ip == '127.0.0.1':
continue
netmask = addr_info['netmask']
network = ipaddress.IPv4Network(f"{ip}/{netmask}", strict=False)
return network
return None
def scan_ollama(ip, port, timeout):
"""扫描指定 IP 和端口的 Ollama 服务"""
url = f"http://{ip}:{port}/api/tags"
try:
response = requests.get(url, timeout=timeout)
if response.status_code == 200:
data = response.json()
models = [model['name'] for model in data.get('models', [])]
return (ip, port, models)
except (requests.ConnectionError, requests.Timeout, requests.JSONDecodeError):
pass
return None
def main():
parser = argparse.ArgumentParser(description='扫描局域网内的 Ollama 服务及模型')
parser.add_argument('-p', '--ports', nargs='+', type=int, default=[11434],
help='要扫描的端口列表(默认:11434)')
parser.add_argument('-t', '--threads', type=int, default=50,
help='并发线程数(默认:50)')
parser.add_argument('-T', '--timeout', type=float, default=2.0,
help='请求超时时间(秒)(默认:2)')
args = parser.parse_args()
network = get_local_network()
if not network:
print("无法检测到本地网络接口")
return
print(f"扫描网络: {network}")
print(f"扫描端口: {args.ports}")
print(f"开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("=" * 60)
found = []
with ThreadPoolExecutor(max_workers=args.threads) as executor:
futures = []
for host in network.hosts():
ip = str(host)
for port in args.ports:
futures.append(
executor.submit(scan_ollama, ip, port, args.timeout)
)
for future in futures:
result = future.result()
if result:
found.append(result)
if not found:
print("未找到运行 Ollama 服务的主机")
return
print("\n发现以下 Ollama 实例:")
for ip, port, models in found:
print(f"IP: {ip}:{port}")
print(f"可用模型 ({len(models)}):")
for model in models:
print(f" - {model}")
print("-" * 60)
if __name__ == "__main__":
main()