在终端中运行的命令不适用于 go exec.Command
Command that works in terminal doesn't work with go exec.Command
我正在尝试从 go 脚本附加到 go-ethereum 节点:
accountInfo:= fmt.Sprintf("attach %v --exec 'eth.getBalance(eth.accounts[0])'", connect)
//x, err := exec.Command("geth", accountInfo).Output() // returns 'Fatal: Unable to attach to remote geth: no known transport for URL scheme "c"'
x, err := exec.Command("geth", accountInfo).Output() // returns "invalid command: "attach ws://127.0.0.1:8101...." <--- rest of the metaData string
if err != nil {
fmt.Println(err)
}
这个命令在终端中运行得很好,但是当运行这样时它一直告诉我它是无效的。这让我发疯。
Unlike the "system" library call from C and other languages, the os/exec package intentionally does not invoke the system shell and does not expand any glob patterns or handle other expansions, pipelines, or redirections typically done by shells.
由于 exec.Command()
的 arg ...string
参数没有被 shell 处理,每个参数都完全按照指定的方式传递给命令。在您的情况下,metaData
的全部内容作为单个参数提供给 geth
。
您应该改为创建一段字符串,每个字符串包含一个参数。然后使用 ...
符号将该切片作为 arg
参数提供。
下面是一个使用 uname
命令进行演示的示例:
package main
import (
"fmt"
"os/exec"
)
func main() {
command := "uname"
argsString := "--kernel-name --machine"
argsSlice := []string{"--kernel-name", "--machine"}
// Equivalent command:
// $ uname "--kernel-name --machine"
fmt.Println("exec.Command(command, argsString)")
stringOutput, err := exec.Command(command, argsString).CombinedOutput()
if err != nil {
fmt.Printf("Failed: %s\n", err)
}
fmt.Printf("Output:\n%s\n", stringOutput)
// Equivalent command:
// $ uname --kernel-name --machine
fmt.Println("exec.Command(command, argsSlice)")
sliceOutput, err := exec.Command(command, argsSlice...).CombinedOutput()
if err != nil {
fmt.Printf("Failed: %s", err)
}
fmt.Printf("Output:\n%s\n", sliceOutput)
}
这是输出:
$ go run main.go
exec.Command(command, argsString)
Failed: exit status 1
Output:
uname: unrecognized option '--kernel-name --machine'
Try 'uname --help' for more information.
exec.Command(command, argsSlice)
Output:
Linux x86_64
我正在尝试从 go 脚本附加到 go-ethereum 节点:
accountInfo:= fmt.Sprintf("attach %v --exec 'eth.getBalance(eth.accounts[0])'", connect)
//x, err := exec.Command("geth", accountInfo).Output() // returns 'Fatal: Unable to attach to remote geth: no known transport for URL scheme "c"'
x, err := exec.Command("geth", accountInfo).Output() // returns "invalid command: "attach ws://127.0.0.1:8101...." <--- rest of the metaData string
if err != nil {
fmt.Println(err)
}
这个命令在终端中运行得很好,但是当运行这样时它一直告诉我它是无效的。这让我发疯。
Unlike the "system" library call from C and other languages, the os/exec package intentionally does not invoke the system shell and does not expand any glob patterns or handle other expansions, pipelines, or redirections typically done by shells.
由于 exec.Command()
的 arg ...string
参数没有被 shell 处理,每个参数都完全按照指定的方式传递给命令。在您的情况下,metaData
的全部内容作为单个参数提供给 geth
。
您应该改为创建一段字符串,每个字符串包含一个参数。然后使用 ...
符号将该切片作为 arg
参数提供。
下面是一个使用 uname
命令进行演示的示例:
package main
import (
"fmt"
"os/exec"
)
func main() {
command := "uname"
argsString := "--kernel-name --machine"
argsSlice := []string{"--kernel-name", "--machine"}
// Equivalent command:
// $ uname "--kernel-name --machine"
fmt.Println("exec.Command(command, argsString)")
stringOutput, err := exec.Command(command, argsString).CombinedOutput()
if err != nil {
fmt.Printf("Failed: %s\n", err)
}
fmt.Printf("Output:\n%s\n", stringOutput)
// Equivalent command:
// $ uname --kernel-name --machine
fmt.Println("exec.Command(command, argsSlice)")
sliceOutput, err := exec.Command(command, argsSlice...).CombinedOutput()
if err != nil {
fmt.Printf("Failed: %s", err)
}
fmt.Printf("Output:\n%s\n", sliceOutput)
}
这是输出:
$ go run main.go
exec.Command(command, argsString)
Failed: exit status 1
Output:
uname: unrecognized option '--kernel-name --machine'
Try 'uname --help' for more information.
exec.Command(command, argsSlice)
Output:
Linux x86_64