Go로 작성한 프로그램에서 로그를 별도의 파일에 쓸 때, 프로그램에서 Panic 발생 시 Panic에 출력은 해당 파일에 남지 않는다.
Panic 에 대한 출력을 로그 파일에 남기고 싶을 때, 첫 번째 방법은 프로그램 실행 시 아래와 같이 실행하는 것.
Program 2> ./log.txt&
두 번째 방법은 syscall 패키지를 사용해서 stderr을 로그 파일로 리디렉션 시키는 방법이 있다.
func main() {
logFile, _ := os.Create("log.txt")
syscall.Dup2(int(logFile.Fd()), 2)
}
이렇게 하면 패닉이 발생했을 때, 로그 파일에 패닉에 대한 내용이 남는다.
근데 syscall 패키지는 크로스플랫폼이 아니다. 즉, 이 방법은 리눅스에 한정된다. (Windows는 안됨)
Windows에서는 아래와 같이 할 수 있는 것 같은데, 해보지는 못했다.
(참고 : https://stackoverflow.com/questions/34772012/capturing-panic-in-golang)
package main
import (
"log"
"os"
"syscall"
)
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
)
func setStdHandle(stdhandle int32, handle syscall.Handle) error {
r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
if r0 == 0 {
if e1 != 0 {
return error(e1)
}
return syscall.EINVAL
}
return nil
}
// redirectStderr to the file passed in
func redirectStderr(f *os.File) {
err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
if err != nil {
log.Fatalf("Failed to redirect stderr to file: %v", err)
}
// SetStdHandle does not affect prior references to stderr
os.Stderr = f
}