一、背景及定义工作中需要经常使用SSH远程连接设备每次都需要winRcmd输入一长串ssh user192.168.1.XX命令。想到可以做一个脚本工具像应用那样双击即用能快速连接到设备无需过多输入然后操作。定义SSHSecure Shell是一种网络协议和安全工具用于在不安全的网络上安全地进行远程登录和数据传输。它提供了加密的通信通道以保护敏感数据的机密性和完整性。SSH协议支持多种应用其中最常用的是SSH远程登录、SCPSecure Copy Protocol和SFTPSSH File Transfer Protocol。二、主流SSH工具情况市面上常见的ssh工具有Xshell、PUTTY、Finalshell、Mobaxterm、VSCode等这些工具都可用于连接各有自己的优势和特长。1.XshellXshell易用性好功能强大可填写邮箱申请家庭和教育版。2. PUTTYPUTTY优点是小而轻巧也很容易使用只有几兆大小虽然界面可能看起来一般。3.FinalshellFinalshell是国产的免费开源ssh工具必需要支援一波可以命令也可传输文件第一次上手需要一丢丢时间熟悉之后很好用。4. MobaxtermMobaxterm优点是可以用于设备的群体控制简单意思讲就是可以多开同时在多个终端输入相同内容Multipaste。5.VScodeVScode优点是拓展性强使用ssh连接需要安装插件同时提一嘴设备端也需要安装openssh-server。具体使用方法就不详细介绍了可以参考以下链接中的内容使用。VScode使用ssh远程连接Ubuntu【超简单且详细步骤】_vscode ssh-CSDN博客每种ssh工具都有自己的优势而我想要的工具是一方面能够快速连接远程设备同时不需要过多的输入前面网段在同一WIFI下一般不会变也就是只输入最后一个数字就能连接在断联后也能够快速重连。三、SSH连接工具基本情况1.基于python开发部署在本地windows终端使用pyinstaller封装双击即用补齐IP地址最后一段即可连接。2.支持修改用户名和固定网段3.断联后支持按照原来的ip地址快速重连或重新开始输入新的IP连接或只打开普通的cmd终端或关闭终端4.第一次连接新设备也无需输入yes四、使用步骤1.双击SSH连接工具v1.0.2.exe2.修改示例用户名和固定网段第一次使用需要修改示例用户名和固定网段后期使用不用每次修改示例用户名为abc改为自己想连接的设备用户名比如我想要远程的用户名为hhh按1输入新用户名可以看到连接命令里的abc已经变为了hhh按2修改固定网段例如我的固定网段为192.168.77.XX3.回车开始连接补齐IP地址最后一段例如我这里IP为102可以设置设备开机后自动通过企业微信群机器人播报自己的IP地址参考doubao等AI助手输入密码连接成功##.连接断开按1可以快速重连刚才的主机按2可以开始连接其他主机按3开启cmd终端按q关闭终端五、源代码exe可执行文件地址https://wwbav.lanzouu.com/i7q6B3s4lktg 密码:h9mzimport json import subprocess import sys import time from pathlib import Path from typing import Any, Dict, Optional # --------------------------------------------------------------------------- # 终端样式ANSI # --------------------------------------------------------------------------- class _T: RST \033[0m BOLD \033[1m CYAN \033[36m GREEN \033[32m YELLOW \033[33m RED \033[31m BLUE \033[34m WHITE \033[97m def _enable_ansi_if_windows() - None: if sys.platform ! win32: return try: import ctypes handle ctypes.windll.kernel32.GetStdHandle(-11) mode ctypes.c_uint32() if ctypes.windll.kernel32.GetConsoleMode(handle, ctypes.byref(mode)) 0: return new_mode mode.value | 0x0004 ctypes.windll.kernel32.SetConsoleMode(handle, new_mode) except Exception: pass def _clear_screen() - None: print(\033[3J\033[2J\033[H, end, flushTrue) def _hr(char: str ─, width: int 65) - None: print(f{_T.WHITE}{char * width}{_T.RST}) def _blank(n: int 1) - None: for _ in range(n): print() def _title(text: str) - None: _blank(1) print(f{_T.BOLD}{_T.CYAN}{═ * 65}{_T.RST}) print(f{_T.BOLD}{_T.CYAN} {text}{_T.RST}) print(f{_T.BOLD}{_T.CYAN}{═ * 65}{_T.RST}) _blank(1) def _kv(label: str, value: str, indent: str ) - None: print(f{indent}{_T.WHITE}{label}{_T.RST} {_T.GREEN}{value}{_T.RST}) def _menu_line(key: str, desc: str, indent: str ) - None: print(f{indent}{_T.YELLOW}{key}{_T.RST} {_T.WHITE}{desc}{_T.RST}) def _hint(text: str, indent: str ) - None: print(f{indent}{_T.WHITE}{text}{_T.RST}) def _ok(text: str) - None: print(f {_T.GREEN}{text}{_T.RST}) def _warn(text: str) - None: print(f {_T.YELLOW}{text}{_T.RST}) def _err(text: str) - None: print(f {_T.RED}{text}{_T.RST}) def _prompt(text: str) - str: print(f{_T.BOLD}{_T.BLUE}{text}{_T.RST}, end, flushTrue) return input() # --------------------------------------------------------------------------- # 配置EXE 兼容 # --------------------------------------------------------------------------- DEFAULT_CONFIG { remote_user: lab, ip_prefix: 192.168.77., } def get_config_path() - Path: if getattr(sys, frozen, False): base Path(sys.executable).parent else: base Path(__file__).parent return base / ssh_config.json def load_config() - Dict[str, str]: cfg DEFAULT_CONFIG.copy() path get_config_path() if path.exists(): try: data json.loads(path.read_text(encodingutf-8)) for k in cfg: if isinstance(data.get(k), str) and data[k].strip(): cfg[k] data[k].strip() except: pass return cfg def save_config(cfg: dict) - None: path get_config_path() payload {k: str(cfg.get(k, DEFAULT_CONFIG[k])).strip() for k in DEFAULT_CONFIG} path.write_text(json.dumps(payload, ensure_asciiFalse, indent2), encodingutf-8) # --------------------------------------------------------------------------- # 主逻辑 # --------------------------------------------------------------------------- class RobotSSHConnector: def __init__(self): self.config load_config() self.last_host None self.last_user None def _normalize_prefix(self): prefix self.config[ip_prefix] if prefix and not prefix.endswith(.): prefix prefix . self.config[ip_prefix] prefix return prefix def _preview_command(self) - str: user self.config[remote_user] prefix self._normalize_prefix() return fssh -o StrictHostKeyCheckingaccept-new {user}{prefix}主机号 def settings_menu(self) - None: while True: self._normalize_prefix() _title(SSH 连接工具 · 设置) _kv(远程用户名, self.config[remote_user]) _kv(IP 网段前缀, self.config[ip_prefix]) _blank(1) _kv(连接命令, self._preview_command()) _blank(1) _hr() _menu_line(回车, 开始连接) _menu_line(1, 修改用户名) _menu_line(2, 修改网段) _hr() _blank(1) choice _prompt(选择1/2/回车).strip() if choice : save_config(self.config) break if choice 1: u _prompt(新用户名).strip() if u: self.config[remote_user] u save_config(self.config) _ok(已保存) else: _warn(未修改) time.sleep(0.4) elif choice 2: p _prompt(网段前缀如 192.168.77.).strip() if p: if not p.endswith(.): p . self.config[ip_prefix] p save_config(self.config) _ok(已保存) else: _warn(未修改) time.sleep(0.4) else: _warn(无效选项) time.sleep(0.4) def connect(self, user: str, host: str): self.last_user user self.last_host host target f{user}{host} cmd [ssh, -o, StrictHostKeyCheckingaccept-new, target] print(_T.RST, end, flushTrue) _clear_screen() try: code subprocess.call(cmd) _blank(2) _hint(f✅ SSH 会话已断开退出码{code}) except FileNotFoundError: _err(❌ 未找到 ssh 命令请安装 OpenSSH 客户端) except Exception as e: _err(f❌ 连接异常{e}) def _new_cmd_tab_in_current_terminal(self): 在当前 Windows Terminal 新开 CMD 标签页普通 CMD 则 fallback 新窗口 if sys.platform ! win32: subprocess.Popen(bash, shellTrue) return # 优先用 wt.exe 在当前窗口新开 CMD 标签页 try: # wt.exe 是 Windows Terminal-p 后面是你的 CMD profile 名 subprocess.Popen( [wt.exe, new-tab, -p, 命令提示符], creationflagssubprocess.CREATE_NO_WINDOW ) _ok(✅ 已在当前终端打开新 CMD 标签页) return except Exception: pass # 没有 Windows Terminal 时fallback 到独立 CMD 窗口 try: subprocess.Popen(cmd.exe, creationflagssubprocess.CREATE_NEW_CONSOLE) _ok(✅ 已打开独立 CMD 窗口未检测到 Windows Terminal) except Exception as e: _err(f❌ 打开终端失败{e}) def show_reconnect_menu(self): while True: _blank(1) _hr(, 65) _hint(连接已断开请选择操作) _menu_line(1, 重新快速连接直接连刚才的主机) _menu_line(2, 开始新的连接回到设置页面) _menu_line(3, 打开新的CMD标签页) _menu_line(q, 关闭窗口退出) _hr(, 65) _blank(1) choice _prompt(请输入选择 [1/2/3/q]).strip().lower() if choice 1: if self.last_host and self.last_user: _ok(f✅ 正在重新连接{self.last_user}{self.last_host}) self.connect(self.last_user, self.last_host) else: _warn(❌ 无最近连接记录无法重连) time.sleep(1) elif choice 2: _ok(✅ 返回设置页面开始新连接) time.sleep(0.8) self.settings_menu() self.connect_in_this_terminal() break elif choice 3: self._new_cmd_tab_in_current_terminal() time.sleep(1) elif choice q: _ok( 正在退出...) break else: _warn(⚠️ 无效输入请输入 1/2/3/q) time.sleep(0.5) def connect_in_this_terminal(self) - None: prefix self._normalize_prefix() user self.config[remote_user] _title(连接主机) _kv(网段, prefix) _hint(输入主机号或完整IP) _hr() _blank(1) hint _prompt(主机号/IP).strip() if not hint: _warn(已取消) return host hint if . in hint else f{prefix}{hint} self.connect(user, host) self.show_reconnect_menu() def run() - None: _enable_ansi_if_windows() try: app RobotSSHConnector() app.settings_menu() app.connect_in_this_terminal() except KeyboardInterrupt: _warn( 已退出) time.sleep(0.8) except Exception as e: _err(f错误{e}) input(按回车关闭...) if __name__ __main__: run()