DM Log

[RDP 모니터링 프로젝트 #5] 운영 서버 - Flask API & SQLite 메타데이터 저장 본문

PJT/영상 파일 재생 PJT

[RDP 모니터링 프로젝트 #5] 운영 서버 - Flask API & SQLite 메타데이터 저장

Dev. Dong 2025. 11. 30. 22:31

개요

녹화 종료 시 Window 서버가 전달하는 메타데이터를 중앙 서버에 저장하고, 영상 조회를 위한 API를 제공하는 운영 서버 구조 구축

  1. SQLite DB 스키마 설계
  2. Flask API 구축
  3. record_stop.bat 수정(운영 서버 메타데이터 POST 전송)
  4. record_stop_test.bat 테스트 도구 제공
  5. 파일 전송 완료 후 DB 상태 업데이트
  6. React 영상 목록 / 재생을 위한 API제공

SQLite DB 설계

  • DB는 영상 파일의 메타데이터만 저장
  • 스키마
필드 타입 설명
id PK PK, 자동 증가
server_name TEXT server1 / server2 ...
user TEXT RDP 사용자
session TEXT 세션 ID
date TEXT 녹화 시작 날짜 YYYYMMDD
filename TEXT 파일명
filepath TEXT Docker 내부 저장 경로
uploaded INTEGER 0=전송 전 / 1=전송 완료
time TEXT 녹화 시작 시간
upload_time TEXT YYMMDDHHMMSS (전송 완료 시각)

SQLite 테이블 생성 스크립트

  • /app/db/init_db.py
import sqlite3

conn = sqlite3.connect("rdp.db")
cur = conn.cursor()

cur.execute("""
CREATE TABLE IF NOT EXISTS rdp_video (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    server_name TEXT,
    user TEXT,
    session TEXT,
    date TEXT,
    filename TEXT,
    filepath TEXT,
    uploaded INTEGER,
    time TEXT,
    upload_time TEXT
)
""")

conn.commit()
conn.close()

녹화 영상 저장 스크립트 수정

  • record_stop.bat (메타데이터 POST 포함)
@echo off
setlocal enabledelayedexpansion

set BASE_DIR=C:\rdp_monitor
set RECORD_DIR=%BASE_DIR%\record
set LOG_DIR=%BASE_DIR%\logs

:: 인자: 사용자명/세션ID
set USER_NAME=%1
set SESSION_ID=%2

:: 날짜 계산
for /f "tokens=1-3 delims=- " %%a in ("%date%") do (
    set YYYY=%%c
    set MM=%%a
    set DD=%%b
)
set TODAY=%YYYY%%MM%%DD%

:: 시간 계산
for /f "tokens=1-3 delims=:." %%a in ("%time%") do (
    set HH=%%a
    set MI=%%b
    set SS=%%c
)
set TS=%YYYY%%MM%%DD%%HH%%MI%%SS%

:: 서버 이름
set SERVER_NAME=server1

:: 파일명 생성
set FILE_NAME=%USER_NAME%_%TS%.webm
set FILE_RELATIVE=%TODAY%/%USER_NAME%/%FILE_NAME%

:: PID 파일
set USER_FOLDER=%RECORD_DIR%\%TODAY%\%USER_NAME%
set PID_FILE=%USER_FOLDER%\%SESSION_ID%.pid

if exist "%PID_FILE%" (
    set /p PID=<"%PID_FILE%"
    taskkill /PID !PID! /F >nul 2>&1
    del "%PID_FILE%"
)

:: 로그 기록
if not exist "%LOG_DIR%\%TODAY%" mkdir "%LOG_DIR%\%TODAY%"
echo [%date% %time%] STOP USER=%USER_NAME% SESSION=%SESSION_ID% FILE=%FILE_NAME% >> "%LOG_DIR%\%TODAY%\logoff.log"

:: 메타데이터 POST
powershell -Command ^
"Invoke-WebRequest -Uri 'http://운영 서버 IP/api/rdp/metadata' ^
-Method POST ^
-Body '{\"server\":\"%SERVER_NAME%\",\"user\":\"%USER_NAME%\",\"session\":\"%SESSION_ID%\",\"date\":\"%TODAY%\",\"filename\":\"%FILE_NAME%\",\"filepath\":\"%FILE_RELATIVE%\",\"uploaded\":0,\"time\":\"%HH%%MI%%SS%\"}' ^
-ContentType 'application/json'"

exit /b 0
  • record_stop_test.bat (실제 녹화 없이 API 동작 확인 용)
@echo off
setlocal enabledelayedexpansion

echo ------------------------------
echo   METADATA POST TEST START
echo ------------------------------

set USER_NAME=testuser
set SESSION_ID=0x99999
set SERVER_NAME=server1

:: 날짜
for /f "tokens=1-3 delims=- " %%a in ("%date%") do (
    set YYYY=%%c
    set MM=%%a
    set DD=%%b
)
set TODAY=%YYYY%%MM%%DD%

:: 시간
for /f "tokens=1-3 delims=:." %%a in ("%time%") do (
    set HH=%%a
    set MI=%%b
    set SS=%%c
)
set TS=%YYYY%%MM%%DD%%HH%%MI%%SS%

set FILE_NAME=%USER_NAME%_%TS%.webm
set FILE_RELATIVE=%TODAY%/%USER_NAME%/%FILE_NAME%

powershell -Command ^
"Invoke-WebRequest -Uri 'http://운영 서버 IP/api/rdp/metadata' ^
-Method POST ^
-Body '{\"server\":\"%SERVER_NAME%\",\"user\":\"%USER_NAME%\",\"session\":\"%SESSION_ID%\",\"date\":\"%TODAY%\",\"filename\":\"%FILE_NAME%\",\"filepath\":\"%FILE_RELATIVE%\",\"uploaded\":0,\"time\":\"%HH%%MI%%SS%\"}' ^
-ContentType 'application/json'"

echo TEST COMPLETE
pause
exit /b 0

Flask API

  • 메타데이터 저장 - POST /api/rdp/metadata
@app.route("/api/rdp/metadata", methods=["POST"])
def metadata():
    data = request.json

    query("""
    INSERT INTO rdp_video
    (server_name, user, session, date, filename, filepath, uploaded, time)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    """, (
        data["server"],
        data["user"],
        data["session"],
        data["date"],
        data["filename"],
        data["filepath"],
        data.get("uploaded", 0),
        data["time"]
    ))

    return jsonify({"result":"ok"})
  • 서버 별 녹화된 날짜 리스트 API - GET /api/rdp/dates?server=server1
@app.route("/api/rdp/dates", methods=["GET"])
def get_dates():
    server = request.args.get("server")

    rows = query("""
        SELECT DISTINCT date
        FROM rdp_video
        WHERE server_name=?
        ORDER BY date DESC
    """, (server,))

    dates = [r[0] for r in rows]
    return jsonify(dates)
  • 날짜 별  영상 목록 - GET /api/rdp/list?server=server1&date=20250312
@app.route("/api/rdp/list", methods=["GET"])
def get_list():
    server = request.args.get("server")
    date = request.args.get("date")

    rows = query("""
        SELECT id, filename, filepath, uploaded, user
        FROM rdp_video
        WHERE server_name=? AND date=?
        ORDER BY time ASC
    """, (server, date))

    return jsonify(rows)

 

  • 영상 재생 API - GET /api/rdp/video/<path>
@app.route("/api/rdp/video/<path:filepath>")
def serve_video(filepath):
    full_path = f"/data/rdp-video/{filepath}"   # Docker 내부 기준
    return app.send_static_file(full_path)