背景
之前写过一篇《如何在 windows 服务器上开机启动程序》,原理是用「计划任务」功能实现应用或服务的开机启动,或定时启动。
但是遇到了一个比较麻烦的问题,那就是一些需要 GUI 交互的脚本无法顺利执行,比如:运行一个 python 脚本,自动填写用户名、密码登录某个 APP。因为脚本要用到 pyautogui、pywinauto 这类操作 GUI(模拟鼠标键盘的操作)的库,所以在没有用远程桌面连接 win 服务器的时候,这些脚本是无法正常运行的。
最近又在研究这块,专门深度问了一下 ChatGPT,还真找到了一个解决方法——VNC Server。
操作步骤
VNC Server 有很多应用,我随便选了一个 TightVNC。先把使用方法写在前面,后面再介绍原理。
-
在 官网 下载 TightVNC 的安装程序;
-
在服务器安装 TightVNC,并
Run TightVNC Server,默认端口 5900,并设置访问密码; -
(重要)在服务器的安全组策略中,放开 5900 端口的入流量,否则无法连接到远程桌面,如下图:
-
在客户端,比如自己的 PC,也安装 TightVNC,运行
TightVNC Viewer,输入服务器的 IP,点击 connect,然后输入访问密码,即可登录远程桌面; -
(可选)为方便下次登录,直接保存成
.vnc文件,下次双击即可,如下图:
这样,通过 TightVNC 登录的远程桌面,再去「计划任务」里面启动需要操作 GUI 的脚本就没问题了。可以用下面这个简单的 vbs 脚本实验一下:
MsgBox "Hello, this is a message box!", 64, "Title"
注意:如果用 rdp 登录了远程桌面,那么要重新用 TightVNC 登录一遍,否则就失效了。
ChatGPT 讲原理
我直接把 ChatGPT 给我的答案贴上来吧,它回答的比我全面。
为什么计划任务不能顺利执行 pyautogui 的脚本
问:我在 win server 2012 的服务器上设置了一个计划任务。测试的时候没问题,但是第二天登陆上去一看,卡在了输入密码的一个步骤。pytyon 脚本里用了 pyautogui。请问是什么原因,要怎么解决 ChatGPT:
你提到在 Windows Server 2012 上运行的 Python 脚本使用了
pyautogui,并且任务卡在了输入密码的步骤。pyautogui主要用于模拟键盘和鼠标操作,但它在无 GUI 环境(如锁屏、远程桌面断开、无用户登录等情况下)运行时可能会出现问题。可能的原因
- 无用户会话:当你登出或者远程桌面断开连接时,Windows Server 2012 会进入锁屏状态或者没有活动的用户会话。
pyautogui依赖于图形用户界面(GUI)来进行鼠标和键盘操作,因此在没有图形界面或锁屏的情况下,pyautogui将无法正常工作。- 远程桌面断开:在通过远程桌面连接到服务器后,当你关闭远程桌面连接,系统可能会挂起 GUI 进程。此时,
pyautogui无法操作锁屏界面,因此任务会卡住。解决方案
1. 使用“控制台会话”启动任务
当你使用任务计划程序创建任务时,确保该任务在有活动的桌面会话(“控制台会话”)下运行。可以按照以下步骤进行设置:
勾选用户登录选项:在创建任务的“常规”选项卡中,确保选中了 “不论用户是否登录都要运行” ,但同时启用 “使用最高权限运行” 。
强制使用控制台会话:你可以尝试通过命令行连接到服务器上的本地控制台会话:
cmd Copy code mstsc /admin使用
/admin选项可以连接到控制台会话,而不是创建新的远程桌面会话。控制台会话保持用户界面活动,pyautogui可以在其中正常工作。2. 使用虚拟显示(虚拟桌面环境)
如果你需要在服务器上运行 GUI 自动化脚本,可以考虑使用虚拟显示工具,如 VNC Server 或 RDP Wrapper,以保持虚拟桌面环境持续可用。这样即使远程桌面断开连接,图形环境仍然存在,
pyautogui可以继续操作。
- VNC Server:安装并配置 VNC 服务器,保持持续的虚拟桌面连接,避免因为用户登出或远程桌面断开而导致的 GUI 丢失问题。
3. 避免使用
pyautogui或 GUI 自动化工具尽量避免在服务器环境中使用基于 GUI 的自动化工具。考虑是否能通过无 GUI 依赖的工具来实现任务。例如:
- 使用 Selenium WebDriver(如果涉及网页自动化):Selenium 支持无头浏览器(Headless Chrome、Headless Firefox),可以在后台运行浏览器,无需 GUI 环境。
- 通过 Python 内置模块或其他命令行工具来处理非图形界面任务:例如,可以使用
subprocess、requests等库来模拟输入、提交表单等任务,而不是模拟键盘和鼠标操作。4. 保持远程桌面连接(临时解决方案)
如果你只是想临时保持远程桌面连接持续运行以便测试,可以通过以下方式防止会话被锁定:
使用 保持远程桌面活动的小工具(如 NoSleep 或类似工具)防止会话断开。
修改组策略设置,避免在断开远程桌面连接时锁屏:
- 打开“组策略编辑器”(gpedit.msc)。
- 导航到
计算机配置 > 管理模板 > Windows 组件 > 远程桌面服务 > 远程桌面会话主机 > 会话时间限制。- 找到 “在指定时间后断开会话” ,并将其设置为“已禁用”。
总结
pyautogui在无 GUI 环境下无法正常工作,因此任务会在锁屏时卡住。可以通过确保使用控制台会话、使用虚拟桌面工具、避免 GUI 自动化等方式解决。- 如果任务是基于 GUI 的操作,最好在保持用户登录和有活动会话的情况下运行。
为什么 VNC Service 能够保留 GUI
问:VNC Server 为什么能维持服务器的 GUI 环境?我本地电脑关机也没关系吗?
ChatGPT:
VNC Server 之所以能够维持服务器的 GUI 环境,且在你本地电脑关机或断开连接的情况下依然能保持运行,是因为 VNC(Virtual Network Computing) 的工作机制与远程桌面协议(如 RDP)不同。以下是 VNC Server 能保持服务器 GUI 环境运行的原因,以及你本地设备关机是否会影响其工作的详细解释:
1. VNC Server 的工作原理
VNC 是基于客户端-服务器架构的远程控制协议。它允许你通过网络在本地计算机(客户端)上查看和操作远程计算机(服务器)上的 GUI 环境。
VNC Server 是运行在远程计算机上的一个服务,它在服务器上维护一个独立的 GUI 会话。这个 GUI 环境由 VNC Server 管理,而不是依赖客户端设备。
当你通过 VNC 客户端连接到服务器时,VNC Server 在后台继续运行并保持其管理的 GUI 环境,即使客户端断开或本地电脑关机,VNC Server 仍然维持远程计算机的图形界面。
2. 独立于本地计算机的 GUI 环境
- 与 Microsoft 的远程桌面协议(RDP)不同,VNC 并不会接管或终止服务器上的图形界面。如果你断开 RDP 会话,通常服务器的 GUI 会话也会断开或退出。
- 但是 VNC 不会这么做,VNC Server 保持服务器的 GUI 环境独立运行,即使没有任何客户端连接,它依然能够保持 GUI 的状态。除非你手动关闭 VNC Server 服务,服务器上的 GUI 环境会一直保持运行。
3. 本地电脑关机的影响
- 你的本地电脑关机、断网或者断开 VNC 客户端连接,不会影响服务器上的 GUI 会话。VNC Server 会在服务器端继续运行,GUI 会话也不会被中断。
- 当你重新打开本地电脑并再次使用 VNC 客户端连接时,你会重新恢复到之前的服务器 GUI 会话,而不是创建一个新的会话。
4. 为何 VNC 可以保持 GUI 环境
- VNC 的设计独立于远程客户端:VNC Server 本质上只是向客户端传送图形界面信息,客户端仅仅作为一个“查看和控制器”。客户端断开连接时,VNC Server 依然在服务器上运行,并保持图形会话的状态。
- 不会影响服务器的显示器状态:即使没有任何客户端连接,VNC Server 仍然会在后台管理服务器的显示输出和 GUI 操作。因此,它可以在无人连接时继续运行,直到你手动关闭 GUI 或 VNC 服务。
5. 与 RDP 的区别
- RDP(远程桌面协议) :当你通过 RDP 连接服务器时,通常你接管了服务器的图形界面,而本地显示器上可能没有 GUI。断开 RDP 会话通常会结束图形界面。
- VNC:与 RDP 不同,VNC 会保留服务器的图形界面,即使你断开连接,它也不会关闭服务器上的图形会话。
总结
- VNC Server 可以维持服务器的 GUI 环境,因为它独立运行于服务器上,不依赖于本地客户端的连接。
- 本地电脑关机、断网或者断开连接都不会影响 VNC Server 维护的服务器 GUI 会话。你可以随时通过客户端重新连接,并继续从上一次断开时的 GUI 状态工作。
结语
这下真的解决了一个大问题,之前因为无法在服务器上操作 GUI,好多设想的功能实现不了。包括但不限于:
- 微信自动发消息;
- 定时自动登录某些应用;
- 爬取应用里的一些数据;
- ……
这下好了,好多小工具都能搞起来了,希望对大家也有帮助。