Java에서 Windows Power Shell 명령어 실행

2024. 4. 1. 10:45·📘 Backend/Java

Java에서 Windows PowerShell 명령어 실행

평소에 리눅스 환경의 서버에서 작업을 하다가 윈도우에 서버를 구축하고 Java 프로그램을 돌리던 중,

분석된 RTSP 영상을 HLS로 스트리밍 하는 로직에서 FFmpeg 프로세스가 실행이 안되어 알아 보았습니다.


Java 코드에서 OS 마다 실행할 Command를 Runtime의 getRuntime().exec()를 통해 실행합니다.

이 때 Linux와 Windows는 Shell환경이 다르니 당연히 OS에 맞는 Shell을 지정해줘야 제대로 동작 할 겁니다.


잘 동작하는지 테스트 하기 위해 그리고 실시간 영상 변환 프로세스 체크 로직에 Windows 관련 코드를 좀 추가 해주었습니다.

그리고 리눅스와 같은 환경을 만들어 테스트 해보겠습니다.


테스트

RTSP Stream을 FFmpeg을 이용해 변환하는 프로세스 실행


변환중인 재생리스트(.m3u8)파일과 세그먼트(.ts)파일


실행중인 FFmpeg 프로세스 ID 확인 (Power Shell)


로직 추가 - Check FFmpeg Process

리눅스에서는 잘 작동하던 로직이 윈도우에서 안된 문제이니, 윈도우 환경에서 테스트 진행

  • 임의의 RTSP 영상을 FFmpeg을 이용해 변환 시킵니다.
  • 변환중인 FFmpeg 프로세스의 ID를 출력하는 윈도우 명령어를 추가해주고, exec()에 /bin/sh를 빼주고 command 변수에 powershell.exe를 붙여 Shell을 지정 해 줍니다.
  • 윈도우 프로세스의 InputStream, ErrorStream을 모두 출력 해줍니다.
/**  
 * FFMPEG 프로세스가 실행 중인지 확인한다.  
 * * @param ip  
 * @param port  
 * @param instanceName  
 * @return  
 */  
public boolean isFfmpegProcessRunning(final String ip, final Integer port, final String instanceName) {  
    boolean isRunning = false;  
    String command = "";  

    if (OS.contains("win")) {  
        command = "powershell.exe $currentId = (Get-Process -Id $PID).Id; Get-WmiObject Win32_Process | Where-Object { $_.CommandLine -like '*ffmpeg -i rtsp://" + ip + ":" + port + "/" + instanceName + "*' -and $_.ProcessId -ne $currentId } | Select-Object ProcessId";  
        log.info("Check FFmpeg - OS : Windows");  
    } else {  
        command = "ps -ef | grep ffmpeg | grep rtsp://" + ip + ":" + port + "/" + instanceName + " | grep -v grep | awk '{print $2}'";  
        log.info("Check FFmpeg - OS : Linux");  
    }  

    log.info("Check FFmpeg - Command : {}", command);  

    Process process = null;  

    try {  
        if (OS.contains("win")) {  
            // 윈도우에서는 powershell 명령을 직접 실행  
            process = Runtime.getRuntime().exec(command);  
        } else {  
            // 리눅스에서는 /bin/sh를 통해 명령 실행  
            process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", command});  
        }  

        BufferedReader inputStream = new BufferedReader(new InputStreamReader(process.getInputStream()));  
        BufferedReader errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream()));  

        String inputLine;  
        while ((inputLine = inputStream.readLine()) != null) {  
            log.info("Check FFmpeg - Input Stream - {}", inputLine);  
            isRunning = true;  
        }  

        String errorLine;  
        while ((errorLine = errorStream.readLine()) != null) {  
            log.info("Check FFmpeg - Error Stream - {}", errorLine);  
        }  

        process.waitFor(3000, TimeUnit.MILLISECONDS);  

    } catch (Exception e) {  
        log.warn("Check FFmpeg - Exception : {}", e.getMessage());  
        e.printStackTrace();  
    }  

    return isRunning;  
}

Main 함수 실행 결과 프로세스가 실행 중임을 확인함과 동시에 Process ID까지 잘 출력 되어 isRunning값 True 반환


실제 로직 수정 후 찍힌 로그

  • 특정 카메라 번호에 대한 FFmpeg 프로세스 ID가 없으면 FFmpeg을 실행하는 Health Check 로직이 잘 실행 되었습니다.
저작자표시

'📘 Backend > Java' 카테고리의 다른 글

Semaphore - Multi Threading 작업 순서 제어 & 동기화  (0) 2024.09.06
Producer-Consumer Pattern with RabbitMQ  (0) 2024.06.25
Coarse-Grained Lock & Fine-Grained Lock  (1) 2024.03.24
Java - Recursive를 이용한 File & Directory 제거  (0) 2024.03.21
ReentrantLock을 이용한 동시성 제어 (Mutex)  (1) 2024.02.25
'📘 Backend/Java' 카테고리의 다른 글
  • Semaphore - Multi Threading 작업 순서 제어 & 동기화
  • Producer-Consumer Pattern with RabbitMQ
  • Coarse-Grained Lock & Fine-Grained Lock
  • Java - Recursive를 이용한 File & Directory 제거
신건우
신건우
조용한 개발자
  • 신건우
    우주먼지
    신건우
  • 전체
    오늘
    어제
    • 분류 전체보기 (422)
      • 📘 Frontend (71)
        • Markup (1)
        • Style Sheet (2)
        • Dart (8)
        • Javascript (12)
        • TypeScript (1)
        • Vue (36)
        • React (2)
        • Flutter (9)
      • 📘 Backend (143)
        • Java (34)
        • Concurrency (19)
        • Reflection (1)
        • Kotlin (29)
        • Python (1)
        • Spring (42)
        • Spring Cloud (5)
        • Message Broker (5)
        • Streaming (2)
        • 기능 개발 (5)
      • 💻 Server (6)
        • Linux (6)
      • ❌ Error Handling (11)
      • 📦 Database (62)
        • SQL (31)
        • NoSQL (2)
        • JPQL (9)
        • QueryDSL (12)
        • Basic (4)
        • Firebase (4)
      • ⚙️ Ops (57)
        • CS (6)
        • AWS (9)
        • Docker (8)
        • Kubernetes (13)
        • MSA (1)
        • CI & CD (20)
      • 📚 Data Architect (48)
        • Data Structure (10)
        • Algorithm (8)
        • Programmers (17)
        • BaekJoon (5)
        • CodeUp (4)
        • Design Pattern (4)
        • AI (0)
      • ⚒️ Management & Tool (8)
        • Git (7)
        • IntelliJ (1)
      • 📄 Document (10)
        • Project 설계 (6)
        • Server Migration (3)
      • 📄 책읽기 (2)
        • 시작하세요! 도커 & 쿠버네티스 (2)
      • 🎮 Game (4)
        • Stardew Vally (1)
        • Path of Exile (3)
  • 블로그 메뉴

    • 링크

      • Github
    • 공지사항

    • 인기 글

    • 태그

      Lock #Thread #Concurrency
      React #Markdown
      GStreamer #Pipeline
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.0
    신건우
    Java에서 Windows Power Shell 명령어 실행
    상단으로

    티스토리툴바