소소한 팁
Go 언어에서 프로세스 실행 타임아웃(timeout) 지정하기
생계형 개발자!
2021. 2. 8. 13:33
Go 언어의 장점은 goroutine이라는 가벼운 thread를 기반으로 동적인 처리를 효율적으로 제공한다는 것이다. 그리고 채널 등을 통해 goroutine을 어렵지 않게 제어할 수 있지만, 별도로 프로세스를 실행하는 경우에는 통제가 어렵다.
실제 내부적으로 Maven이나 Gradle 빌드를 별도의 프로세스로 실행하는 경우에 해당 프로세스들이 중지되지 않는 경우들이 종종 발생한다. 이런 경우 내부적인 goroutine 관리만으로는 프로세스를 중지할 수 없다.
이런 경우에 친절하게도 Go에서는 타임아웃이 적용된 프로세스를 시작할 수 있고, 타임아웃이 된 경우에 실행했던 프로세스를 "kill -9"와 같은 명령으로 강제 종료시키는 것을 지원한다. 이를 공통 함수로 활용하면 어렵지 않게 타임아웃을 적용할 수 있다.
package util
import (
"context"
"errors"
"fmt"
"log"
"os/exec"
"runtime"
"time"
"golang.org/x/text/encoding/korean"
"golang.org/x/text/transform"
)
// Windows에서 한글 처리 (euc-kr -> utf-8)
func WindowsHangul(text string) (result string, err error) {
result, _, err = transform.String(korean.EUCKR.NewDecoder(), text)
return
}
func ExecCommandWithTimeout(errorOnTimeout bool, timeoutMin int, workingDirectory string, name string, arg ...string) (output string, timedOut bool, runError error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeoutMin) * time.Minute)
defer cancel()
cmd := exec.CommandContext(ctx, name, arg...)
cmd.Dir = workingDirectory
stdOutAndErr, err := cmd.CombineOutput()
if ctx.Err() == context.DeadlineExceeded {
timedOut = true
}
if runtime.GOOS == "windows" {
output, _ = WindowsHangul(string(stdOutAndErr))
} else {
output = string(stdOutAndErr)
}
if err != nil {
output = fmt.Sprintf("%s\nError : %v", output, err)
runError = err
}
// Timeout 발생 시, error 발생
if timedOut {
var resolvedError error
if runError == nil {
if errorOnTimeout {
runError = errors.New("timed out")
}
} else {
if !errorOnTimeout {
resolvedError = runError
runError = nil
}
}
output += "\n=====> The process requested to execute has timed out!!!"
output += fmt.Sprintln("\ntimed out process :", name, arg)
if resolvedError != nil {
output += fmt.Sprintln("Resolved error :", resolvedError)
}
log.Println("[WARN] timed out proess working dir. :", workingDirectory)
log.Println("[WARN] timed out process output :", output)
}
return
}
아울러, Windows에서의 한글 처리(euc-kr 결과를 utf-8로 변환)하는 함수도 포함하고 있다.
Written with ♥ by Vincent Han