Windows 启动时自动运行多个 Python 脚本
这篇记录几种常用启动方式。先按脚本是否需要登录前运行、是否需要可见窗口来选择入口;同一个后端脚本只保留一种自动启动方式,避免服务、任务计划和 Startup 同时拉起重复进程。
- A. 登录前就在后台运行 → 对长期守护型脚本可使用 Windows Service;这里用第三方 NSSM 做包装
- B. 用户登录后运行并显示窗口 → 使用任务计划程序 +
.bat - C. 后台运行、登录后只看状态 → 后端由 A 负责,前台只查看日志或监控界面
如果脚本不需要真正的服务生命周期,也可以直接用任务计划程序的“系统启动时”触发器,不必为了开机运行就一定引入 NSSM。
下文使用一组示例路径,按实际安装位置和脚本名称替换:
Python (conda env) : D:\ProgramData\anaconda3\envs\csyh\python.exe
脚本目录 : D:\opcua\csyh
脚本文件 : OPCUA_1R_A.py OPCUA_1R.py OPCUA_2R_A.py OPCUA_2R.py OPCUA_KP_A.py OPCUA_KP.py
0. 先决准备(必做)
确认 Python 路径正确。直接运行目标解释器检查版本最直观:
"D:\ProgramData\anaconda3\envs\csyh\python.exe" --version如果提示找不到文件,就改为本机实际的解释器绝对路径。
确认脚本能在命令行单独正常运行:
"D:\ProgramData\anaconda3\envs\csyh\python.exe" "D:\opcua\csyh\OPCUA_1R_A.py"在
D:\opcua\csyh下创建一个logs文件夹:用于写入日志(服务模式强烈建议)。mkdir D:\opcua\csyh\logs按运行方式收集输出。前台运行时保留控制台输出;服务运行时可在 nssm 的 I/O 页配置标准输出和标准错误文件,配合 Python 的 -u 参数减少缓冲。不要统一把 sys.stdout 改到文件后,又期待前台窗口继续显示 print 输出。
业务日志可以单独使用 logging 同时写文件和控制台。以下是初始化片段,后续使用 logging.info(…) 等记录日志:
import logging from logging.handlers import RotatingFileHandler from pathlib import Path logdir = Path(r"D:\opcua\csyh\logs") logdir.mkdir(parents=True, exist_ok=True) handler = RotatingFileHandler( logdir / (Path(__file__).name + ".log"), maxBytes=5_000_000, backupCount=3, encoding="utf-8", ) logging.basicConfig( level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", handlers=[handler, logging.StreamHandler()], ) logging.info("SCRIPT STARTED")该片段不会自动接管已有的 print;nssm 的输出文件与应用日志应使用不同文件名,避免同时写同一个文件。
A. 开机立即运行(登录前)——使用 Windows 服务(nssm)
优点:电脑上电 / 系统启动后就运行;不依赖用户登录;适合守护进程。
缺点:系统服务不能显示 GUI / 控制台窗口到用户桌面(安全限制)。
A.1 下载并安装 nssm(Non-Sucking Service Manager)
- 将适合架构的 nssm.exe 放在自己的工具目录,例如 D:\tools\nssm,并将该目录加入所用终端的 PATH,或在命令中使用完整路径。
- 确认在管理员 cmd 可以运行
nssm。
A.2 注册服务(为每个脚本建服务)
以 管理员 身份打开命令提示符(右键“以管理员身份运行”),然后对每个脚本运行:
示例(为 OPCUA_1R_A.py 注册):
nssm install OPCUA_1R_A
会弹出 GUI 输入框,填写:
- Path:
D:\ProgramData\anaconda3\envs\csyh\python.exe - Startup directory:
D:\opcua\csyh - Arguments:
-u D:\opcua\csyh\OPCUA_1R_A.py
(按 Install service 保存)
对其他脚本重复(用不同服务名,如 OPCUA_1R 等)。
A.3 设置自动启动(开机自动)
在管理员 cmd 中运行:
sc config OPCUA_1R_A start= auto
sc config OPCUA_1R start= auto
sc config OPCUA_2R_A start= auto
sc config OPCUA_2R start= auto
sc config OPCUA_KP_A start= auto
sc config OPCUA_KP start= auto
A.4 启动 / 停止 / 查看服务状态
启动某服务:
net start OPCUA_1R_A
停止:
net stop OPCUA_1R_A
查看服务状态:
sc query OPCUA_1R_A
A.5 日志与调试
- 因为服务没有窗口,检查
D:\opcua\csyh\logs\OPCUA_1R_A.py.log(参考上面 Python 日志写法)。 - 若想捕获更多输出,在 nssm 的
I/O页可以配置 Stdout/Err 重定向文件。
B. 用户登录后自动弹出窗口(可见)——任务计划程序 + .bat / VBS
目标:用户一登录后立刻看到控制台窗口或 GUI(比如你想观察输出)。
关键点:需要交互窗口时,使用目标用户的交互登录会话,选择“仅当用户登录时运行”。“以最高权限运行”控制权限级别,不会因勾选它就自动转到 Session 0;是否提权按脚本实际需要决定。
B.1 在脚本目录下创建 run_all.bat
路径:D:\opcua\csyh\run_all.bat,内容(详尽版:含延时、工作目录、窗口标题):
@echo off
title OPCUA 启动脚本总控
REM 延时等待桌面完全加载(必要时调整秒数)
timeout /t 10 >nul
REM 切换到脚本目录
cd /d "D:\opcua\csyh"
REM 逐个启动并让窗口最大化显示(每个窗口标题有区分)
start "OPCUA_1R_A" /max cmd /k "D:\ProgramData\anaconda3\envs\csyh\python.exe D:\opcua\csyh\OPCUA_1R_A.py"
start "OPCUA_1R" /max cmd /k "D:\ProgramData\anaconda3\envs\csyh\python.exe D:\opcua\csyh\OPCUA_1R.py"
start "OPCUA_2R_A" /max cmd /k "D:\ProgramData\anaconda3\envs\csyh\python.exe D:\opcua\csyh\OPCUA_2R_A.py"
start "OPCUA_2R" /max cmd /k "D:\ProgramData\anaconda3\envs\csyh\python.exe D:\opcua\csyh\OPCUA_2R.py"
start "OPCUA_KP_A" /max cmd /k "D:\ProgramData\anaconda3\envs\csyh\python.exe D:\opcua\csyh\OPCUA_KP_A.py"
start "OPCUA_KP" /max cmd /k "D:\ProgramData\anaconda3\envs\csyh\python.exe D:\opcua\csyh\OPCUA_KP.py"
REM 可选:暂停以防窗口马上关闭(仅当脚本本身结束时需要)
REM pause
exit
说明:
start "title" cmd /k "python ...":用 cmd 打开并保持窗口(不立即关闭)。timeout /t 10:建议延时 10 秒,可根据机器速度调整。
B.2 (可选)激活已经打开的窗口
创建 D:\opcua\csyh\bring_front.vbs,仅用于尝试激活同一交互会话中已经存在的窗口。先由 B.1 创建窗口,再调用它,不在这里重复启动 run_all.bat:
Set WshShell = CreateObject("WScript.Shell")
' 激活各个窗口(按窗口标题)
On Error Resume Next
WshShell.AppActivate "OPCUA_1R_A"
WScript.Sleep 500
WshShell.AppActivate "OPCUA_1R"
WScript.Sleep 500
WshShell.AppActivate "OPCUA_2R_A"
' 根据需要继续 AppActivate
AppActivate 是激活窗口,不是始终置顶。目标窗口必须已经创建,且标题匹配;它不能修复会话隔离,也不保证绕过系统的焦点限制。
B.3 在“任务计划程序”中创建任务(非常详细步骤)
- 打开:
Win + R→ 输入taskschd.msc→ 回车。 - 右侧 点击:创建任务…(不是“创建基本任务”)。
- 常规(General)选项卡:
- 名称:
OPCUA Login Launch - 描述:
登录后启动 OPCUA 脚本(任选) - 安全选项:选择你的用户账户(默认你的当前用户)。
- 选择:
仅当用户登录时运行(非常关键,保证窗口可见)。 - 权限级别:是否勾选“以最高权限运行”取决于实际需要,不能把它与会话是否交互混为一谈
- 配置为:Windows 10/11。
- 名称:
- 触发器(Triggers) → 新建(New…):
- 开始任务:
At log on(登录时) - 用户:
Any user或指定用户 - 高级设置:延迟任务执行:10 秒(建议)
- 点击 确定。
- 开始任务:
- 操作(Actions) → 新建(New…):
- 操作:
Start a program - 程序或脚本(Program/script):
cmd.exe - 添加参数(Add arguments):
(使用 /c 会运行并关闭 cmd;如果你想保留 master 窗口也可以直接填写 bat 路径,但用 cmd /c 更可靠用于显示)/c "D:\opcua\csyh\run_all.bat" - 起始于(Start in):
D:\opcua\csyh - 确定。
- 操作:
- 条件(Conditions):取消不必要限制,如“仅在使用交流电时”等。
- 设置(Settings):勾选“如果任务失败,重试”等按需设置。
- 保存。选择“仅当用户登录时运行”时通常不需要额外保存账户密码;如果改成“无论用户是否登录都要运行”,才会涉及保存对应账户凭据等额外配置。
- 测试:右键任务 → 运行,应该立即在桌面看到多个窗口弹出。
B.4 验证
- 退出当前账户并重新登录或重启并登录,等待大约 10 秒,观察窗口是否自动弹出。
- 若没有弹出,检查任务历史(在任务上右键 -> 查看历史)和
run_all.bat是否有错误输出。
C. 混合方案:后端运行,前台只监控
同一个后端脚本只由一个入口负责启动。采用服务方案时,登录任务不再运行启动这些后端的 run_all.bat,而是打开日志查看器或单独的监控界面。
例如,日志文件已由服务或应用创建后,在前台 PowerShell 中查看:
Get-Content -LiteralPath "D:\opcua\csyh\logs\OPCUA_1R_A.py.log" -Tail 50 -Wait
日志路径按实际配置填写;Ctrl+C 仅停止查看,不会停止后台服务。独立 GUI 可以通过后端提供的状态接口显示数据,不能为了“显示窗口”再启动一份相同业务逻辑。
原文的“绑定端口后立刻关闭 socket”只能检查当时的端口状态,不能作为单实例锁;两个进程都可能检查通过。端口被其他程序占用也不代表同一个脚本已启动。
需要单实例保护时,在程序中使用明确命名、原子获取并在整个运行期持有的互斥量或文件锁;失败时区分“实例已存在”与权限等其他错误。检查 PID 文件存在本身也不够,还涉及陈旧文件和竞争条件。计划任务中的“不启动新实例”只约束该任务,不能同时约束另外的服务入口。
D. 备用方法(注册表、Startup folder)简要说明
- Startup folder(
shell:startup): 把.bat或快捷方式放进去,用户登录后会运行(等同于 B 的 simpler 版本)。 - 注册表:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run可添加启动项(专业但不推荐用于复杂脚本)。
这些方法都需要用户登录才能显示前台。
E. 常见问题与排错
- 脚本运行但看不到任何输出
- 检查是否为服务(服务不会显示窗口)。
- 检查日志文件
D:\opcua\csyh\logs\*.log。
- 计划任务运行但窗口不显示
- 确保任务“仅当用户登录时运行”。
- 检查任务的登录类型和运行账户;AppActivate 不能把非交互会话的窗口带到当前桌面,也不能替代权限配置。
- 确保“操作”使用
cmd.exe /c "path\to\run_all.bat"并设置正确的 “起始于” 路径。
- “操作目录无效”错误
- 在 .bat 中使用
cd /d "D:\opcua\csyh"或 在任务的 “起始于” 填写目录。
- 在 .bat 中使用
- 脚本重复启动
- 检查是否有服务、登录任务和 Startup 项同时启动同一后端。先保留一个启动入口;程序级保护需使用运行期持有的原子锁。
- 权限 / 环境变量问题(conda 环境)
- 如果脚本依赖 conda 环境包,建议使用环境中
python.exe的绝对路径,或在 .bat 中先激活环境(复杂),例如:call "D:\ProgramData\anaconda3\Scripts\activate.bat" csyh python D:\opcua\csyh\OPCUA_1R_A.py - 注意:在服务下激活 conda 有时会失败,直接使用 env 的
python.exe更稳。
- 如果脚本依赖 conda 环境包,建议使用环境中
- 启动顺序 / 依赖(网络/盘未挂载)
- 如果脚本依赖网络驱动器或云盘,同步尚未完成可能失败。为计划任务设置延迟(30s 或更长),或在脚本中重试逻辑。
F. 文件清单
run_all.bat(前文给出)bring_front.vbs(可选,用于激活窗口)startup_opcua_service_setup.cmd(管理员运行,一次性注册服务的模板脚本)——示例内容:
@echo off
REM 请以管理员身份运行,先确认 nssm 在 PATH 中或改用完整路径
nssm install OPCUA_1R_A "D:\ProgramData\anaconda3\envs\csyh\python.exe" -u "D:\opcua\csyh\OPCUA_1R_A.py"
nssm install OPCUA_1R "D:\ProgramData\anaconda3\envs\csyh\python.exe" -u "D:\opcua\csyh\OPCUA_1R.py"
nssm install OPCUA_2R_A "D:\ProgramData\anaconda3\envs\csyh\python.exe" -u "D:\opcua\csyh\OPCUA_2R_A.py"
nssm install OPCUA_2R "D:\ProgramData\anaconda3\envs\csyh\python.exe" -u "D:\opcua\csyh\OPCUA_2R.py"
nssm install OPCUA_KP_A "D:\ProgramData\anaconda3\envs\csyh\python.exe" -u "D:\opcua\csyh\OPCUA_KP_A.py"
nssm install OPCUA_KP "D:\ProgramData\anaconda3\envs\csyh\python.exe" -u "D:\opcua\csyh\OPCUA_KP.py"
REM 显式设置各服务的工作目录,不能依赖安装命令运行时的当前目录
for %%S in (OPCUA_1R_A OPCUA_1R OPCUA_2R_A OPCUA_2R OPCUA_KP_A OPCUA_KP) do nssm set %%S AppDirectory "D:\opcua\csyh"
sc config OPCUA_1R_A start= auto
sc config OPCUA_1R start= auto
sc config OPCUA_2R_A start= auto
sc config OPCUA_2R start= auto
sc config OPCUA_KP_A start= auto
sc config OPCUA_KP start= auto
echo Services created. You can start them via: net start OPCUA_1R_A
pause
NSSM 支持
nssm install <name> <program> [args]的命令行安装方式;如果参数较复杂、包含较多引号,也可以改用nssm install <name>打开 GUI 填写。服务安装后不要随意移动正在使用的nssm.exe。
G. 推荐顺序(快速部署建议)
- 在本地命令行测试每个脚本能否正常运行并写日志。
- 若需要“开机就运行(登录前)”,先用 nssm 注册服务(A)。测试并查看日志。
- 若选择前台方案,使用 B 启动后端;若后端已由 A 负责,登录任务仅打开日志或独立监控界面,不重复运行 run_all.bat。
- 最后优化:延时、错误重试、日志轮转、避免重复启动。
评论将在接近此处时加载,也可点击立即加载。