I'm trying to attach to a go-ethereum node from a go script:
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)
}
This command works perfectly fine in terminal but it keeps telling me it's invalid when running it like this. This is making me go nuts.
From the os/exec
documentation:
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.
Since the arg ...string
parameter of exec.Command()
isn't processed by a shell, each argument is handed to the command exactly as specified. In your case, the entire content of metaData
is provided to geth
as a single argument.
You should instead create a slice of strings, each containing a single argument. And then provide that slice as the arg
parameter using the ...
notation.
Here's an example demonstrating this, using the uname
command:
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)
}
And it's otuput:
$ 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