尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Python自动化SecureCRT:pyautogui与pywinauto方案对比与实战

Python自动化SecureCRT:pyautogui与pywinauto方案对比与实战 1. 从手动到自动为什么我们需要用Python控制SecureCRT如果你和我一样日常工作中需要管理几十甚至上百台服务器那么SecureCRT这个终端仿真软件大概率是你的老朋友了。它的稳定性、多会话管理和丰富的协议支持SSH, Telnet, Serial等让它成为很多运维工程师和开发者的首选。但日复一日地登录、执行重复命令、检查日志这些机械性操作不仅枯燥还容易因为疲劳而出错。我最初的想法很简单能不能让电脑自己来干这些活这就是我们今天要聊的核心用Python来自动化控制SecureCRT。这不仅仅是“写个脚本”那么简单它背后是一套完整的自动化运维思路。想象一下凌晨三点需要批量更新所有测试环境的服务你不再需要强打精神守在电脑前一个脚本就能搞定所有登录、执行命令、检查结果、保存日志的操作。或者你需要定期从上百台设备上收集配置信息手动操作可能需要一整天而自动化脚本可能在喝杯咖啡的功夫就完成了。从技术路径上看控制SecureCRT主要有两种主流思路这也是很多朋友刚开始会困惑的地方。一种是“模拟用户操作”就像有一个看不见的手在帮你点击按钮、输入文字代表工具就是pyautogui。另一种是“直接驱动应用程序”通过程序接口来更精确地控制比如pywinauto。这两种方法各有优劣适用的场景也不同我会在后面的章节里详细拆解。但无论哪种方法最终目的都是将我们从重复劳动中解放出来把精力投入到更有价值的故障分析、架构设计等工作中去。2. 方案选型模拟点击 vs. 程序驱动哪个更适合你在决定用Python控制SecureCRT之前我们必须先搞清楚两种核心实现方式的原理和适用边界。这直接决定了脚本的稳定性、开发效率和最终能实现的自动化程度。2.1 方案一模拟用户操作以pyautogui为代表这个方案的思路非常直观你的Python脚本扮演一个“机器人用户”它通过控制鼠标光标移动、点击以及模拟键盘按键输入来操作SecureCRT的图形界面。pyautogui库就是这个领域的瑞士军刀。它的工作原理是直接与操作系统如Windows的图形子系统交互发送虚拟的鼠标和键盘事件。当你调用pyautogui.click(x, y)时它就相当于在屏幕坐标(x, y)处执行了一次鼠标点击。它的核心优势在于“通用性”极强几乎无所不能只要你能在屏幕上看到并能手动操作的功能pyautogui理论上都能模拟。这包括点击菜单栏、选择会话、在终端里输入命令、甚至处理一些弹窗。开发简单快速不需要理解SecureCRT的内部接口或数据结构。你需要做的就是记录下每个操作对应的屏幕坐标或图像特征。对应用程序无侵入你不需要SecureCRT提供任何额外的API支持甚至可以用它来控制任何其他没有开放接口的GUI软件。但它的劣势也同样明显这往往是导致脚本脆弱的根源严重依赖屏幕环境脚本通过坐标或图像识别来定位元素。如果你的SecureCRT窗口位置被移动了、大小改变了或者屏幕分辨率变了坐标就会失效脚本立刻“失明”。虽然可以通过截图匹配pyautogui.locateOnScreen来增强鲁棒性但这又带来了新的问题。图像匹配的性能与可靠性问题截图匹配需要处理图像速度较慢且对UI的微小变化如主题颜色变化、字体抗锯齿差异非常敏感容易匹配失败。无法处理“不可见”状态脚本只知道“看到了什么”不知道“程序内部是什么状态”。例如它无法直接读取终端里某一行文字的内容除非你将那部分屏幕截取下来做OCR光学字符识别这大大增加了复杂度。容易被意外中断pyautogui有一个著名的“故障安全”Fail-Safe机制。如果将鼠标快速移动到屏幕的左上角坐标(0,0)会触发pyautogui.FailSafeException并中止脚本。这是为了防止脚本失控但在调试时不小心碰到鼠标就可能意外终止任务。提示如果你决定使用pyautogui一个重要的实践是在脚本开始运行时先将鼠标移动到屏幕中央的一个“安全位置”并在整个脚本运行期间避免手动移动鼠标以防止意外触发Fail-Safe。2.2 方案二程序驱动与控制以pywinauto为代表这个方案的思路更“底层”一些它试图将SecureCRT识别为一个由窗口、控件按钮、输入框、文本框等组成的应用程序然后通过Windows的UI自动化框架如UIA,Win32 API来直接访问和操作这些控件。pywinauto库就是专门为此而生。它允许你通过控件的类型、名称、自动化ID等属性来定位它们而不是屏幕坐标。它的核心优势在于“精准”和“稳定”基于控件属性而非坐标你可以通过如window.child_window(title“连接”, control_type“Button”)这样的方式来定位“连接”按钮。只要SecureCRT的界面控件属性不变无论窗口放在哪里脚本都能找到它。可以获取控件状态和信息你不仅能点击按钮还能读取文本框里的文字内容。这对于从终端输出中捕获命令结果至关重要。执行效率更高直接调用控件方法比模拟鼠标移动和点击要快得多。更健壮不受屏幕分辨率、窗口位置变化的影响。然而它的挑战在于“复杂性”和“依赖”需要逆向分析界面你必须先弄清楚SecureCRT窗口的控件结构。这通常需要使用像Inspect.exeWindows SDK自带或SPY这样的工具来探查学习成本较高。对应用程序版本可能敏感如果SecureCRT版本更新导致界面控件层次或属性发生变化你的脚本可能需要调整。并非所有控件都易于访问特别是终端屏幕本身的内容显示区域它可能是一个复杂的自定义控件pywinauto未必能直接从中读取文本。有时针对终端内容的操作可能仍需结合pyautogui的截图OCR或更底层的方案。2.3 如何选择一个简单的决策框架根据我的经验你可以遵循以下原则进行选择如果你的自动化需求简单、一次性或者需要兼容多个不同软件优先考虑pyautogui。例如你只是需要每天早上一键打开SecureCRT并连接某个服务器。如果你的自动化需求复杂、需要长期稳定运行且主要针对SecureCRT优先尝试pywinauto。例如你需要自动登录多个会话执行一系列命令并根据命令输出结果做出判断如检查服务状态失败则重启。混合方案在实践中最高效稳定的往往是混合方案。用pywinauto来处理稳定的界面操作如点击连接按钮、选择会话列表而对于从终端屏幕读取命令输出这种pywinauto可能难以直接处理的任务可以谨慎地使用pyautogui截图结合OCR库如pytesseract来完成。或者更优的方案是直接利用SecureCRT的脚本功能VBScript/JScript来获取输出再用Python调用它。对于追求高可靠性的生产环境自动化我强烈建议你深入了解pywinauto并考虑将其作为主力。接下来我们就以pywinauto为核心详细拆解如何一步步构建一个能稳定控制SecureCRT的Python脚本。3. 实战准备环境搭建与SecureCRT界面侦察在开始编写自动化脚本之前我们需要把“战场”准备好。这包括安装必要的Python库以及最重要的一步——摸清SecureCRT这个“对手”的底细即它的窗口和控件结构。3.1 安装必要的Python库首先确保你有一个Python环境3.6及以上版本均可。然后我们主要安装pywinauto。打开你的命令行CMD或PowerShell执行pip install pywinautopywinauto会自动处理其依赖。如果你想后续尝试混合方案中的OCR部分也可以安装pytesseract和Pillow用于图像处理pip install pytesseract pillow请注意pytesseract只是一个Python封装你还需要在系统上安装Tesseract OCR引擎本身并从其官网下载对应的中文语言包。3.2 使用Inspect工具侦察SecureCRT界面这是整个pywinauto方案中最关键也最具技巧性的一步。我们需要知道SecureCRT的主窗口、按钮、输入框、会话列表、终端显示区域分别对应什么控件。Windows系统自带了一个强大的工具叫Inspect.exe通常位于C:\Program Files (x86)\Windows Kits\10\bin\版本号\x64目录下。你也可以通过Windows SDK安装它。侦察步骤打开SecureCRT并保持在一个典型状态比如停留在会话连接对话框或主界面。以管理员身份运行Inspect.exe。在Inspect的工具栏上你会看到一个类似鼠标指针的图标“将鼠标悬停在元素上以查看其属性”。点击它。将你的鼠标移动到SecureCRT的窗口上移动到你想侦察的特定元素上比如“连接”按钮。Inspect的界面会实时显示当前鼠标所指控件的详细信息。你需要重点关注以下几个属性在Inspect的“属性”标签页中Name(或LegacyIAccessible.Name)控件的名称这是最常用的定位标识。比如一个按钮上显示的文字“连接”往往就是它的Name。ControlType控件的类型如Button、Edit输入框、List列表、Document文档区域终端可能属于这种。AutomationId自动化ID这是一个开发者设置的、理论上唯一且稳定的标识符。如果存在且有意义这是比Name更可靠的定位依据因为Name可能随语言环境变化。ClassNameWin32窗口类名。有时当Name和AutomationId都不好用的时候可以用这个。RuntimeId运行时ID每次控件实例化时都不同不能用于持久化定位。一个实际的侦察案例假设我要侦察SecureCRT的“快速连接”对话框。在SecureCRT中点击“文件”-“快速连接”。用Inspect工具指向“主机名”输入框。我可能会看到Name: “主机名:”注意可能包含冒号ControlType: EditAutomationId: 1001假设值。指向“连接”按钮可能看到Name: “连接(C)”ControlType: ButtonAutomationId: 1。注意控件的Name属性有时并不是你肉眼看到的文本。例如一个分组框GroupBox的Name可能是其标题而它内部的输入框的Name可能是一个空字符串或一个静态文本标签的Name。你需要仔细辨别父子控件关系。Inspect工具中的“树”视图可以帮助你理解控件层次。记录下你的发现最好用表格整理界面元素推测用途定位方式 (示例)备注主窗口应用主界面app.window(title“SecureCRT”)标题可能包含会话名“快速连接”按钮打开连接对话框主窗口.child_window(title“快速连接” control_type“Button”)快速连接对话框输入连接参数app.window(title“快速连接”)对话框-主机名输入框输入IP/主机名对话框.child_window(auto_id“1001”, control_type“Edit”)优先用AutomationId对话框-连接按钮执行连接对话框.child_window(title“连接” control_type“Button”)终端面板显示命令输出主窗口.child_window(control_type“Document”)或 通过类名定位这是最难定位的部分可能需要反复尝试侦察工作可能需要一些耐心尤其是定位终端显示区域。有时它可能是一个自定义控件标准的Document类型无法访问其文本。这时可能需要尝试其他属性或者回退到pyautogui截图方案。4. 核心脚本编写从连接到执行命令掌握了界面结构后我们就可以开始编写Python脚本了。我们将按照一个完整的自动化流程来构建启动SecureCRT - 建立连接 - 在终端执行命令 - 获取输出。4.1 启动SecureCRT并连接到主窗口pywinauto提供了两种后端backendwin32默认基于pywin32和uia基于微软的UI Automation。对于较新的应用程序如基于WPF、WinForms或现代UI的uia通常支持更好。SecureCRT是一个相对传统的Win32程序但我们可以先尝试uia如果不行再换win32。from pywinauto import Application import time # 尝试使用uia后端启动或连接SecureCRT # 如果SecureCRT已经在运行使用connect。否则使用start。 try: # 连接到已有进程通过进程ID或窗口标题 app Application(backend“uia”).connect(title“SecureCRT”, timeout10) except Exception as e: print(f“未找到正在运行的SecureCRT尝试启动新实例: {e}”) # 请将路径替换为你自己的SecureCRT安装路径 securecrt_path r“C:\Program Files\VanDyke Software\SecureCRT\SecureCRT.exe” app Application(backend“uia”).start(securecrt_path) # 等待程序完全启动 time.sleep(3) # 获取主窗口对象 # 注意标题可能动态变化这里使用模糊匹配或获取顶层窗口 main_window app.window(title“SecureCRT”) # 或者 app.top_window() print(“已连接到SecureCRT主窗口。”)4.2 打开“快速连接”对话框并输入信息假设我们已经通过Inspect侦察到“快速连接”按钮的title是“快速连接”。# 点击菜单栏或工具栏上的“快速连接”按钮 # 首先需要找到这个按钮。它可能在“文件”菜单下也可能有独立的工具栏按钮。 # 方案A如果它是工具栏按钮且有明确的标题 try: quick_connect_btn main_window.child_window(title“快速连接” control_type“Button”) quick_connect_btn.click_input() except Exception as e: print(f“未找到标题为‘快速连接’的按钮尝试通过菜单打开: {e}”) # 方案B通过菜单打开 # 先点击“文件”菜单 main_window.child_window(title“文件(F)” control_type“MenuItem”).click_input() time.sleep(0.5) # 等待菜单下拉 # 再点击“快速连接”菜单项 # 注意菜单项可能在一个弹出菜单里需要一层层定位。这里简化处理使用type_keys模拟快捷键 main_window.type_keys(“%FQ”) # AltF 打开文件菜单然后按 Q (快速连接的快捷键需确认你的版本) # 或者直接发送全局快捷键 CtrlShiftN (如果这是你的快速连接快捷键) # main_window.type_keys(“^N”) # 等待“快速连接”对话框出现 connect_dlg app.window(title“快速连接”) connect_dlg.wait(‘visible’, timeout5) print(“快速连接对话框已打开。”)接下来在对话框中填写信息。假设主机名输入框的AutomationId是1001端口是1002用户名是1003。# 定位并输入主机名 hostname_edit connect_dlg.child_window(auto_id“1001”, control_type“Edit”) hostname_edit.set_text(“192.168.1.100”) # 替换为你的服务器IP time.sleep(0.2) # 定位并输入端口如果需要修改默认22 port_edit connect_dlg.child_window(auto_id“1002”, control_type“Edit”) port_edit.set_text(“22”) time.sleep(0.2) # 定位并输入用户名 username_edit connect_dlg.child_window(auto_id“1003”, control_type“Edit”) username_edit.set_text(“your_username”) # 替换为你的用户名 time.sleep(0.2) # 注意密码输入框通常是一个安全控件set_text可能无效。 # SecureCRT通常会在连接后或通过已保存的会话配置来处理密码。 # 这里假设我们使用已保存的会话或者使用SSH密钥认证跳过密码输入。 # 如果需要处理密码弹窗那将是另一个需要侦察和处理的独立窗口。4.3 执行连接并等待终端就绪点击对话框的“连接”按钮。connect_button connect_dlg.child_window(title“连接” control_type“Button”) connect_button.click_input() print(“正在连接...”) # 等待连接对话框关闭并假设终端窗口已就绪 connect_dlg.wait_not(‘visible’, timeout10) # 连接后主窗口的标题可能会变化包含主机名等信息。我们需要重新获取当前活动的终端窗口。 # 一个常见的方法是查找包含“终端”或特定主机名标题的子窗口。 time.sleep(2) # 额外等待终端稳定4.4 在终端中执行命令并获取输出难点与方案这是最具挑战性的一步。如前所述pywinauto可能无法直接读取终端区域一个复杂的自定义控件的文本。我们需要一些变通方案。方案A使用type_keys发送命令并依赖其他方式获取输出我们可以用type_keys向当前活动窗口发送键盘命令就像你在手动输入一样。# 获取当前焦点窗口应该是终端窗口 # 有时直接使用 main_window 发送按键即可因为焦点就在终端上。 terminal_window main_window # 或者通过更精确的方式定位如 main_window.child_window(title_re“.*192.168.1.100.*”) # 发送命令假设连接后提示符是 [userhost ~]$ # 先按回车确保在新的一行 terminal_window.type_keys(“{ENTER}”) time.sleep(0.5) # 输入命令 terminal_window.type_keys(“df -h{ENTER}”) # 执行 df -h 命令 print(“已发送命令: df -h”) time.sleep(1) # 等待命令执行和输出现在如何获取df -h的输出纯pywinauto很难。这时可以考虑混合方案方案B混合方案 -pyautogui截图 OCR在发送命令并等待后用pyautogui对终端输出区域进行截图然后用OCR识别文字。import pyautogui import pytesseract from PIL import ImageGrab # 1. 首先你需要知道终端输出区域在屏幕上的坐标。 # 这可以通过手动截图工具获取或者用pyautogui的定位功能但第一次仍需手动。 # 假设你已经通过侦察知道了终端区域的大致坐标 (left, top, right, bottom) terminal_region (100, 200, 900, 600) # 请替换为你的实际坐标 # 2. 发送命令后等待输出稳定 time.sleep(2) # 3. 截图 screenshot pyautogui.screenshot(regionterminal_region) # screenshot.save(‘terminal_output.png’) # 可以保存用于调试 # 4. OCR识别 # 配置Tesseract路径如果你安装了的话 # pytesseract.pytesseract.tesseract_cmd r‘C:\Program Files\Tesseract-OCR\tesseract.exe’ output_text pytesseract.image_to_string(screenshot, lang‘eng’) # 如果是英文 # 如果是中文输出需要下载中文语言包并指定 lang‘chi_sim’ 或 ‘chi_tra’ print(“识别到的输出”) print(output_text)方案C推荐利用SecureCRT内置脚本功能这是最稳定、最优雅的方案。SecureCRT本身支持VBScript和JScript脚本可以通过脚本执行命令并获取输出。我们可以用Python生成一个临时的脚本文件然后用pywinauto或subprocess触发SecureCRT运行这个脚本最后解析脚本输出的结果文件。编写一个VBScript模板它能连接会话、执行命令、将输出写入文件。‘ template.vbs $language “VBScript” $interface “1.0” Sub Main Dim hostname, username, password hostname “HOST” username “USER” ‘ 密码处理需谨慎建议使用会话配置或密钥 ‘ password “PASS” ‘ 连接到会话假设会话已存在或使用快速连接参数 ‘ 这里简化处理使用已保存的会话名 crt.Session.Connect(“/S ““MySavedSession”””) ‘ 等待连接完成 crt.Screen.WaitForString(“$ “ 10) ‘ 等待出现提示符超时10秒 ‘ 发送命令 crt.Screen.Send(“df -h” vbCr) ‘ 等待命令执行完成等待出现新的提示符 crt.Screen.WaitForString(“$ “ 5) ‘ 获取上一屏的输出从发送命令后到新提示符前 ‘ 更准确的做法是记录发送命令前的行号然后读取之间的行 result crt.Screen.ReadString(“$ “) ‘ 读取到提示符为止的内容包含命令本身和输出 ‘ 简单处理移除命令本身 result Replace(result, “df -h” vbCr, “”) ‘ 将结果写入文件 Set fso CreateObject(“Scripting.FileSystemObject”) Set file fso.CreateTextFile(“output.txt”, True) file.Write result file.Close End Sub用Python动态生成并执行脚本import subprocess import os import tempfile def run_securecrt_script(host, user, command): # 读取模板 with open(‘template.vbs’, ‘r’, encoding‘utf-8’) as f: template f.read() # 替换占位符 script_content template.replace(‘HOST’, host).replace(‘USER’, user).replace(‘df -h’, command) # 创建临时脚本文件 with tempfile.NamedTemporaryFile(mode‘w’, suffix‘.vbs’, deleteFalse, encoding‘utf-8’) as tmp: tmp.write(script_content) tmp_script_path tmp.name # 构建SecureCRT命令行执行脚本 # SecureCRT.exe /script path\to\script.vbs securecrt_path r“C:\Program Files\VanDyke Software\SecureCRT\SecureCRT.exe” cmd [securecrt_path, “/script”, tmp_script_path] try: # 执行等待完成 subprocess.run(cmd, checkTrue, timeout30) # 读取输出文件 with open(‘output.txt’, ‘r’, encoding‘utf-8’) as f: output f.read() return output except subprocess.TimeoutExpired: print(“脚本执行超时”) return None except Exception as e: print(f“执行失败: {e}”) return None finally: # 清理临时脚本文件 os.unlink(tmp_script_path) # 可选清理输出文件 if os.path.exists(‘output.txt’): os.remove(‘output.txt’) # 使用示例 result run_securecrt_script(“192.168.1.100”, “myuser”, “ls -la /tmp”) if result: print(“命令输出”, result)方案C虽然需要学习一点VBScript但它彻底摆脱了对UI的依赖稳定性和效率最高是生产环境的首选。pywinauto在这里的角色可以简化为在需要的时候启动SecureCRT或者管理多个会话窗口。5. 进阶技巧与避坑指南掌握了基础操作后我们来看看如何让脚本更健壮、更高效以及那些我踩过坑后才学到的经验。5.1 处理弹窗与意外情况自动化脚本最怕意外。比如连接失败时的错误弹窗、证书确认提示、或者“是否保存会话”的对话框。策略超时等待与条件判断不要一味地使用time.sleep固定等待而应该使用wait方法配合超时和条件判断。from pywinauto.timings import TimeoutError try: # 等待某个窗口出现最多等10秒 error_dialog app.window(title“连接错误”) error_dialog.wait(‘visible’, timeout10) print(“检测到错误弹窗”) # 处理错误比如点击“确定”按钮 error_dialog.child_window(title“确定” control_type“Button”).click_input() # 然后可以执行恢复逻辑比如重试或记录日志 except TimeoutError: print(“未出现错误弹窗继续流程。”)对于证书确认可以预先在SecureCRT的会话选项里设置为“接受并保存”避免脚本运行时弹出。5.2 提高控件定位的鲁棒性不要只依赖title因为它可能被本地化或改变。综合利用多种属性。# 不好的做法只依赖标题英文版和中文版不兼容 btn window.child_window(title“Connect”) # 好的做法结合多种属性 btn window.child_window(title“连接” control_type“Button”) # 中文环境 # 或者使用 automation_id如果稳定的话 btn window.child_window(auto_id“cmdConnect”, control_type“Button”) # 或者使用类名 btn window.child_window(class_name“Button”, found_index0) # 可能不稳定 # 最佳实践使用模糊匹配或后备方案 connect_buttons window.children(control_type“Button”) for btn in connect_buttons: if “连接” in btn.window_text() or “Connect” in btn.window_text(): target_btn btn break5.3 管理多个会话与窗口如果你需要自动化操作多个服务器管理多个SecureCRT标签页或窗口是关键。使用会话配置文件为每个服务器在SecureCRT中创建保存好的会话.ini文件或内置数据库。你的脚本只需打开SecureCRT然后通过命令行或脚本连接这些会话名。# 命令行连接已保存的会话 subprocess.run([securecrt_path, “/T”, “/SESSION MyServer1”]) subprocess.run([securecrt_path, “/T”, “/SESSION MyServer2”]) # /T 表示在新标签页打开用pywinauto切换标签页侦察标签栏的控件然后通过点击不同的标签来切换活动会话。多进程/多线程对于完全独立的操作可以考虑为每个会话启动一个独立的SecureCRT进程或Python线程但要注意资源竞争和复杂度。5.4 脚本的健壮性设计日志记录在每个关键步骤开始连接、发送命令、获取输出都记录日志便于出错时回溯。异常处理用try...except包裹可能失败的操作如控件找不到、连接超时并设计重试机制。超时控制为所有等待操作设置合理的超时时间避免脚本永远挂起。环境隔离确保脚本运行时屏幕不被其他操作干扰特别是使用pyautogui时。可以考虑在虚拟机或专用账户中运行。配置外置将服务器列表、命令、坐标等信息放在配置文件如JSON, YAML或数据库中使脚本逻辑与数据分离。5.5 一个我踩过的坑焦点丢失在使用type_keys发送命令时必须确保目标窗口是当前活动窗口且有焦点。如果在此期间用户点击了其他窗口命令就会发到别处。解决方法是在发送命令前先调用set_focus()确保窗口聚焦或者使用send_keystrokes方法它不依赖焦点但行为略有不同。terminal_window.set_focus() time.sleep(0.1) # 等待焦点切换 terminal_window.type_keys(“ls -la{ENTER}”)6. 完整实战案例批量服务器健康检查让我们综合运用以上知识实现一个实用的脚本自动登录到列表中的多台服务器执行一组健康检查命令如检查磁盘空间、内存使用率、关键进程状态并将结果收集到一个统一的报告中。设计思路采用**方案CSecureCRT脚本**作为核心执行引擎保证稳定获取命令输出。用Python作为主控脚本负责读取服务器列表、生成动态VBScript、顺序或并发执行、解析结果、生成报告。使用pywinauto仅作为辅助用于在必要时确保SecureCRT主程序已启动如果采用单进程多标签模式。核心代码结构import json import subprocess import tempfile import os from datetime import datetime import concurrent.futures # 用于并发执行 # 1. 定义健康检查命令 HEALTH_CHECKS { “disk”: “df -h | grep -E ‘^/dev/|Filesystem’“, “memory”: “free -h”, “process”: “ps aux | grep -E ‘nginx|mysql|java’ | grep -v grep”, } # 2. 读取服务器配置 with open(‘servers.json’, ‘r’) as f: servers json.load(f) # servers.json 格式: [{“name”: “Web-01”, “host”: “10.0.0.1”, “user”: “ops”, “session_name”: “Web01”}, ...] # 3. VBScript模板 (增强版) VBS_TEMPLATE “““ $language “VBScript” $interface “1.0” Sub Main crt.Session.Connect(“/S ““{session_name}”””) If crt.Session.Connected Then crt.Screen.Synchronous True crt.Screen.WaitForString(“$ “ 10) ‘ 执行命令并捕获输出 Dim allOutput allOutput “” ‘ 发送并捕获每个命令 {command_blocks} ‘ 写入结果文件 Set fso CreateObject(“Scripting.FileSystemObject”) Set file fso.CreateTextFile(“{output_file}”, True) file.Write allOutput file.Close crt.Session.Disconnect Else ‘ 连接失败写入错误信息 Set fso CreateObject(“Scripting.FileSystemObject”) Set file fso.CreateTextFile(“{output_file}”, True) file.Write “ERROR: Failed to connect to {session_name}” file.Close End If End Sub “““ # 4. 为单个服务器执行检查的函数 def check_single_server(server_info): host server_info[‘host’] session server_info.get(‘session_name’, host) output_file f“result_{session}_{datetime.now().strftime(‘%H%M%S’)}.txt” # 动态生成命令块 command_blocks [] for check_name, command in HEALTH_CHECKS.items(): block f“crt.Screen.Send(”“{command}”“ vbCr)\n” block f“ crt.Screen.WaitForString vbCrLf, 1\n” # 等待命令回显 block f“ crt.Screen.WaitForString ““$ ”“, 5\n” block f“ output crt.Screen.ReadString(““$ ”“)\n” block f“ allOutput allOutput ““--- {check_name.upper()} ---““ vbCrLf output vbCrLf” command_blocks.append(block) command_blocks_str “ “.join(command_blocks) # 填充模板 script_content VBS_TEMPLATE.format( session_namesession, command_blockscommand_blocks_str, output_fileoutput_file ) # 写入临时脚本并执行 with tempfile.NamedTemporaryFile(mode‘w’, suffix‘.vbs’, deleteFalse, encoding‘utf-8’) as f: f.write(script_content) script_path f.name securecrt_path r“C:\Program Files\VanDyke Software\SecureCRT\SecureCRT.exe” try: subprocess.run([securecrt_path, “/script”, script_path], checkTrue, timeout60, capture_outputTrue) # 读取结果 if os.path.exists(output_file): with open(output_file, ‘r’) as f: result f.read() os.remove(output_file) return {“server”: server_info[‘name’], “status”: “success”, “data”: result} else: return {“server”: server_info[‘name’], “status”: “error”, “data”: “No output file generated.”} except subprocess.TimeoutExpired: return {“server”: server_info[‘name’], “status”: “timeout”, “data”: “”} except Exception as e: return {“server”: server_info[‘name’], “status”: “exception”, “data”: str(e)} finally: os.unlink(script_path) # 5. 主执行逻辑 - 顺序执行 print(f“开始对 {len(servers)} 台服务器进行健康检查...”) results [] for server in servers: print(f“正在检查 {server[‘name’]}...”) result check_single_server(server) results.append(result) print(f“ 结果: {result[‘status’]}”) # 6. 生成报告 report_name f“health_report_{datetime.now().strftime(‘%Y%m%d_%H%M%S’)}.txt” with open(report_name, ‘w’) as f: f.write(“服务器健康检查报告\n”) f.write(“”*50 “\n”) for r in results: f.write(f“\n服务器: {r[‘server’]}\n”) f.write(f“状态: {r[‘status’]}\n”) f.write(f“详细信息:\n{r[‘data’]}\n”) f.write(“-”*50 “\n”) print(f“检查完成报告已生成: {report_name}”) # 可选并发执行版本适用于服务器数量多时 # with concurrent.futures.ThreadPoolExecutor(max_workers3) as executor: # 控制并发数 # future_to_server {executor.submit(check_single_server, s): s for s in servers} # for future in concurrent.futures.as_completed(future_to_server): # server future_to_server[future] # try: # result future.result() # results.append(result) # except Exception as exc: # results.append({“server”: server[‘name’], “status”: “future_error”, “data”: str(exc)})这个案例展示了如何将Python的灵活性与SecureCRT脚本的稳定性结合起来构建一个真正实用的运维自动化工具。你可以在此基础上扩展比如添加邮件报警、将结果存入数据库、或与监控系统集成。自动化之路总是从解决一个具体的痛点开始。也许你只是厌倦了每天重复登录几台服务器看日志那么从用pyautogui记录下你的操作开始。当你需要更稳定、更复杂的流程时再逐步引入pywinauto和SecureCRT脚本。关键是要动手去做在踩坑和解决问题的过程中你会对GUI自动化、进程间交互有更深刻的理解。最后记住没有一劳永逸的方案保持脚本的可维护性和可读性当SecureCRT版本更新时你才能快速调整侦察结果和定位逻辑。
返回列表