-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.ps1
More file actions
209 lines (187 loc) · 7.6 KB
/
install.ps1
File metadata and controls
209 lines (187 loc) · 7.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# ============================================================
# ctpbee Terminal — Dispatcher Frontend Installer
# Windows PowerShell script
# Usage: powershell -ExecutionPolicy Bypass -File install.ps1
# ============================================================
param(
[switch]$NoService,
[switch]$NoVenv,
[string]$PythonPath = ""
)
$ErrorActionPreference = "Stop"
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$ProjectName = "ctpbee-terminal"
$ServiceName = "ctpbee-dispatcher-bridge"
$VenvDir = Join-Path $ScriptDir ".venv"
# ── Colors ──
function Write-OK { Write-Host " [OK] " -NoNewline -ForegroundColor Green; Write-Host $args }
function Write-Warn { Write-Host " [WARN] " -NoNewline -ForegroundColor Yellow; Write-Host $args }
function Write-Err { Write-Host " [ERR] " -NoNewline -ForegroundColor Red; Write-Host $args }
function Write-Info { Write-Host " [..] " -NoNewline -ForegroundColor Cyan; Write-Host $args }
# ── Banner ──
Write-Host ""
Write-Host " ctpbee Terminal · Frontend Installer (Windows)" -ForegroundColor Green
Write-Host ""
# ── Find Python ──
function Find-Python {
Write-Info "Checking Python..."
$candidates = @()
if ($PythonPath) { $candidates += $PythonPath }
$candidates += "python3", "python"
foreach ($cmd in $candidates) {
try {
$v = & $cmd -c "import sys; print(sys.version)" 2>$null
if ($LASTEXITCODE -eq 0) {
Write-OK "Python: $cmd`n $(($v -split '\n')[0])"
return $cmd
}
} catch {}
}
Write-Err "Python 3.8+ not found. Install from https://python.org and retry."
Write-Err "Make sure 'Add Python to PATH' is checked during installation."
exit 1
}
$PythonExe = Find-Python
# Check version
$major = & $PythonExe -c "import sys; print(sys.version_info[0])"
$minor = & $PythonExe -c "import sys; print(sys.version_info[1])"
if ([int]$major -lt 3 -or ([int]$major -eq 3 -and [int]$minor -lt 8)) {
Write-Err "Python $major.$minor detected — need 3.8+"
exit 1
}
# ── Virtual environment ──
$UseVenv = $false
if (-not $NoVenv) {
if (Test-Path $VenvDir) {
Write-OK "venv already exists: $VenvDir"
$UseVenv = $true
} else {
$answer = Read-Host " Create Python virtual environment (.venv)? [Y/n]"
if ($answer -notmatch '^[Nn]') {
Write-Info "Creating virtual environment..."
& $PythonExe -m venv $VenvDir
Write-OK "venv created"
$UseVenv = $true
} else {
Write-Info "Skipped venv — using system Python"
}
}
}
if ($UseVenv) {
$PipExe = Join-Path $VenvDir "Scripts\pip.exe"
$PythonVenv = Join-Path $VenvDir "Scripts\python.exe"
Write-Info "Upgrading pip..."
& $PipExe install --quiet --upgrade pip 2>$null
} else {
$PipExe = "$PythonExe -m pip"
$PythonVenv = $PythonExe
}
# ── Install dependencies ──
Write-Info "Installing Python dependencies..."
$reqFile = Join-Path $ScriptDir "requirements.txt"
if (Test-Path $reqFile) {
& $PipExe install --quiet -r $reqFile
} else {
Write-Warn "requirements.txt not found, installing minimal deps"
& $PipExe install --quiet websockets redis
}
Write-OK "Dependencies installed"
# ── Default .env ──
$envFile = Join-Path $ScriptDir ".env"
if (-not (Test-Path $envFile)) {
Write-Info "Creating default .env..."
@"
# ctpbee Redis connection
CTPBEE_REDIS_HOST=127.0.0.1
CTPBEE_REDIS_PORT=6379
CTPBEE_REDIS_DB=0
# ctpbee Dispatcher channels
CTPBEE_ORDER_UP_KERNEL=ctpbee_order_up_kernel
CTPBEE_ORDER_DOWN_KERNEL=ctpbee_order_down_kernel
CTPBEE_TICK_KERNEL=ctpbee_tick_kernel
# WebSocket bridge server
CTPBEE_WS_HOST=0.0.0.0
CTPBEE_WS_PORT=8765
"@ | Out-File -FilePath $envFile -Encoding utf8
Write-OK ".env created"
} else {
Write-OK ".env already exists"
}
# ── Windows Service via NSSM or scheduled task ──
if (-not $NoService) {
Write-Host ""
$nssm = Get-Command nssm -ErrorAction SilentlyContinue
if ($nssm) {
# ── NSSM preferred ──
Write-Info "NSSM detected — can register as Windows service"
$answer = Read-Host " Register as Windows service? [y/N]"
if ($answer -match '^[Yy]') {
Write-Info "Installing service via NSSM..."
$serverScript = Join-Path $ScriptDir "server.py"
& nssm install $ServiceName $PythonVenv $serverScript
& nssm set $ServiceName AppDirectory $ScriptDir
& nssm set $ServiceName DisplayName "ctpbee Dispatcher Bridge"
& nssm set $ServiceName Description "WebSocket bridge for ctpbee Dispatcher mode"
& nssm set $ServiceName Start SERVICE_AUTO_START
Write-OK "Service installed: $ServiceName"
$answer2 = Read-Host " Start the service now? [y/N]"
if ($answer2 -match '^[Yy]') {
& nssm start $ServiceName
Write-OK "Service started"
} else {
Write-Info "Manual start: nssm start $ServiceName"
}
}
} else {
# ── Scheduled Task fallback ──
Write-Info "NSSM not found (install via: winget install nssm)"
Write-Info "Falling back to Scheduled Task option..."
$answer = Read-Host " Create startup scheduled task? [y/N]"
if ($answer -match '^[Yy]') {
$taskName = "ctpbee-dispatcher-bridge"
$serverScript = Join-Path $ScriptDir "server.py"
# Remove existing task if present
schtasks /delete /tn $taskName /f 2>$null
$action = New-ScheduledTaskAction -Execute $PythonVenv `
-Argument $serverScript `
-WorkingDirectory $ScriptDir
$trigger = New-ScheduledTaskTrigger -AtStartup
$settings = New-ScheduledTaskSettingsSet `
-AllowStartIfOnBatteries `
-DontStopIfGoingOnBatteries `
-RestartCount 3 `
-RestartInterval (New-TimeSpan -Minutes 1)
$principal = New-ScheduledTaskPrincipal -UserId "$env:USERDOMAIN\$env:USERNAME" `
-LogonType Interactive `
-RunLevel LeastPrivilege
Register-ScheduledTask -TaskName $taskName `
-Action $action `
-Trigger $trigger `
-Settings $settings `
-Principal $principal `
-Description "ctpbee Dispatcher Bridge Server" | Out-Null
Write-OK "Scheduled task '$taskName' created (runs at startup)"
$answer2 = Read-Host " Run the task now? [y/N]"
if ($answer2 -match '^[Yy]') {
Start-ScheduledTask -TaskName $taskName
Write-OK "Task started"
}
}
}
}
# ── Summary ──
$frontendPath = Join-Path $ScriptDir "ctpbee-frontend\index.html"
Write-Host ""
Write-Host " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor White
Write-Host " Installation Complete" -ForegroundColor Green
Write-Host ""
Write-Host " Frontend: http://localhost:8000/ctpbee-frontend/index.html" -ForegroundColor Cyan
Write-Host ""
Write-Host " Start (一键启动):" -ForegroundColor White
if ($UseVenv) {
Write-Host " $VenvDir\Scripts\activate" -ForegroundColor DarkGray
}
Write-Host " python $ScriptDir\start.py" -ForegroundColor DarkGray
Write-Host ""
Write-Host " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -ForegroundColor White
Write-Host ""