亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

golang 重新啟動的父進程沒有收到 SIGINT

golang 重新啟動的父進程沒有收到 SIGINT

Go
滄海一幻覺 2021-09-13 15:58:56
我正在編寫一個小程序來管理其他進程的重啟?;旧希斠粋€應用程序進程啟動(稱為 A)時,它會產生一個新進程(稱為 D),它有一個簡單的 HTTP 服務器。當 D 收到一個 http 請求時,它會殺死 A 并重新啟動它。問題是,A 現在不響應 CTRL-C,我不知道為什么??赡芎芎唵?,也可能我不太了解進程、終端和信號之間的關系。但它在具有相同標準輸入/標準輸出/標準錯誤的同一個終端中運行。下面是一個演示這種行為的完整程序。package mainimport (    "flag"    "log"    "net/http"    "os"    "os/exec"    "strconv"    "time")/*    Running this program starts an app (repeatdly prints 'hi') and spawns a new process running a simple HTTP server    When the server receives a request, it kills the other process and restarts it.    All three processes use the same stdin/stdout/stderr.    The restarted process does not respond to CTRL-C :(*/var serv = flag.Bool("serv", false, "run server")// run the app or run the serverfunc main() {    flag.Parse()    if *serv {        runServer()    } else {        runApp()    }}// handle request to server// url should contain pid of process to restartfunc handler(w http.ResponseWriter, r *http.Request) {    pid, err := strconv.Atoi(r.URL.Path[1:])    if err != nil {        log.Println("send a number...")    }    // find the process    proc, err := os.FindProcess(pid)    if err != nil {        log.Println("can't find proc", pid)        return    }    // terminate the process    log.Println("Terminating the process...")    err = proc.Signal(os.Interrupt)    if err != nil {        log.Println("failed to signal interupt")        return    }    // restart the process    cmd := exec.Command("restarter")    cmd.Stdin = os.Stdin    cmd.Stdout = os.Stdout    cmd.Stderr = os.Stderr    if err := cmd.Start(); err != nil {        log.Println("Failed to restart app")        return    }    log.Println("Process restarted")}該程序預計將被安裝。為方便起見,您可以使用go get github.com/ebuchman/restarter.運行程序restarter。它應該打印其進程 ID。然后curl http://localhost:9999/<procid>啟動重啟。新進程現在不會響應 CTRL-C。為什么?我錯過了什么?
查看完整描述

2 回答

?
慕蓋茨4494581

TA貢獻1850條經驗 獲得超11個贊

這與 Go 沒有任何關系。您從終端外殼啟動進程 A。進程 A 啟動進程 D(不確定 B 發生了什么,但沒關系)。進程 D 殺死進程 A?,F在你的 shell 看到它啟動的進程已經退出,所以 shell 準備聽另一個命令。進程 D 啟動進程 A 的另一個副本,但外殼對此一無所知。當您鍵入 ^C 時,shell 將處理它。如果你運行另一個程序,shell 會安排 ^C 去那個程序。shell 對進程 A 的副本一無所知,因此它永遠不會將 ^C 指向該進程。

查看完整回答
反對 回復 2021-09-13
?
人到中年有點甜

TA貢獻1895條經驗 獲得超7個贊

您可以查看兩個 http 服務器框架采用的方法來偵聽和攔截信號(包括SIGINT,甚至SIGTERM)


kornel661/nserv,其中ZeroDowntime-example/server.go使用通道:


// catch signals:

signals := make(chan os.Signal)

signal.Notify(signals, os.Interrupt, os.Kill)

zenazn/goji,其中graceful/signal.go使用類似的方法:


var stdSignals = []os.Signal{syscall.SIGINT, syscall.SIGTERM}

var sigchan = make(chan os.Signal, 1)

func init() {

    go waitForSignal()

}


查看完整回答
反對 回復 2021-09-13
  • 2 回答
  • 0 關注
  • 223 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號