dongying9756 2016-08-31 01:44
浏览 216
已采纳

连续两次进入os / exec Command.Start()

I'm trying to use Go's os/exec Command() to simulate a keypress, and sometimes I'll want to use this keypress multiple times in quick succession. I'm using exec.Command to call "xte", "key XF86AudioPlay", which pauses music on a Linux OS. While the Command can Start() or Run() no problem, if I try to execute again, I get an error:

exec: already started

I've tried using Process.Kill() immediately after the execution, in order to free it up, but this will make the execution not work in the first place. I got this idea from here: Terminating a Process Started with os/exec in Golang

My code uses a switch and calls this pause function accordingly, but I'll simply share the basis of the code I wrote, with the case as an example function:

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)
        }
}

So, to recap, I'm successful at calling it one time, but upon success calls to Pause(), I get the error from cmd.Start()/Run() which read: exec: already started.

I also tried going lower, that is, using syscall, but I ran into some trouble. I tried:

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

And here I got a permission denied error, even running as super user (sudo).

How should I proceed call this Command() and then free it up for immediate recall? Or am I on the right track with syscall?

Edit So the solution as both Amd and Son Bui state, was to create the Command everytime I intend to call it, basically putting the assignment cmd := exec.Command()inside my Pause() method.

  • 写回答

2条回答 默认 最新

  • douwen7516 2016-08-31 04:01
    关注

    As the type Cmd struct { Docs said:

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


    1- Use two separate exec.Command like this,
    Also you may need some delay between runs (simulating two separate keystrokes):

    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- You may run it once:

    You may use something like this (not tested):

    xte 'key XF86AudioPlay' 'key XF86AudioPlay'
    

    and consider adding a short delay to the xte command (simulating two separate keystrokes):

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

    Like this:

    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)
        }
    }
    

    See:

    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


    I hope this helps.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
  • ¥20 怎么在stm32门禁成品上增加查询记录功能
  • ¥15 Source insight编写代码后使用CCS5.2版本import之后,代码跳到注释行里面
  • ¥50 NT4.0系统 STOP:0X0000007B
  • ¥15 想问一下stata17中这段代码哪里有问题呀
  • ¥15 flink cdc无法实时同步mysql数据
  • ¥100 有人会搭建GPT-J-6B框架吗?有偿
  • ¥15 求差集那个函数有问题,有无佬可以解决