본문 바로가기
개발/Desktop

[Desktop] 데스크탑 애플리케이션에서 터미널 명령어 수행 (with. mac os)

by JhDroid 2023. 4. 16.
728x90

맥에서 명령어 수행하기

  • Mac OS에서 어플리케이션 실행 시나 버튼을 눌렀을 때 특정 명령어를 수행하는 방법에 대해 정리해봤습니다.
    • Window도 아마 비슷한 방식으로 동작할거같은데 테스트는 못해봤습니다...
  • 테스트 환경
    • 인텔리제이 IDEA CE
    • Kotlin

 

Runtime

  • Java의 Runtime 클래스를 통해 외부 프로세스를 실행하거나 명령어를 수행할 수 있습니다.
    • Runtime 클래스는 어플리케이션과 어플리케이션 실행 환경(OS)과의 인터페이스 역할을 합니다.
val runCommand = Runtime.getRuntime().exec("adb devices")
  • Runtime.getRuntime() : 현재 어플리케이션 관련한 Runtime 객체를 받습니다.
  • exec() : 명령어를 수행할 함수 (지정된 커맨드를 독립한 프로세스로 실행)
  • 단, 위 코드는 결과를 받을 수 없는데(exec() 함수는 Process 객체를 리턴해줌) 단순 명령어 수행 후 리턴 값이 필요없다면 상관이 없지만 결과를 전달받아야할 때는 다음과 같이 수정해주어야 합니다.
val runCommand = Runtime.getRuntime().exec("adb devices")
    .inputStream.bufferedReader().readText()

System.out.print("result : $runCommand")

 

ProcessBuilder

  • ProcessBuilder와 확장함수를 통해 깔끔한 예외처리와 함께 명령어 수행이 가능합니다.
fun String.runCommand(): String {
    try {
        val parse = this.split("\\s".toRegex())
        val process = ProcessBuilder(*parse.toTypedArray())
            .redirectErrorStream(true)
            .start()

        process.waitFor(10, TimeUnit.MINUTES)
        return process.inputStream.bufferedReader().readText()
    } catch (e: IOException) {
        return "error"
    }
}
  • split ~ ProcessBuilder : 공백(\s) 기준으로 split 후 Spread 연산자를 통해 나열
    • ProcessBuilder는 exec() 함수와 다르게 공백이 들어가면 안되고 명령어를 순차적으로 전달해야 함
      • ex : ProcessBuilder("adb", "devices")
  • redirectErrorStream(true) : 커맨드가 잘못되었을 때 errorStream을 리턴 (설정하지 않으면 에러 발생 시 결과를 못 읽어옴)

 

  • 위에서 만든 함수를 수행해보자.
val successResult = "adb devices".runCommand()
println("success :: $successResult")

val errorResult = "adb device".runCommand() // s 빠짐
println("error :: $errorResult")

  • 명령어 수행 성공, 실패인 경우 모두 리턴 값을 받아오는것을 확인할 수 있습니다.

 

기타

  • 특정 디렉토리에서 작업을 수행해야 할 때
    • directory 함수에 File(작업을 수행할 경로) 전달
fun String.runCommand(workDir: File): String {
    try {
        val parts = this.split("\\s".toRegex())
        val process = ProcessBuilder(*parts.toTypedArray())
            .directory(workDir)
        // ...
}

 

 

 

참고

 

How to invoke external command from within Kotlin code?

I want to invoke an external command from Kotlin code. In C/Perl, I would use the system() function. In Python, I would use the subprocess module. In Go, I would use os/exec, and etc. But how do ...

stackoverflow.com

 

* 글에 틀린 부분이 있으면 댓글 부탁드립니다 :D

728x90