下面由golang教程欄目給大家介紹Golang如何創(chuàng)建守護(hù)進(jìn)程以及平滑重啟,希望對(duì)需要的朋友有所幫助!
作為一名 PHP 開發(fā)老兵。使用過命令行對(duì) nginx、PHP-FPM 進(jìn)行啟動(dòng)/重啟/停止等操作。印象非常深刻。讓我用 C/C++ 開發(fā)這樣的系統(tǒng)肯定是沒精力搞了。然而,自從 Golang 進(jìn)入了我的視野之后。我發(fā)現(xiàn)這一切都變得非常的容易。
1)生成守護(hù)進(jìn)程
直接上代碼:
package main import ( "os" "os/exec" "path/filepath" ) func main() { //判 斷當(dāng)其是否是子進(jìn)程,當(dāng)父進(jìn)程return之后,子進(jìn)程會(huì)被 系統(tǒng)1 號(hào)進(jìn)程接管 if os.Getppid() != 1 { // 將命令行參數(shù)中執(zhí)行文件路徑轉(zhuǎn)換成可用路徑 filePath, _ := filepath.Abs(os.Args[0]) cmd := exec.Command(filePath, os.Args[1:]...) // 將其他命令傳入生成出的進(jìn)程 cmd.Stdin = os.Stdin // 給新進(jìn)程設(shè)置文件描述符,可以重定向到文件中 cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Start() // 開始執(zhí)行新進(jìn)程,不等待新進(jìn)程退出 return } }
對(duì) Linux 系統(tǒng)熟悉的人應(yīng)該知道:用戶創(chuàng)建的守護(hù)進(jìn)程會(huì)被 Linux 系統(tǒng)的 1 號(hào)進(jìn)程接管。換句話說,上面的代碼只能在 Linux 系統(tǒng)運(yùn)行。Unix 系統(tǒng)我沒有玩過。所以,也不能給出具體的建議。
我在網(wǎng)上看到還有其他的方法實(shí)現(xiàn)守護(hù)進(jìn)程的創(chuàng)建。但是,我覺得只有上面源碼的方式我覺得不錯(cuò)。并且成功用于項(xiàng)目當(dāng)中。
比如:
os.StartProcess() 創(chuàng)建守護(hù)進(jìn)程。 syscall.RawSyscall() 創(chuàng)建守護(hù)進(jìn)程。
唯獨(dú) exec.Command
創(chuàng)建守護(hù)進(jìn)程的方式最高級(jí)。封裝得最好。推薦使用這種試。
2) 守護(hù)進(jìn)程啟動(dòng)/重啟/停止
在第 1 點(diǎn)當(dāng)中,我們已經(jīng)成功啟動(dòng)了一個(gè)守護(hù)進(jìn)程。但是,我們不可能使用 kill 命令去結(jié)束它。然后,再啟動(dòng)吧。所以,我們要用業(yè)界專業(yè)的手法:信號(hào)。
任何進(jìn)程在運(yùn)行中都能接收到我們發(fā)送給它的信號(hào)。關(guān)于 Linux 的信號(hào)有很多。大家可以自己 Google 搜索關(guān)鍵詞:Linux 信號(hào)。
直接上源碼:
package main import "fmt" import "os" import "os/signal" import "syscall" func main() { // Go signal notification works by sending `os.Signal` // values on a channel. We'll create a channel to // receive these notifications (we'll also make one to // notify us when the program can exit). sigs := make(chan os.Signal, 1) done := make(chan bool, 1) // `signal.Notify` registers the given channel to // receive notifications of the specified signals. signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) // This goroutine executes a blocking receive for // signals. When it gets one it'll print it out // and then notify the program that it can finish. go func() { sig := <-sigs fmt.Println() fmt.Println(sig) done <- true }() // The program will wait here until it gets the // expected signal (as indicated by the goroutine // above sending a value on `done`) and then exit. fmt.Println("awaiting signal") <-done fmt.Println("exiting") }
有三個(gè)關(guān)鍵點(diǎn):
1)注冊(cè)信號(hào)
2)接收信號(hào)
3)處理信號(hào)。
只要把創(chuàng)建守護(hù)進(jìn)程與信號(hào)量處理整合一起,就能實(shí)現(xiàn)命令去管理守護(hù)進(jìn)程了。