连续两次 os/exec Command.Start()
Go os/exec Command.Start() twice in a row
我正在尝试使用 Go 的 os/exec Command()
来 模拟按键 ,有时我我会想在 快速连续 中多次使用此按键。我正在使用 exec.Command
调用 "xte"、"key XF86AudioPlay",这会暂停 Linux OS 上的音乐。虽然 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
.
我也尝试过降低,即使用syscall
,但我运行遇到了一些麻烦。我试过了:
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
错误,甚至 运行 作为超级用户 (sudo)。
我应该如何继续调用此 Command()
然后释放它以立即 召回 ?还是我在 syscall
的正确轨道上?
编辑
所以 Amd 和 Son Bui 状态的解决方案是 create 每次我打算调用它时 Command
,基本上把赋值 cmd := exec.Command()
里面我的Pause()
方法。
正如 type Cmd struct {
文档所说:
A Cmd cannot be reused after calling its Run, Output or CombinedOutput
methods.
1- 像这样使用两个单独的 exec.Command
,
此外,您可能需要 运行s 之间的一些延迟(模拟两个单独的击键):
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)
}
}
参见:
http://manpages.ubuntu.com/manpages/wily/man1/xte.1.html
http://wiki.robotz.com/index.php/Linux_Tools_to_Remap_Keys_and_Mouse_Buttons
希望对您有所帮助。
从源代码看:
cmd 结构:(https://golang.org/src/os/exec/exec.go 第 99 行)
// Process is the underlying process, once started.
Process *os.Process
并且在Start
函数中(https://golang.org/src/os/exec/exec.go第327行)
:
if c.Process != nil {
return errors.New("exec: already started")
}
所以你只能使用cmd.Start一次。如果你想多次使用,你可以一次创建新的 Cmd 或 运行 多个命令,例如:
cmd := exec.Command("/bin/sh", "-c", "command1; command2; command3; ...")
我正在尝试使用 Go 的 os/exec Command()
来 模拟按键 ,有时我我会想在 快速连续 中多次使用此按键。我正在使用 exec.Command
调用 "xte"、"key XF86AudioPlay",这会暂停 Linux OS 上的音乐。虽然 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
.
我也尝试过降低,即使用syscall
,但我运行遇到了一些麻烦。我试过了:
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
错误,甚至 运行 作为超级用户 (sudo)。
我应该如何继续调用此 Command()
然后释放它以立即 召回 ?还是我在 syscall
的正确轨道上?
编辑
所以 Amd 和 Son Bui 状态的解决方案是 create 每次我打算调用它时 Command
,基本上把赋值 cmd := exec.Command()
里面我的Pause()
方法。
正如 type Cmd struct {
文档所说:
A Cmd cannot be reused after calling its Run, Output or CombinedOutput methods.
1- 像这样使用两个单独的 exec.Command
,
此外,您可能需要 运行s 之间的一些延迟(模拟两个单独的击键):
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)
}
}
参见:
http://manpages.ubuntu.com/manpages/wily/man1/xte.1.html
http://wiki.robotz.com/index.php/Linux_Tools_to_Remap_Keys_and_Mouse_Buttons
希望对您有所帮助。
从源代码看:
cmd 结构:(https://golang.org/src/os/exec/exec.go 第 99 行)
// Process is the underlying process, once started.
Process *os.Process
并且在Start
函数中(https://golang.org/src/os/exec/exec.go第327行)
:
if c.Process != nil {
return errors.New("exec: already started")
}
所以你只能使用cmd.Start一次。如果你想多次使用,你可以一次创建新的 Cmd 或 运行 多个命令,例如:
cmd := exec.Command("/bin/sh", "-c", "command1; command2; command3; ...")