59 lines
2.1 KiB
Python
59 lines
2.1 KiB
Python
|
|
import subprocess, os, sys, asyncio
|
||
|
|
|
||
|
|
BASE = r'C:\Users\whdwo\OneDrive\바탕 화면\stockbot_v3'
|
||
|
|
pid_file = os.path.join(BASE, 'logs', 'bot.pid')
|
||
|
|
|
||
|
|
# 1-a) PID 파일로 종료
|
||
|
|
if os.path.exists(pid_file):
|
||
|
|
try:
|
||
|
|
pid = int(open(pid_file).read().strip())
|
||
|
|
result = subprocess.run(["taskkill", "/PID", str(pid), "/F"], capture_output=True, text=True)
|
||
|
|
print(f"PID 파일 종료: {pid} -> returncode={result.returncode}")
|
||
|
|
except Exception as e:
|
||
|
|
print(f"PID 파일 종료 실패: {e}")
|
||
|
|
os.remove(pid_file)
|
||
|
|
else:
|
||
|
|
print("PID 파일 없음")
|
||
|
|
|
||
|
|
# 1-b) 잔존 프로세스 스캔
|
||
|
|
r = subprocess.run(
|
||
|
|
["powershell", "-Command",
|
||
|
|
"Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -like '*app/main.py*' -or $_.CommandLine -like '*app\\\\main.py*' } | Select-Object -ExpandProperty ProcessId"],
|
||
|
|
capture_output=True, text=True
|
||
|
|
)
|
||
|
|
pids = [p.strip() for p in r.stdout.strip().splitlines() if p.strip().isdigit()]
|
||
|
|
for pid in pids:
|
||
|
|
result = subprocess.run(["taskkill", "/PID", pid, "/F"], capture_output=True, text=True)
|
||
|
|
print(f"잔존 프로세스 종료: {pid} -> returncode={result.returncode}")
|
||
|
|
|
||
|
|
if not pids:
|
||
|
|
print("실행 중인 봇 없음 — 새로 시작합니다")
|
||
|
|
|
||
|
|
# 2. 봇 시작 + PID 저장
|
||
|
|
os.chdir(BASE)
|
||
|
|
log_path = os.path.join(BASE, "logs", "bot_stderr.log")
|
||
|
|
env = os.environ.copy()
|
||
|
|
env["PYTHONUNBUFFERED"] = "1"
|
||
|
|
proc = subprocess.Popen(
|
||
|
|
[sys.executable, "-u", "app/main.py"],
|
||
|
|
creationflags=subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP,
|
||
|
|
stdout=open(log_path, "a", encoding="utf-8"),
|
||
|
|
stderr=subprocess.STDOUT,
|
||
|
|
close_fds=True,
|
||
|
|
env=env,
|
||
|
|
)
|
||
|
|
with open(pid_file, "w") as f:
|
||
|
|
f.write(str(proc.pid))
|
||
|
|
print(f"봇 시작 완료 PID={proc.pid}")
|
||
|
|
|
||
|
|
# 3. Discord 알림
|
||
|
|
sys.path.insert(0, BASE)
|
||
|
|
from app.main import load_env
|
||
|
|
load_env()
|
||
|
|
from app.monitor.notifier import send
|
||
|
|
mode = os.getenv("KIS_MOCK", "true")
|
||
|
|
dry = os.getenv("DRY_RUN", "true")
|
||
|
|
label = "[모의투자]" if mode == "true" else "[실거래]"
|
||
|
|
asyncio.run(send(f"{label} 자동매매 봇 시작 (DRY_RUN={dry})"))
|
||
|
|
print("Discord 알림 전송 완료")
|