[Java] cmd 명령어를 실행하기 위한 방법 (Process 클래스)


Development note/Java  2019. 6. 5. 22:53

안녕하세요. 명월입니다.


이 글은 java 환경에서 cmd 명령어를 실행하기 위한 방법에 대한 글입니다.

우리가 프로그램을 작성할 시 웹 어플리케이션이나 일반 어플리케이션에서 다른 프로그램을 실행하거나 내부 서버를 조종해야 할 경우가 있습니다. 예를 들면 jankins의 경우, 웹 환경에서 git이나 svn의 명령어를 조작하거나 쉘 명령어를 쳐서 웹 환경에서 서버를 제어할 수 있게끔하는 프로그램입니다.

이처럼 프로그램을 통해 쉘 명령어를 사용할 경우가 있는 데 이럴 때 사용할 수 있는 소스 코드 입니다.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Scanner;
import java.util.concurrent.Executors;

public class ProcessTest2 {
  public static void main(String[] args) {
    try {
      //Linux의 경우는 /bin/bash
      //Process process = Runtime.getRuntime().exec("/bin/bash");
      Process process = Runtime.getRuntime().exec("cmd");
      //Process의 각 stream을 받는다.
      //process의 입력 stream
      OutputStream stdin = process.getOutputStream();
      //process의 에러 stream
      InputStream stderr = process.getErrorStream();
      //process의 출력 stream
      InputStream stdout = process.getInputStream();

      //쓰레드 풀을 이용해서 3개의 stream을 대기시킨다.
      
      //출력 stream을 BufferedReader로 받아서 라인 변경이 있을 경우 console 화면에 출력시킨다.
      Executors.newCachedThreadPool().execute(() -> {
        // 문자 깨짐이 발생할 경우 InputStreamReader(stdout)에 인코딩 타입을 넣는다. ex) InputStreamReader(stdout, "euc-kr")
        // try (BufferedReader reader = new BufferedReader(new InputStreamReader(stdout, "euc-kr"))) {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(stdout))) {
          String line;
          while ((line = reader.readLine()) != null) {
            System.out.println(line);
          }
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      });

      //에러 stream을 BufferedReader로 받아서 에러가 발생할 경우 console 화면에 출력시킨다.
      Executors.newCachedThreadPool().execute(() -> {
        // 문자 깨짐이 발생할 경우 InputStreamReader(stdout)에 인코딩 타입을 넣는다. ex) InputStreamReader(stdout, "euc-kr")
        // try (BufferedReader reader = new BufferedReader(new InputStreamReader(stderr, "euc-kr"))) {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(stderr))) {
          String line;
          while ((line = reader.readLine()) != null) {
            System.out.println("err " + line);
          }
        } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      });

      //입력 stream을 BufferedWriter로 받아서 콘솔로부터 받은 입력을 Process 클래스로 실행시킨다.
      Executors.newCachedThreadPool().execute(() -> {
        // Scanner 클래스는 콘솔로 부터 입력을 받기 위한 클래스 입니다.
        try (Scanner scan = new Scanner(System.in)) {
          try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin))) {
            while (true) {
              // 콘솔로 부터 엔터가 포함되면 input String 변수로 값이 입력됩니다.
              String input = scan.nextLine();
              // 콘솔에서 \n가 포함되어야 실행된다.(엔터의 의미인듯 싶습니다.)
              input += "\n";
              writer.write(input);
              // Process로 명령어 입력
              writer.flush();
              // exit 명령어가 들어올 경우에는 프로그램을 종료합니다.
              if ("exit\n".equals(input)) {
                System.exit(0);
              }
            }
          } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
      });

    } catch (Throwable e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

위 결과 화면을 보면 제가 콘솔에서 cd의 명령어와 dir의 명령어를 치고 결과를 출력받는 이미지입니다. 마지막에 exit 명령어를 치면서 프로그램을 종료시킵니다.

eclipse 환경에서 글자 인코딩 설정을 안해서 문자 깨짐 현상이 나오는데 단순 eclipse 설정의 문제입니다. 실제의 String에는 한글이 들어가 있습니다. 그래도 이클립스 설정을 해도 문자 깨짐이 발생하면 위 InputStreamReader에 인코딩 타입을 넣으면 해결됩니다.


여기까지 cmd 명령어를 실행하기 위한 방법에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.