Windows Server环境下Streamlit应用后台持久化运行的可靠方案咨询
Windows Server环境下Streamlit应用后台持久化运行的可靠方案咨询
作为常年在生产环境折腾Windows服务部署的老鸟,我来给你梳理几个靠谱的方案,完全适配你“退出RDP/终端后仍持续运行”的需求,都是我踩过坑后验证过的稳定方案。
一、最推荐的生产级方案:NSSM(Non-Sucking Service Manager)
你听说的NSSM确实是Windows下替代nohup最实用的工具之一,我在多个生产项目里用它跑Python/Streamlit应用,稳定性拉满,而且配置起来一点不复杂,给你一步一步来:
- 准备NSSM工具
- 下载对应服务器位数(32/64位)的NSSM压缩包,解压后把
nssm.exe放到C:\Windows\System32目录下,这样任意终端都能直接调用命令。
- 下载对应服务器位数(32/64位)的NSSM压缩包,解压后把
- 编写Streamlit启动脚本
- 先写一个批处理文件(比如命名为
start_streamlit.bat),内容要包含虚拟环境激活和启动命令,避免系统Python版本冲突:@echo off cd /d "C:\你的Streamlit项目根目录路径" call "C:\你的Python虚拟环境路径\Scripts\activate.bat" streamlit run app.py --server.port 8501 - 先在终端手动运行这个批处理,确认能正常启动应用,避免后续踩坑。
- 先写一个批处理文件(比如命名为
- 用NSSM注册系统服务
- 打开管理员权限的命令提示符(CMD),运行:
nssm install StreamlitAppService - 弹出图形配置窗口后,按以下标签配置:
- Application标签:
- Path:选择你刚才写的
start_streamlit.bat完整路径 - Working Directory:填写你的Streamlit项目根目录
- Path:选择你刚才写的
- Log On标签:建议选「本地系统账户」,勾选“允许服务与桌面交互”(方便后续看日志,生产环境也可以不勾),或者用有管理员权限的本地账户,避免权限不足导致启动失败。
- Recovery标签:把第一次/第二次/后续失败的动作都设为「Restart the Service」,这样应用崩溃后会自动重启,保障可用性。
- Application标签:
- 打开管理员权限的命令提示符(CMD),运行:
- 启动并验证服务
- 运行
nssm start StreamlitAppService启动服务 - 打开服务管理器(运行
services.msc),找到你创建的StreamlitAppService,确认状态为「正在运行」 - 退出RDP会话,用另一台机器访问
http://你的服务器IP:8501,验证应用正常运行。
- 运行
二、无额外工具方案:Windows任务计划程序
如果你不想装第三方工具,Windows自带的任务计划程序也能实现,适合轻量场景:
- 准备启动脚本
- 和上面一样,先写好能正常启动应用的
start_streamlit.bat脚本。
- 和上面一样,先写好能正常启动应用的
- 创建持久化任务
- 打开「任务计划程序」,点击「创建任务」:
- 常规标签:
- 任务名称:比如
StreamlitAutoStart - 必须勾选「不管用户是否登录都要运行」,这是实现后台持久化的核心!
- 勾选「使用最高权限运行」,避免权限问题。
- 任务名称:比如
- 触发器标签:
- 点击「新建」,选择「启动时」(服务器开机自动启动),也可以再加一个「工作站解锁时」的触发器,双重保障。
- 操作标签:
- 点击「新建」,操作选「启动程序」,程序或脚本选择你的
start_streamlit.bat,起始于填写项目根目录。
- 点击「新建」,操作选「启动程序」,程序或脚本选择你的
- 设置标签:
- 勾选「如果任务失败,每隔5分钟重试3次」
- 勾选「允许任务按需运行」
- 常规标签:
- 打开「任务计划程序」,点击「创建任务」:
- 验证效果
- 手动运行任务,确认应用启动后,退出RDP会话,远程访问验证可用性。
三、进阶定制方案:自写Windows服务(Python实现)
如果需要更精细的控制(比如自定义日志、启动前依赖检查),可以用Python的pywin32模块自己写服务,适合有开发能力的场景:
- 安装依赖
- 运行
pip install pywin32
- 运行
- 编写服务代码
- 示例核心代码如下,你可以根据自己的需求调整:
import win32serviceutil import win32service import win32event import subprocess import sys class StreamlitService(win32serviceutil.ServiceFramework): _svc_name_ = "StreamlitAppService" _svc_display_name_ = "Streamlit应用服务" def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) self.process = None def SvcStop(self): self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) if self.process: self.process.terminate() win32event.SetEvent(self.hWaitStop) def SvcDoRun(self): # 启动Streamlit应用 self.process = subprocess.Popen( [r"C:\你的虚拟环境路径\Scripts\python.exe", "-m", "streamlit", "run", "app.py", "--server.port", "8501"], cwd=r"C:\你的项目根目录路径" ) win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE) if __name__ == '__main__': win32serviceutil.HandleCommandLine(StreamlitService)
- 示例核心代码如下,你可以根据自己的需求调整:
- 注册并启动服务
- 用管理员权限运行终端,执行:
python your_service.py install net start StreamlitAppService - 后续可以在
services.msc里直接管理这个服务的启停。
- 用管理员权限运行终端,执行:
生产环境最佳实践
- 日志配置:一定要给应用配置日志输出,比如修改批处理脚本,把输出重定向到日志文件:
这样应用崩溃或异常时,能通过日志快速排查问题。streamlit run app.py --server.port 8501 >> C:\streamlit_logs\app.log 2>&1 - 权限设置:不管用哪种方案,都要用有足够权限的账户运行,避免因为权限不足无法读取依赖、写入日志等问题。
- 自动重启机制:用NSSM的Recovery配置或任务计划的重试规则,实现应用崩溃后自动重启,保障服务可用性。
- 防火墙配置:确保Streamlit使用的端口(默认8501)在Windows防火墙中已开放,避免外部无法访问。
最后说句实在的
生产环境里我最常用的还是NSSM,原因很简单:配置可视化、不用写代码、稳定性高,出问题了在服务管理器里就能快速启停、看状态。任务计划程序适合临时场景或者不想装工具的情况,自写服务适合需要深度定制的场景。按上面的步骤来,肯定能解决你退出RDP后应用停止的问题!




