好湿?好紧?好多水好爽自慰,久久久噜久噜久久综合,成人做爰A片免费看黄冈,机机对机机30分钟无遮挡

主頁 > 知識庫 > golang 后臺進程的啟動和停止操作

golang 后臺進程的啟動和停止操作

熱門標簽:電話機器人軟件免費 百度地圖標注后傳給手機 涿州代理外呼系統 阿克蘇地圖標注 外呼系統顯本地手機號 外呼系統用什么卡 excel地圖標注分布數據 壽光微信地圖標注 評價高的400電話辦理

啟動命令

我們先來個非后臺運行的啟動命令

func init() {
    startCmd := cobra.Command{
        Use:   "start",
        Short: "Start Gonne",
        Run: func(cmd *cobra.Command, args []string) {
            startHttp()
        },
    }
    startCmd.Flags().BoolVarP(daemon, "deamon", "d", false, "is daemon?")
    RootCmd.AddCommand(startCmd)
 
}

startHttp方法啟動一個http的web服務

func startHttp() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello cmd!")
    })
    if err := http.ListenAndServe(":9090", nil); err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

現在通過gonne start便可以啟動一個web服務了,但是程序停留在命令行,如果ctrl+C程序也會終止了

命令行參數

如果想要后臺啟動,那么得讓start命令知道是要后臺運行的,參照docker命令行的方式就是加上-d,給一個命令添加參數的判斷只需很少的代碼

改造一下代碼

func init() {
    var daemon bool
    startCmd := cobra.Command{
        Use:   "start",
        Short: "Start Gonne",
        Run: func(cmd *cobra.Command, args []string) {
            if daemon {
        fmt.Println("gonne start",daemon)        
            }
            startHttp()
        },
    }
    startCmd.Flags().BoolVarP(daemon, "deamon", "d", false, "is daemon?")
    RootCmd.AddCommand(startCmd)
 
}

命令行輸入

gonne start -d

這樣就可以接收到-d參數了,這里要說明一下,第一個參數取值,第二個參數代碼--deamon,第三個參數代表-d

第四個參數代碼不加-d時候的默認值,第五參數是描述

后臺運行

后臺運行其實這里使用的是一個巧妙的方法,就是使用系統的command命令行啟動自己的命令行輸入,是不是有點繞,再看看看改造后的代碼

Run: func(cmd *cobra.Command, args []string) {
  if daemon {
    command := exec.Command("gonne", "start")
    command.Start()
    fmt.Printf("gonne start, [PID] %d running...\n", command.Process.Pid)
    ioutil.WriteFile("gonne.lock", []byte(fmt.Sprintf("%d", command.Process.Pid)), 0666)
    daemon = false
    os.Exit(0)
  } else {
    fmt.Println("gonne start")
  }
  startHttp()
},

用exec的Command啟動剛輸入的gonne start -d,就會攔截到這條請求然后通過gonne start,但是程序就不會停留在命令行了,然后發現http服務還在,還可以訪問。

還有一點就是把pid輸出到gonne.lock文件,給停止的程序調用

終止后臺程序

有了之前的操作后,停止就簡單多了

func init() {
    RootCmd.AddCommand(stopCmd)
}
 
var stopCmd = cobra.Command{
    Use:   "stop",
    Short: "Stop Gonne",
    Run: func(cmd *cobra.Command, args []string) {
        strb, _ := ioutil.ReadFile("gonne.lock")
        command := exec.Command("kill", string(strb))
        command.Start()
        println("gonne stop")
    },
}

執行 gonne stop 即可終止之前啟動的http服務

help命令

好了,關于命令的操作講完了,再看看cobra給的福利,自動生成的help命令

這個不需要你做什么操作,只需要輸入gonne help,相關信息已經幫你生產好了。

appletekiMacBook-Pro:andev apple$ gonne help
Usage:
  gonne [flags]
  gonne [command]
 
