检查 exec.Command 是否已退出

huangapple go评论70阅读模式
英文:

Checking if exec.Command exited

问题

我正在尝试编写一个程序,可以运行一个可执行文件,并在2秒内获取可执行文件是否退出。

files, _ := ioutil.ReadDir("Files/")

for _, f := range files {
    cmd := exec.Command(fmt.Sprint("Files/", f.Name()))
    cmd.Start()
    time.Sleep(2 * time.Second)
    if cmd.ProcessState.Exited() {
        fmt.Println("Exited")
    } else {
        fmt.Println("Not exited")
    }
}

这段代码会导致一个panic: runtime error: invalid memory address or nil pointer dereference错误,因为cmd.ProcessState还没有被设置(如果使用cmd.Run()则可以工作,但这违背了整个目的)。我尝试搜索其他方法,但找不到其他方法。

是否有其他方法可以实现这个功能?如果有,如何使用它?

英文:

I'm trying to make a program that can run an executable, and get if the executable exited in 2 seconds

files, _ := ioutil.ReadDir("Files/")

for _, f := range files {
	cmd := exec.Command(fmt.Sprint("Files/", f.Name()))
	cmd.Start()
	time.Sleep(2 * time.Second)
	if cmd.ProcessState.Exited() {
		fmt.Println("Exited")
	} else {
		fmt.Println("Not exited")
	}
}

This gives a panic: runtime error: invalid memory address or nil pointer dereference
Because it isn't set yet (If I use cmd.Run() it works but that defeats the whole purpose). I've tried searching for other ways to do it but I can't find any other ways.
Are there any other ways to do this? And if so, how do I use it?

答案1

得分: 2

始终检查错误。

来自 cmd.Start 文档

> 如果 Start 返回成功,c.Process 字段将被设置。

因此,请确保 cmd.Start 没有出错:

err := cmd.Start()
if err != nil {
    log.Fatalf("cmd.Start 错误: %v", err)
}

还有来自 exec.Cmd 文档

// ProcessState 包含有关已退出进程的信息,
// 在调用 Wait 或 Run 后可用。
ProcessState *os.ProcessState
// 包含已过滤或未导出的字段

因此,如果进程尚未完成,则 ProcessState 将为 nil - 因此您将得到一个运行时 panic。

英文:

Always check errors.

From cmd.Start docs

> If Start returns successfully, the c.Process field will be set.

so ensure cmd.Start is not erroring:

err := cmd.Start()
if err != nil {
    log.Fatalf("cmd.Start error: %v", err)
}

also from the exec.Cmd docs:

// ProcessState contains information about an exited process,
// available after a call to Wait or Run.
ProcessState *os.ProcessState
// contains filtered or unexported fields

so if the process has not completed then ProcessState will be nil - and thus you will get a runtime panic.

答案2

得分: 0

这对我有用:

files, _ := ioutil.ReadDir("Files/")

for _, f := range files {
	cmd := exec.Command(fmt.Sprint("Files/", f.Name()))
	cmd.Start()
	time.Sleep(2 * time.Second)

	check, _ := exec.Command("tasklist", "/FI", "PID eq "+fmt.Sprint(cmd.Process.Pid)).Output()
	output := string(check)
	if strings.HasPrefix(output, "INFO: No tasks are running") {
		fmt.Println("Exited")
	} else {
		fmt.Println("Still running")
	}
}
英文:

This worked for me:

files, _ := ioutil.ReadDir("Files/")

for _, f := range files {
	cmd := exec.Command(fmt.Sprint("Files/", f.Name()))
	cmd.Start()
	time.Sleep(2 * time.Second)

	check, _ := exec.Command("tasklist", "/FI", "PID eq "+fmt.Sprint(cmd.Process.Pid)).Output()
	output := string(check)
	if strings.HasPrefix(output, "INFO: No tasks are running") {
		fmt.Println("Exited")
	} else {
		fmt.Println("Still running")
	}
}

huangapple
  • 本文由 发表于 2022年1月5日 23:51:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/70595788.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定