连续两次执行 os/exec Command.Start()

标签 go exec system-calls

我正在尝试使用 Go 的 os/exec Command()模拟按键,有时我想使用此按键快速连续多次。我正在使用 exec.Command 调用 "xte" ,“key XF86AudioPlay”,它在 Linux 操作系统上暂停音乐。虽然 Command 可以 Start() Run() 没问题,但如果我再次尝试执行,我得到一个错误:

exec: already started

我试过在执行后立即使用 Process.Kill() 来释放它,但这首先会使执行无法进行。我从这里得到这个想法:Terminating a Process Started with os/exec in Golang

我的代码使用了一个 switch 并相应地调用了这个暂停函数,但我将简单地分享我编写的代码的基础,以 case 作为示例函数:

cmd := exec.Command("xte", "key XF86AudioPlay")
//...
func Pause() {
        err := cmd.Start() // or cmd.Run()
        if err != nil {
            fmt.Println(err)
        }
        err = cmd.Process.Kill()
        if err != nil {
            fmt.Printf("Failed to kill: %s", err)
        }
}

所以,回顾一下,我成功调用了一次,但在成功调用 Pause() 后,我从 cmd.Start()/Run() 读取:exec: already started

我也尝试过降低,即使用系统调用,但我遇到了一些麻烦。我试过:

args[0] = "xte"
args[1] = "key"
args[2] = "XF86AudioPlay"
//... Pause():
            err := syscall.Exec("/bin", args, os.Environ())
        if err != nil {
            fmt.Println(err)
        }

这里我遇到了一个permission denied 错误,即使是作为 super 用户 (sudo) 运行也是如此。

我应该如何继续调用此 Command() 然后释放它以立即调用?还是我在 syscall 的正确轨道上?

编辑 因此,正如 Amd 和 Son Bui 所说,解决方案是在每次我打算调用它时创建 Command,基本上是将赋值 cmd := exec.Command ()我的 Pause() 方法中。

最佳答案

正如 type Cmd struct { 文档所说:

A Cmd cannot be reused after calling its Run, Output or CombinedOutput methods.


1- 像这样使用两个单独的 exec.Command
此外,您可能需要在运行之间进行一些延迟(模拟两个单独的击键):

package main

import (
    "fmt"
    "os"
    "os/exec"
    "time"
)

func main() {
    Pause()
    fmt.Println("Once")
    time.Sleep(100 * time.Millisecond)
    Pause()
    fmt.Println("Twice")
}
func Pause() {
    cmd := exec.Command("xte", "key XF86AudioPlay")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    err := cmd.Run()
    if err != nil {
        fmt.Println(err)
    }
}

2- 你可以运行一次:

你可以使用这样的东西(未经测试):

xte 'key XF86AudioPlay' 'key XF86AudioPlay'

并考虑向 xte 命令添加一个短暂的延迟(模拟两个单独的击键):

xte 'key XF86AudioPlay' 'usleep 100000' 'key XF86AudioPlay'

像这样:

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main() {
    Pause()
    fmt.Println("Once")
}
func Pause() {
    cmd := exec.Command("xte", `key XF86AudioPlay`, `usleep 100000`, `key XF86AudioPlay`)
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    err := cmd.Run()
    if err != nil {
        fmt.Println(err)
    }
}

参见:

https://askubuntu.com/questions/499926/why-do-these-xte-commands-work-in-terminal-but-not-when-bound-with-xbindkeys

http://manpages.ubuntu.com/manpages/wily/man1/xte.1.html

http://wiki.robotz.com/index.php/Linux_Tools_to_Remap_Keys_and_Mouse_Buttons


希望对您有所帮助。

关于连续两次执行 os/exec Command.Start(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39239499/

相关文章:

c - 写入文件时出现 I/O 问题

json - golang json 使用字段名称进行解码

go - 为了避免多个数据库调用在 Go 网络应用程序处理程序中相互阻塞,goroutines + syncGroup 是唯一的方法吗?

mysql - 指向 MySQL 查询抽象接口(interface)的指针片段

php - 为什么超时不工作linux服务器

c - sys_break 有什么作用?

go - 链接到第一篇/最后一篇文章

java - 使用来自 Java 的重定向标准输入和标准输出运行外部程序

linux - 使用 -exec cp 覆盖复制文件

linux - 对添加到内核的系统调用的 undefined reference