Java에서 코드로 리눅스 명령어(shell command)를 실행하는 방법에 대해서 알아보겠습니다.

1. 단순한 명령어 실행

Runtime.exec()를 이용하여 명령어를 실행할 수 있습니다. 실행 결과를 확인하지 않고 명령어만 실행합니다. 실행 결과를 읽는 방법은 다음에 소개합니다.

  • exec(command) : command를 실행
  • waitFor() : 명령어 실행이 완료될 때까지 기다리며 정상적으로 종료되면 0을 리턴
import java.io.IOException;

public class Example {

    public static void main(String[] args) {

        String command = "ls -l"; // 실행할 Linux 명령어
        try {
            Process process = Runtime.getRuntime().exec(command);
            int exitCode = process.waitFor();
            System.out.println("exit code: " + exitCode);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Output:

exit code: 0

2. 명령어 실행 및 결과 받기

Runtime.exec()으로 명령어를 실행하고, 리턴된 Process로 실행 결과를 읽을 수 있습니다.

  • process.getInputStream() : 명령어 실행 결과에 대한 InputStream 리턴
  • reader.readLine() : 실행 결과를 한 줄씩 리턴
  • waitFor() : 명령어 실행이 완료될 때까지 기다리며 정상적으로 종료되면 0을 리턴
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Example {

    public static void main(String[] args) {

        String command = "ls -l"; // 실행할 Linux 명령어
        try {
            Process process = Runtime.getRuntime().exec(command);
            int exitCode = process.waitFor();

            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()));

            System.out.println("result:");
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            System.out.println("exit code: " + exitCode);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Output:

result:
total 32
drwxrwxr-x 7 mjs mjs 4096 Jun  1  2022 build
-rw-rw-r-- 1 mjs mjs  723 Sep  3 10:34 build.gradle
drwxrwxr-x 3 mjs mjs 4096 Oct 10  2021 gradle
-rwxrwxr-x 1 mjs mjs 5770 Oct 10  2021 gradlew
-rw-rw-r-- 1 mjs mjs 3058 Oct 10  2021 gradlew.bat
-rw-rw-r-- 1 mjs mjs   34 Oct 10  2021 settings.gradle
drwxrwxr-x 4 mjs mjs 4096 Oct 10  2021 src
exit code: 0

3. ProcessBuilder로 명령어 실행, 결과 받기

ProcessBuilder를 사용하여 명령어를 실행할 수 있으며, 실행 결과는 Process를 통해 위와 같이 읽을 수 있습니다.

  • String[] commands = {"ls", "-l"} : “ls -al”은 “ls”와 “-al”을 분리하여 배열로 입력, 띄어쓰기가 있으면 모두 분리하면 됨.
  • new ProcessBuilder(commands) : commands를 실행하는 ProcessBuilder 생성
  • builder.directory(new File(directory)); : 명령어가 실행되는 작업 디렉토리 경로 설정
  • builder.start() : 명령어 실행
  • process.waitFor() : 명령어 실행이 완료될 때까지 기다리며 정상적으로 종료되면 0을 리턴
  • BufferedReader를 이용하여 Process에서 실행 결과 읽음
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

public class Example {

    public static void main(String[] args) {

        String directory = "/home/mjs/IdeaProjects/JavaExample";
        String[] commands = {"ls", "-l"};

        try {
            ProcessBuilder builder = new ProcessBuilder(commands);
            builder.directory(new File(directory)); // working directory 설정

            Process process = builder.start();
            int exitCode = process.waitFor();

            // 실행 결과 읽기 & 출력
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()));
            System.out.println("result:");
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            System.out.println("exit code: " + exitCode);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Output:

result:
total 32
drwxrwxr-x 7 mjs mjs 4096 Jun  1  2022 build
-rw-rw-r-- 1 mjs mjs  723 Sep  3 10:34 build.gradle
drwxrwxr-x 3 mjs mjs 4096 Oct 10  2021 gradle
-rwxrwxr-x 1 mjs mjs 5770 Oct 10  2021 gradlew
-rw-rw-r-- 1 mjs mjs 3058 Oct 10  2021 gradlew.bat
-rw-rw-r-- 1 mjs mjs   34 Oct 10  2021 settings.gradle
drwxrwxr-x 4 mjs mjs 4096 Oct 10  2021 src
exit code: 0