Hide Windows scheduler bot execution
This commit is contained in:
@@ -45,6 +45,8 @@ AI에게 맡기지는 않습니다. AI는 장 전/장중/장후 시장을 분석
|
||||
- DB: SQLite (`data/stockbot.db`)
|
||||
- 알림: Discord Webhook
|
||||
- AI/ML: 시장 분석과 관찰용 점수 기록까지만 사용
|
||||
- 스케줄러 작업은 숨김 실행으로 등록하고, 장중 봇 본체는 Windows에서
|
||||
`pythonw.exe`를 우선 사용해 콘솔 창 없이 백그라운드로 실행합니다.
|
||||
|
||||
운영 모드는 아래처럼 나뉩니다.
|
||||
|
||||
@@ -79,6 +81,10 @@ powershell -ExecutionPolicy Bypass -File scripts\setup_scheduler.ps1
|
||||
powershell -ExecutionPolicy Bypass -File scripts\run_training_pipeline.ps1
|
||||
```
|
||||
|
||||
운영 중 봇을 직접 켜야 할 때는 `python app/main.py`보다
|
||||
`python scripts\start_bot.py`를 사용합니다. 이 경로는 기존 봇을 정리한 뒤
|
||||
콘솔 없는 백그라운드 프로세스로 새 봇을 띄우고 Discord 시작 알림을 보냅니다.
|
||||
|
||||
## 에이전트 운영 문서
|
||||
|
||||
- `AGENTS.md`: Codex가 읽는 운영 지침
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# Implementation Log
|
||||
|
||||
## 2026-07-02
|
||||
|
||||
- Hardened Windows background operation so users do not need to keep a visible
|
||||
console window open:
|
||||
- `scripts/start_bot.py` now starts `app/main.py` with `pythonw.exe` when it is
|
||||
available.
|
||||
- `scripts/_watchdog.py` uses the same `pythonw.exe` restart path.
|
||||
- `scripts/setup_scheduler.ps1` registers scheduled PowerShell tasks with
|
||||
`-WindowStyle Hidden` and marks task settings as hidden.
|
||||
- Updated `README.md` with the background-operation rule and the preferred
|
||||
manual start command.
|
||||
|
||||
## 2026-06-10
|
||||
|
||||
- Enabled wake-from-sleep behavior for Scheduler tasks:
|
||||
|
||||
@@ -17,6 +17,14 @@ from app.main import load_env
|
||||
load_env()
|
||||
|
||||
|
||||
def _bot_python() -> str:
|
||||
if os.name == "nt":
|
||||
pythonw = Path(sys.executable).with_name("pythonw.exe")
|
||||
if pythonw.exists():
|
||||
return str(pythonw)
|
||||
return sys.executable
|
||||
|
||||
|
||||
def _is_process_alive(pid: int) -> bool:
|
||||
result = subprocess.run(
|
||||
["tasklist", "/FI", f"PID eq {pid}", "/NH"],
|
||||
@@ -69,7 +77,7 @@ def _restart_bot() -> int:
|
||||
log_path = PROJECT / "logs" / "bot_stderr.log"
|
||||
with open(log_path, "a", encoding="utf-8") as log:
|
||||
proc = subprocess.Popen(
|
||||
[sys.executable, "-u", "app/main.py"],
|
||||
[_bot_python(), "-u", "app/main.py"],
|
||||
cwd=PROJECT,
|
||||
creationflags=creationflags,
|
||||
stdout=log,
|
||||
|
||||
@@ -25,7 +25,7 @@ function Register-StockTask {
|
||||
$Trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek $Weekdays -At $Time
|
||||
$Action = New-ScheduledTaskAction `
|
||||
-Execute "powershell.exe" `
|
||||
-Argument "-NonInteractive -ExecutionPolicy Bypass -File `"$Project\scripts\$Script`"" `
|
||||
-Argument "-NoProfile -WindowStyle Hidden -NonInteractive -ExecutionPolicy Bypass -File `"$Project\scripts\$Script`"" `
|
||||
-WorkingDirectory $Project
|
||||
$Settings = New-ScheduledTaskSettingsSet `
|
||||
-ExecutionTimeLimit (New-TimeSpan -Minutes $LimitMinutes) `
|
||||
@@ -34,6 +34,7 @@ function Register-StockTask {
|
||||
-DontStopIfGoingOnBatteries `
|
||||
-RunOnlyIfNetworkAvailable:$false
|
||||
$Settings.DisallowStartIfOnBatteries = $false
|
||||
$Settings.Hidden = $true
|
||||
|
||||
Register-ScheduledTask `
|
||||
-TaskName $Name `
|
||||
@@ -49,7 +50,7 @@ function Register-StockTask {
|
||||
|
||||
function Register-WatchdogTask {
|
||||
$ScriptPath = Join-Path $Project "scripts\run_watchdog.ps1"
|
||||
$Command = 'schtasks /Create /TN "\StockBot\StockBot_Watchdog" /TR "\"powershell.exe\" -NonInteractive -ExecutionPolicy Bypass -File \"' + $ScriptPath + '\"" /SC WEEKLY /D MON,TUE,WED,THU,FRI /ST 09:00 /RI 5 /DU 06:05 /F'
|
||||
$Command = 'schtasks /Create /TN "\StockBot\StockBot_Watchdog" /TR "\"powershell.exe\" -NoProfile -WindowStyle Hidden -NonInteractive -ExecutionPolicy Bypass -File \"' + $ScriptPath + '\"" /SC WEEKLY /D MON,TUE,WED,THU,FRI /ST 09:00 /RI 5 /DU 06:05 /F'
|
||||
cmd.exe /c $Command | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "StockBot_Watchdog registration failed"
|
||||
@@ -60,6 +61,7 @@ function Register-WatchdogTask {
|
||||
$Task.Settings.WakeToRun = $true
|
||||
$Task.Settings.DisallowStartIfOnBatteries = $false
|
||||
$Task.Settings.StopIfGoingOnBatteries = $false
|
||||
$Task.Settings.Hidden = $true
|
||||
Set-ScheduledTask -TaskName "StockBot_Watchdog" -TaskPath $TaskPath -Settings $Task.Settings | Out-Null
|
||||
|
||||
Write-Host "[OK] StockBot_Watchdog registered weekdays at 09:00-15:05 every 5 minutes" -ForegroundColor Green
|
||||
|
||||
@@ -11,6 +11,14 @@ PID_FILE = PROJECT / "logs" / "bot.pid"
|
||||
LOG_FILE = PROJECT / "logs" / "bot_stderr.log"
|
||||
|
||||
|
||||
def _bot_python() -> str:
|
||||
if os.name == "nt":
|
||||
pythonw = Path(sys.executable).with_name("pythonw.exe")
|
||||
if pythonw.exists():
|
||||
return str(pythonw)
|
||||
return sys.executable
|
||||
|
||||
|
||||
def _taskkill(pid: int) -> None:
|
||||
subprocess.run(["taskkill", "/PID", str(pid), "/F"], capture_output=True, text=True)
|
||||
|
||||
@@ -69,7 +77,7 @@ def _start_bot() -> int:
|
||||
|
||||
with open(LOG_FILE, "a", encoding="utf-8") as log:
|
||||
proc = subprocess.Popen(
|
||||
[sys.executable, "-u", "app/main.py"],
|
||||
[_bot_python(), "-u", "app/main.py"],
|
||||
cwd=PROJECT,
|
||||
creationflags=creationflags,
|
||||
stdout=log,
|
||||
|
||||
Reference in New Issue
Block a user