不論應用是如何部署的,我們都期望能撲捉到應用的錯誤日志,
解決思路:
- 自己寫代碼處理異常攔截,甚至直接在main函數中寫異常攔截。
- stderr重定向到某個文件里
- 使用 syscall.Dup2
第一種方法比較簡單, 我們這里主要看后兩種:
使用 stderr替換的代碼:
package main
import (
"fmt"
"os"
)
func main() {
f, _ := os.OpenFile("C:\\tmp\\11.txt", os.O_WRONLY|os.O_CREATE|os.O_SYNC,
0755)
os.Stdout = f
os.Stderr = f
fmt.Println("fmt")
fmt.Print(make(map[int]int)[0])
}
這里的 Stdout 、Stderr 的含義如下, 同樣也適用win:
在通常情況下,UNIX每個程序在開始運行的時刻,都會有3個已經打開的stream. 分別用來輸入,輸出,打印診斷和錯誤信息。通常他們會被連接到用戶終端. 但也可以改變到其它文件或設備。
Linux內核啟動的時候默認打開的這三個I/O設備文件:標准輸入文件stdin,標准輸出文件stdout,標准錯誤輸出文件stderr,分別得到文件描述符 0, 1, 2。
stdin是標准輸入,stdout是標准輸出,stderr是標准錯誤輸出。大多數的命令行程序從stdin輸入,輸出到stdout或stderr。
上面方法,可能會攔截不到一些系統級別的崩潰信息,這時候就需要走下面的方案了。
使用 syscall.Dup2 的例子如下, 注意 windows 下會編譯直接報錯: undefined: syscall.Dup2, 只有 linux 下才可以用。
syscall.Dup2 is a linux/OSX only thing. there's no windows equivalent。
參考: https://github.com/golang/go/issues/325
package main
import (
"fmt"
"os"
"syscall"
)
func main() {
logFile, _ := os.OpenFile("/tmp/x", os.O_WRONLY|os.O_CREATE|os.O_SYNC, 0755)
syscall.Dup2(int(logFile.Fd()), 1)
syscall.Dup2(int(logFile.Fd()), 2)
fmt.Printf("Hello from fmt\n")
panic("Hello from panic\n")
}
這兩個區別,我看到有下面描述文字:
https://github.com/golang/go/issues/325
比較變態的是,我看到下面的寫法,確保記錄異常日志。
if crashFile, err := os.OpenFile(fmt.Sprintf("%v--crash.log", path), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0664); err == nil {
crashFile.WriteString(fmt.Sprintf("%v Opened crashfile at %v", os.Getpid(), time.Now()))
os.Stderr = crashFile
syscall.Dup2(int(crashFile.Fd()), 2)
}
參考資料:
怎么把所有包括底層類庫,輸出到stderr的內容, 重新定向到一個日志文件里面?
https://groups.google.com/forum/#!topic/golang-china/qUtCQSq6_S8
Replacing os.Stdout/os.Stderr should redirect panic #325
https://github.com/golang/go/issues/325
runtime: support for daemonize
https://github.com/golang/go/issues/227
stdin, stdout, stderr以及重定向
http://my.oschina.net/qihh/blog/55308
Windows管道(Pipe)重定向stdout,stderr,stdin
http://blog.csdn.net/c80486/article/details/6589292
stdin, stdout, stderr 詳解
http://www.cnblogs.com/puputu/archive/2010/06/02/1749769.html
golang中os/exec包用法
http://blog.csdn.net/chenbaoke/article/details/42556949
12.3 應用部署
https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/12.3.md
Go到目前還沒有解決成為守護進程(Daemonize)的問題吧?各位是怎么解決的?
http://segmentfault.com/q/1010000000699471