Available Commands:
  help        Help about any command
  start       Start Gonne
  stop        Stop Gonne
  version     Print the version number of Gonne
 
Flags:
  -h, --help   help for gonne
 
Use "gonne [command] --help" for more information about a command.

當然,子命令也有

appletekiMacBook-Pro:andev apple$ gonne start -h
Start Gonne
 
Usage:
  gonne start [flags]
 
Flags:
  -d, --deamon   is daemon?
  -h, --help     help for start

自此告別各種腳本!

補充:golang子進程的啟動和停止,mac與linux的區別

今天接到一個任務是將原來運行在mac的應用移植到linux,原因當然是因為客戶那邊當前是linux環境,也不想再采購mac電腦。

通常來說,這個工作并不難,因為我選用的服務器端技術是c或者golang,這兩種技術具有很好的可移植性,而且大多是重新編譯即可運行,所以接到任務的開始并沒有把這個當一回事。

跟想象中的也差不多,搭建好linux測試服務器,在mac上把運行很久的應用重新交叉編譯了一遍,部署到linux實驗環境,啟動、測試,看起來一切正常。準備打包交活,這時候發現一個問題,程序無法終止。

簡單調試后就找到了原因,在系統中啟動的子進程,發出終止信號之后居然仍在運行,導致父進程也一直無法退出,尷尬了。

列一下采用的代碼(代碼為簡化版僅供示例):

func startChild1() {
 cmd := exec.Command("/bin/sh", "-c", "sleep 1000")
 time.AfterFunc(10*time.Second, func() {
  fmt.Println("PID1=", cmd.Process.Pid)
  syscall.Kill(-cmd.Process.Pid, syscall.SIGQUIT)
  fmt.Println("killed")
 })
 fmt.Println("begin run")
 cmd.Run()
}

示例代碼首先啟動一個sleep的子進程,表示某個子業務開始工作,然后延時10秒鐘之后,把這個子進程殺死。

這段代碼啟動子進程和關閉子進程在mac電腦的原有系統上工作都很正常,但是到了linux,啟動子進程仍然沒有問題,關閉子進程不成功。

檢查了一下在linux的工作過程,發現啟動子進程之后,實際上是啟動了兩個進程,一個進程是/bin/sh,隨后sh又啟動了一個子進程自身的子進程sleep。

而發出退出命令的時候,只有sh退出了,sleep進程仍然繼續運行。對比同樣的mac電腦上,sh進程是沒有出現的,只有一個sleep進程,所以發出退出命令的時候,sleep正常關閉,系統表現正常。

使用/bin/sh來啟動另外的命令行程序是有原因的,這源于golang本身的設計,golang的exec.Command,后面第一個參數是命令行程序本身,之后的每一個exec.Command參數,都代表命令行程序的一個參數,而不是我們常用的,命令行程序路徑和參數都可以寫在一個字符串,用空格隔開即可。

所以有的時候我們是為了省事,也有的時候是順手移植了別的語言的代碼,就使用/bin/sh來啟動需要的命令行程序,就如同上面示例代碼一樣,這樣情況下,除了-c參數要單獨占用一個字符串,我們原本要啟動的字符串程序及其參數,就可以如同常見語言處理方式那樣,放在一個字符串了。

我們可以嘗試一下這個代碼:

func startChild2() {
 cmd := exec.Command("sleep", "1000")
 time.AfterFunc(10*time.Second, func() {
  fmt.Println("PID2=", cmd.Process.Pid)
  syscall.Kill(-cmd.Process.Pid, syscall.SIGQUIT)
  fmt.Println("killed")
 })
 fmt.Println("begin run")
 cmd.Run()
}

測試一下,這段代碼因為沒有經過/bin/sh程序,在linux上也只有sleep這一個進程被建立,直接向其發出退出指令是可以正常工作的。這從進程的觀察中及實驗的結果中,都可以證實我們的判斷。

