南京邮电大学交换技术与通信网实验自动执行脚本

南京邮电大学交换技术与通信网实验自动执行脚本

这个作业要一行一行输入 GNS3 的 Solar-PuTTy,挺麻烦的,于是就写了一个脚本用来一键执行,当然这个脚本并不能帮你解决你的作业,只是可以很方便执行指令,让你专注于具体内容罢了

这个脚本只用于完成作业,如果要实际使用可以在此基础上使用 GNS3 提供的 api 接口来进行二次开发

使用步骤

安装 Python

安装 Python 在此不做赘述,这个 Python 脚本也不需要 pip 任何的库
我使用的 Python 版本为 3.12,由于 telnetlib 库本身是一个 Deprecated 的库,python 版本应该低于 3.13

写下指令

Python文件相同的目录下的 commands.txt 内写下你需要的指令,允许使用 // 进行行注释,注意需要先切换到一个具体的路由器上,例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// commands.txt

// 切换至 R1
switch_router localhost 5000 // 伪指令,切换到localhost:5000
// 根据 server_settings localhost:5000 是指第1个路由器,即为 R1
config t
int s1/0
ip address 11.11.88.1 255.255.255.252
no shutdown
exit
int loopback0
ip address 11.11.0.1 255.255.255.255
end
write
show ip int b

// 切换至 R2
switch_router localhost 5001
config t
int s1/1
ip address 11.11.88.2 255.255.255.252
no shutdown
exit
int s1/0
ip address 11.11.88.5 255.255.255.252
no shutdown
exit
int loopback0
ip address 11.11.0.2 255.255.255.255
end
write
show ip int b

注意添加了一个伪指令 switch_router <IP address> <Port>,这个指的是你在软件里拖的路由器标记的那个的地址,在 GNS3 的设置里是可以更改的
不建议修改 GNS3 安装时默认监听的 IP地址 与端口号
默认的 IP 地址是 localhost
路由器的端口号默认时 5000-10000,第1个路由器就是 5000,第2个是5001,如果你修改了,请自己更改上面这条伪指令里的值

启动你的路由器


一定要启动路由器,而且路由器一定要是 R1、R2…这样的命名(即默认命名),否则脚本无法连接上,并且注意脚本运行时不要打开你 GNS3 里自带的终端,否则有可能卡住

如果因此不慎卡住,请关闭脚本并关掉 GNS3 的所有路由器,可以解决问题

运行脚本

1
python main.py

运行脚本会逐行读取你 commands.txt 内的指令,遇到 switch_router 会切换到对应路由器环境下,遇到空行和注释会跳过,遇到具体指令就会发送给当前路由器进行执行,总之免去了一行一行输入的麻烦

运行大致能得到如下结果,输出的内容有回显

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import telnetlib
import time
import re
import sys

HOSTNAME = ""
FILENAME = 'commands.txt'
FIRSTFLAG = False

def telnet_login_and_wait_for_prompt(host, port=23, delay=0.5, timeout=5):
try:
tn = telnetlib.Telnet(host, port, timeout)
print(f"[NOTE] Waiting for {delay} seconds to allow the device to initialize...")
time.sleep(delay)
tn.write(b"\r")
output = tn.read_very_eager().decode('ascii')
tn.write(b"\r")
return tn
except Exception as e:
print(f"[Error] question occurred while connecting: {e}")
return None

def send_telnet_command(tn, command, timeout=10):
global FIRSTFLAG
# print(f"[Debug] command: {command}")
tn.write(command.encode('ascii') + b"\r")

prompt_patterns = [
fr"{HOSTNAME}\(config-[\w-]+\)#",
fr"{HOSTNAME}\(config\)#",
fr"{HOSTNAME}#",
]
output_cache = ""
while True:

output = tn.read_some().decode('ascii')
output_cache += output
print(output, end="")
output_cache = output_cache.splitlines()[-1] if "\n" in output_cache else output_cache
if re.search(r"--More--", output_cache):
tn.write(b"\r")
output_cache = ""
continue
if re.search(r"#", output):
if FIRSTFLAG:
FIRSTFLAG = False
continue
# print(f"[Debug] output_cache: {output_cache}")
for pattern in prompt_patterns:
if re.search(pattern, output_cache):
# print(f"[Debug] find patterns {pattern}")
output_cache = ""
return tn

def load_commands_from_file(filename):
with open(filename, 'r', encoding='utf-8') as file:
commands = [line.strip() for line in file.readlines() if line.strip()]
return commands

def process_commands(commands):
global HOSTNAME, FIRSTFLAG
tn = None
for command in commands:
command = command.split('//')[0].strip()
if not command:
continue
# 伪指令:切换路由器 switch_router
if command.startswith('switch_router'):
_, new_host, new_port = command.split()
HOSTNAME = f"R{int(new_port) - 4999}"
FIRSTFLAG = True
if tn:
tn.write(b"exit\r")
print("exit")
tn.close()
print(f"\n[NOTE] Switching to router {new_host} on port {new_port}")
tn = telnet_login_and_wait_for_prompt(new_host, int(new_port))
else:
if tn:
send_telnet_command(tn, command)
else:
print("[Error] No active Telnet session. Skipping command.")
return tn

def configure_router():
commands = load_commands_from_file(FILENAME)
tn = process_commands(commands)

if tn:
tn.write(b"exit\r")
tn.close()

# if __name__ == "__main__":
# with open("output.txt", "w") as file:
# # 重定向标准输出到文件
# sys.stdout = file

# # 示例打印内容
# print("This will be written to the file.")
# print("Another line in the file.")
# configure_router()
# print("exit\n[Success] Configure finished")

if __name__ == "__main__":
configure_router()
print("exit\n[Success] Configure finished")