如何在 PowerShell 中并行运行两个命令并自动分屏
结论
在 Windows Terminal 中,只需调用一次 wt.exe:先创建第一个 pane,再用 split-pane 创建第二个 pane。分号必须传给 wt.exe,否则 PowerShell 会提前把它当作命令分隔符处理。
以下命令会新建一个 Windows Terminal 窗口,创建两个左右排列的 panes,并在其中分别运行两个程序:
wt -w new new-tab --title "program_2" pwsh -NoExit -Command "python 'C:\path\to\program_2\program_2.py'" `; split-pane -V --title "program_1" pwsh -NoExit -Command "& 'C:\path\to\program_1\program_1.exe'"
各参数的作用如下:
`;是用 PowerShell 转义后的分号,会作为参数传给wt.exe。split-pane -V创建左右排列的 panes。- 如需上下排列,可改用
split-pane -H。 -NoExit会在命令结束后保留 shell,不需要时可以删除。&是 PowerShell 的调用运算符,用于执行带完整路径的程序。- 如果使用 Windows PowerShell 5.1,请把
pwsh换成powershell.exe。
为什么原来的分屏命令没有生效
在 PowerShell 中,普通分号用于分隔两条语句:
command1; command2
所以下面的写法实际会执行两条命令:
wt.exe split-pane ... ; split-pane ...
PowerShell 先运行 wt.exe split-pane ...,随后在当前 shell 中查找名为 split-pane 的命令。由于 split-pane 是 wt.exe 的子命令,并不是独立程序,第二部分会报错。
Windows Terminal 也用分号连接多个子命令。要把分号传给它,需要在 PowerShell 中写成:
`;
完整结构是:
wt <第一个 pane 的配置> `; split-pane <第二个 pane 的配置>
在当前 Windows Terminal 窗口中分屏
如果要操作当前 Windows Terminal 窗口,可以使用 -w 0:
wt -w 0 new-tab --title "program_2" pwsh -NoExit -Command "python 'C:\path\to\program_2\program_2.py'" `; split-pane -V --title "program_1" pwsh -NoExit -Command "& 'C:\path\to\program_1\program_1.exe'"
-w 0 会把命令发送给当前 Windows Terminal 窗口。建议从 Windows Terminal 会话中运行这条命令。从其他终端宿主运行时,目标窗口的行为可能受 Windows Terminal 配置影响。
如果要拆分当前已有的 pane,无需先创建新 tab,可以只发送 split-pane 命令:
wt -w 0 split-pane -V pwsh -NoExit -Command "python 'C:\path\to\program_2\program_2.py'"
要同时启动两个新任务时,先创建 tab 再拆分通常更容易控制。
使用 --% 简化转义
PowerShell 在 Windows 上提供 stop-parsing token --%。它会停止解析后面的特殊字符,因此分号不再需要反引号:
wt --% -w new new-tab --title program_2 pwsh -NoExit -Command "python 'C:\path\to\program_2\program_2.py'" ; split-pane -V --title program_1 pwsh -NoExit -Command "& 'C:\path\to\program_1\program_1.exe'"
这种写法更短,但 --% 后面的 PowerShell 变量、表达式和大多数插值无法正常展开。路径固定时可以使用;需要拼接变量时,应继续使用 `;,或者在脚本中处理参数。
用脚本保存为一次操作
可以把命令保存到 run-dev.ps1:
$pythonProgram = 'C:\path\to\program_2\program_2.py'
$nativeProgram = 'C:\path\to\program_1\program_1.exe'
wt -w new `
new-tab --title 'program_2' pwsh -NoExit -Command "python '$pythonProgram'" `
`; split-pane -V --title 'program_1' pwsh -NoExit -Command "& '$nativeProgram'"
以后执行下面的命令即可:
.\run-dev.ps1
如果脚本和两个程序位于同一目录,可以使用 $PSScriptRoot,这样就不会依赖运行脚本时的当前目录:
$pythonProgram = Join-Path $PSScriptRoot 'program_2.py'
$nativeProgram = Join-Path $PSScriptRoot 'program_1.exe'
wt -w new `
new-tab --title 'program_2' pwsh -NoExit -Command "python '$pythonProgram'" `
`; split-pane -V --title 'program_1' pwsh -NoExit -Command "& '$nativeProgram'"
分别打开两个独立窗口
不需要 panes 时,可以启动两个独立的 PowerShell 进程:
Start-Process pwsh -ArgumentList '-NoExit', '-Command', "python 'C:\path\to\program_2\program_2.py'"
Start-Process pwsh -ArgumentList '-NoExit', '-Command', "& 'C:\path\to\program_1\program_1.exe'"
Start-Process 启动子进程后通常会立即返回,第二个程序不用等待第一个程序退出。两个程序会独立运行。它们最终显示为传统控制台窗口、Windows Terminal 窗口还是标签页,取决于系统的默认终端设置。
如果只要求两个程序并行运行,不需要分屏,可以启动它们并等待两者结束:
$p1 = Start-Process python `
-ArgumentList 'C:\path\to\program_2\program_2.py' `
-PassThru
$p2 = Start-Process 'C:\path\to\program_1\program_1.exe' `
-PassThru
Wait-Process -Id $p1.Id, $p2.Id
这种方式只管理进程的并行运行,不控制终端布局。
为什么 ForEach-Object -Parallel 的尝试会报错
下面代码中的两个字符串只是普通文本,PowerShell 不会把它们当作命令执行:
ForEach-Object -Parallel {
"python C:\path\to\program_2\program_2.py"
"C:\path\to\program_1\program_1.exe"
}
此外,ForEach-Object 需要从管道接收待处理对象。-Parallel 用于并行处理一组输入数据,不会创建 terminal pane。即使把代码改成可执行的并行脚本,也不会自动生成分屏界面。
在 PowerShell 7 中,可以这样并行启动任务:
1, 2 | ForEach-Object -Parallel {
if ($_ -eq 1) {
python 'C:\path\to\program_2\program_2.py'
}
else {
& 'C:\path\to\program_1\program_1.exe'
}
}
两个程序的输出仍可能汇集到同一个调用环境中。对于交互式控制台程序,使用 Windows Terminal panes 或独立进程通常更合适。
; 不一定代表所有程序都会串行
对于普通控制台程序:
program1; program2
PowerShell 通常会等 program1 退出后再运行 program2。
wt.exe 是终端启动器,可以把启动请求交给 Windows Terminal 实例后迅速返回。因此,连续调用两次 wt.exe 时,两个目标程序很可能同时运行。仅凭出现两个窗口,无法严格判断进程之间的关系。使用 Windows Terminal 的单次分屏命令或 Start-Process,执行方式会更明确。
跨平台工作流怎么选择
pane 和 tab 是终端程序提供的界面功能,各终端没有通用的 split-pane 命令。Windows Terminal 的 wt 命令也只适用于 Windows Terminal。
可以把工作流分成两层:
- 用脚本或任务运行器定义要启动的程序。
- 用当前平台的终端工具安排这些程序的显示方式。
Windows 可以使用 Windows Terminal 和 wt.exe,Linux、macOS 可以使用 tmux 等 terminal multiplexer。PowerShell 7 能在 Windows、Linux 和 macOS 上运行,可复用大部分启动逻辑,但终端分屏部分仍需按平台编写。
如果开发流程以项目任务为主,也可以通过编辑器的 task 配置启动多个 integrated terminal,让不同系统共用一份项目级配置。
例如,跨平台 PowerShell 脚本可以根据操作系统选择可执行文件:
$pythonProgram = Join-Path $PSScriptRoot 'program_2.py'
if ($IsWindows) {
$nativeProgram = Join-Path $PSScriptRoot 'program_1.exe'
}
else {
$nativeProgram = Join-Path $PSScriptRoot 'program_1'
}
选好可执行文件后,再调用对应平台的终端布局命令。这样只需维护少量平台差异,无需让 Windows Terminal、Linux 终端和 macOS 终端共用同一套 pane 控制语法。
备注:内容仅供参考。
