DM Log

[RDP 모니터링 프로젝트 #3] 다중 RDP 접속 대응 및 세션별 PID 관리 전략 본문

PJT/영상 파일 재생 PJT

[RDP 모니터링 프로젝트 #3] 다중 RDP 접속 대응 및 세션별 PID 관리 전략

Dev. Dong 2025. 11. 30. 16:35

개요

여러 사용자 동시 접속 시 ffmpeg 녹화를 완벽하게 분리하여 안정적 운영 방법에 대한 내용이다.

실제 Window Server 운영 환경에서는 다음과 같은 상황이 빈번하게 발생한다.

  • 여러 사용자가 동시에 원격 접속
  • 동일 사용자가 2개 이상의 RDP 창을 띄움
  • SYSTEM 계정 등 내부 서비스 계정에서 로그 이벤트(4624) 발생
  • 로그온 이벤트가 1번만 아닌 여러 번 발생 문제

위의 상황에서 녹화 실행 시 발생하는 문제

  • ffmpeg 여러 개가 중복 실행
  • 잘못된 PID 종료
  • 사용자 간 영상이 섞임
  • 녹화 파일이 덮어씌어짐
  • 시스테 리소스 폭주

세션(Session ID) 기반으로 녹화를 완벽하게 분리하는 구조로 개선 및 안정화 Batch 스크립트 작성 필요


왜 세션ID 기반 관리인가?

Windows RDP 접속의 경우 로그인 시 고유한 세션ID를 부여하며, 한 사용자라도 RDP를 여러개 접속 시 고유의 Session ID가 부여 되므로 녹화 단위는 사용자가 아닌 세션 ID 기반의 녹화가 진행 되어야 한다. 

기존 단순 방식의 문제

세션 ID를 고려하지 않는 방식은:

  • user1이 2개의 창 생성 시 ffmpeg가 덮어 써짐
  • STOP 시 어떤 프로세스를 종료해야 할지에 대한 문제 밠애
  • SYSTEM 계정도 4624 이벤트 생성 → ffmpeg 수십 개 실행
  • 영상 관리가 불가능

세션 ID 기반 분리 전략

  1. 각 세션은 자신만의 ffmpeg 프로세스를 가짐
  2. ffmpeg 프로세스의 PID를 sessionID.pid 파일에 저장
  3. 로그오프 시 4634 이벤트에서 전달 받은 세션ID로 정확히 해당 ffmpeg만 종료
  4. Winoows Event Log는 중복 발생 가능성 방지를 위해 같은 세션이 녹화 중이면 ffmpeg 실행x

안정화 버전 Batch Script

record_start.bat

@echo off
setlocal enabledelayedexpansion

:: Base paths
set BASE_DIR=C:\rdp_monitor
set RECORD_DIR=%BASE_DIR%\record
set LOG_DIR=%BASE_DIR%\logs
set FFMPEG_PATH=%BASE_DIR%\ffmpeg\ffmpeg.exe

:: Event Variables
set USER_NAME=%1
set SESSION_ID=%2

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

:: Build folder structure
set USER_FOLDER=%RECORD_DIR%\%TODAY%\%USER_NAME%
set LOG_FOLDER=%LOG_DIR%\%TODAY%
set PID_FILE=%USER_FOLDER%\%SESSION_ID%.pid
set ERR_FILE=%LOG_FOLDER%\ffmpeg_%USER_NAME%_%SESSION_ID%.err

:: Create folders if not exists
if not exist "%USER_FOLDER%" mkdir "%USER_FOLDER%"
if not exist "%LOG_FOLDER%" mkdir "%LOG_FOLDER%"

:: Prevent duplicate start
if exist "%PID_FILE%" (
    echo [%date% %time%] DUPLICATE START BLOCKED USER=%USER_NAME% SESSION=%SESSION_ID% >> "%LOG_FOLDER%\logon.log"
    exit /b 0
)

:: Timestamp for filename
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%

:: Output video file
set OUT_FILE=%USER_FOLDER%\%USER_NAME%_%TS%.webm

:: Start ffmpeg with VP9, 30fps, 1280x720
start "" /B "%FFMPEG_PATH%" ^
    -y ^
    -rtbufsize 1500M ^
    -f gdigrab -framerate 30 -i desktop ^
    -vf "scale=1280:720" ^
    -c:v libvpx-vp9 ^
    "%OUT_FILE%" 2>>"%ERR_FILE%"

:: Save PID
echo !ERRORLEVEL! > "%PID_FILE%"

:: Log
echo [%date% %time%] START USER=%USER_NAME% SESSION=%SESSION_ID% FILE=%OUT_FILE% >> "%LOG_FOLDER%\logon.log"

exit /b 0

record_stop.bat

@echo off
setlocal enabledelayedexpansion

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

:: Event args
set USER_NAME=%1
set SESSION_ID=%2

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

set USER_FOLDER=%RECORD_DIR%\%TODAY%\%USER_NAME%
set LOG_FOLDER=%LOG_DIR%\%TODAY%
set PID_FILE=%USER_FOLDER%\%SESSION_ID%.pid

if not exist "%LOG_FOLDER%" mkdir "%LOG_FOLDER%"

:: Kill only if PID exists
if exist "%PID_FILE%" (
    set /p PID=<"%PID_FILE%"
    taskkill /PID !PID! /F >nul 2>&1

    del "%PID_FILE%"
    echo [%date% %time%] STOP USER=%USER_NAME% SESSION=%SESSION_ID% PID=!PID! >> "%LOG_FOLDER%\logoff.log"
) else (
    echo [%date% %time%] STOP FAILED(NO PID) USER=%USER_NAME% SESSION=%SESSION_ID% >> "%LOG_FOLDER%\logoff.log"
)

exit /b 0