知道了原因,處理起來也很容易,一是把程序改成類似上面這樣的方式啟動進程。另外一個辦法則是直接為/bin/sh及我們的命令行進程建立一個進程組,這樣最后發出的指令退出這個進程組,同樣可以同時退出/bin/sh及sleep兩個進程,達到我們的需求。

寫代碼測試一下:

func startChild3() {
 cmd := exec.Command("/bin/sh", "-c", "sleep 1000")
 cmd.SysProcAttr = syscall.SysProcAttr{Setpgid: true}
 time.AfterFunc(10*time.Second, func() {
  fmt.Println("PID3=", cmd.Process.Pid)
  syscall.Kill(-cmd.Process.Pid, syscall.SIGQUIT)
  fmt.Println("killed")
 })
 fmt.Println("begin run")
 cmd.Run()
}

經過實際測試,這段代碼在不改變原有的命令行參數傳遞習慣的基礎上,可以正常在linux及mac電腦順利執行。

最后再說一下命令cmd.Process.Signal,golang文檔上說的很清楚,這是向進程發送消息信號,比如同樣的syscall.SIGQUIT,這也是告訴子進程退出的意思。

所以大多的應用中,我們希望一個進程退出,直接用:

cmd.Process.Signal(syscall.SIGQUIT)

也是可以正常執行的,但對于我們上面說的情況,如果先使用/bin/sh啟動了另外一個子進程,這種方法就無效了(指在linux無效,mac測試是一樣可以用的,關鍵區別同樣是在mac,/bin/sh進程不會保留并等待我們啟動的子進程退出,所以退出消息可以正常的發送到正常的子進程)。

所以為了跨平臺的通用性,建議還是使用Process.Kill或者syscall.Kill來殺死子進程。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。

您可能感興趣的文章:
  • golang 輸出重定向:fmt Log,子進程Log,第三方庫logrus的詳解
  • Golang信號處理及如何實現進程的優雅退出詳解
  • golang如何實現mapreduce單進程版本詳解
  • golang守護進程用法示例

標簽:吐魯番 蘭州 銅川 梅河口 汕頭 重慶 雞西 欽州

巨人網絡通訊聲明:本文標題《golang 后臺進程的啟動和停止操作》,本文關鍵詞  golang,后臺,進程,的,啟動,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《golang 后臺進程的啟動和停止操作》相關的同類信息!
  • 本頁收集關于golang 后臺進程的啟動和停止操作的相關信息資訊供網民參考!
  • 推薦文章
    主站蜘蛛池模板: 青春草色综合丁香久久| 王雪把双腿打开给老赵| 国产精品久久久久久一级毛片军妓| 欧美日韩国产亚洲综合图片小说| 国产成人在线电影| 国产日韩在线| 欧美熟妇hairy高潮HD| 无码ⅴ久久亚洲熟妇无码| 日本成人不卡视频| 公主该戴玉器了| 揉我奶头?啊?嗯高潮A| 久久久无码AV精品亚洲网站红粉| 久久成年人| 艳母免费| 女同学夹得好紧…我要进去了| 把女人弄爽大黄A大片片视频| 美女被啪羞羞视频网站| 舟曲县| 欧美亚洲国产一区| 亚洲国产精品精华液2区45| 人妻无码久久中文字幕鲁一鲁| 91桃色在线看片| 韩国色图| 成品电影5668的功能入口介绍| 国产 丝袜 另类 精品 综合| 野花高清完整版在线观看免费5| 久久福利资源网站免费看| xxxx中国hd| 《甜性涩爱》未删减| 伊在人亚洲香蕉精品播放| labstillalive所有侵犯画面| 无人区乱码1区2区3区免费| 铃木一彻skill全部剧集网盘| 国产ts精品系列米兰| free×xx性欧美漫画| 国产丰满眼镜女在线观看| 国产精品亚洲四区在线观看| 国产精品无码欧美日韩AV红粉| 妻子的视频免费完整版高清观看 | 亚洲国产长腿丝袜AV在线| 郡体交乱之放荡娇妻Video|