如何使用Go启动,监视和终止进程

时间:2017-11-01 13:06:26

标签: go

我正在Go中编写一个程序,它应该打开一个可移植的浏览器到一个给定的页面并监视它,这样如果浏览器关闭,它应该自动重新打开。此程序退出时也应关闭浏览器。

到目前为止,我已经设法在用户关闭浏览器时重新打开浏览器,但是我无法关闭它。

这是我的代码:

package browser

import (
    "fmt"
    "os/exec"

    log "github.com/sirupsen/logrus"
)

type iBrowserHandler interface {
    Start(processListener chan bool) error
    Stop() error
    KillProcess() error
}

type browserHandler struct {
    cmd            *exec.Cmd
    pathToChromium string
    pdvEndpoint    string
}

func newBrowserHandler(pathToChromium string, pdvEndpoint string) iBrowserHandler {
    b := &browserHandler{}
    b.pathToChromium = pathToChromium
    b.pdvEndpoint = pdvEndpoint

    return b
}

func (b *browserHandler) Start(processListener chan bool) error {
    endpoint := fmt.Sprintf("--app=%s", b.pdvEndpoint)

    b.cmd = exec.Command(b.pathToChromium, endpoint, "--kiosk")
    err := b.cmd.Run()
    if err != nil {
        log.WithError(err).Error("Error with the browser process")
        processListener <- false
    } else {
        processListener <- true
    }

    return err
}

func (b *browserHandler) Stop() error {
    err := b.cmd.Process.Release()
    if err != nil {
        log.WithError(err).Fatal("Error shutting down chromium")
    }

    return err
}

func (b *browserHandler) KillProcess() error {
    err := b.cmd.Process.Kill()
    if err != nil {
        log.WithError(err).Fatal("Error killing chromium process")
    }

    return err
}

这是我用来启动浏览器的功能:

var handler iBrowserHandler

func init() {
    var pathToChromium string
    var c = config.GetInstance()
    var os = runtime.GOOS

    if os == "windows" {
        pathToChromium = "chromium-browser\\ChromiumPortable.exe"
    } else {
        pathToChromium = "chrome"
    }

    handler = newBrowserHandler(pathToChromium, c.GetConfig().PDVUrl)
}

func StartBrowser(done chan bool) {
    browserProcessListener := make(chan bool)
    defer close(browserProcessListener)
    go handler.Start(browserProcessListener)

    var tryReopenBrowser = true
    for {
        select {
        case <-browserProcessListener:
            if tryReopenBrowser {
                log.Warn("Browser process is stopped. Attempting to restart")
                go handler.Start(browserProcessListener)
            } else {
                log.Warn("Browser process is stopped. Will not attempt to restart")
            }

        case <-done:
            log.Info("Shutting down browser")
            tryReopenBrowser = false
            handler.KillProcess()
            return

        default:
        }
    }
}

当程序启动时,我调用StartBrowser()函数。浏览器启动后,它会一直监听它是否已关闭(cmd.Run()函数会阻止线程的执行,直到进程完成)。

如果浏览器已关闭,则我的程序会尝试重新打开它。

如果程序收到停止信号,它会尝试关闭浏览器。我尝试使用cmd.Process.Release()cmd.Process.Kill()命令,但两者都不关闭浏览器。还有其他办法吗?

2 个答案:

答案 0 :(得分:1)

我找到了答案!问题是Go cmd.Process.Kill()命令只停止父进程,而不是子进程,所以我不得不通过操作系统手动终止这些进程。

由于我在Windows上,KillProcess()方法现在看起来像这样:

func (b *browserHandler) KillProcess() error {
    log.Info("Killing browser process")
    kill := exec.Command("taskkill", "/T", "/F", "/PID", strconv.Itoa(b.cmd.Process.Pid))
    err := kill.Run()
    if err != nil {
        log.WithError(err).Error("Error killing chromium process")
    }
    log.Info("Browser process was killed")

    return err
}

致谢:thread可以为WindowsUnix系统提供答案。

答案 1 :(得分:0)

而不是cmd.Run()使用cmd.Start() see this