How to run variable as shell script file - go

I need to run a variable as shell script file in golang. I tried like below code
package main
import (
"fmt"
"os/exec"
)
func main() {
var namespaceYaml string = `#!/bin/bash
docker verson`
out, err := exec.Command(namespaceYaml).Output()
fmt.Println(err, string(out))
}
But I cannot get any result. I cannot find where is the mistake.
Please anyone to fix this issue. Thanks in advance.

From official doc:
func Command(name string, arg ...string) *Cmd
Command returns the Cmd struct to execute the named program with the given arguments.
Try this:
package main
import (
"fmt"
"os/exec"
)
func main() {
out, err := exec.Command("docker", "version").Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Docker version is: %s\n", out)
}
Useful links for further details:
exec
examples
Note: make sure docker is installed on your machine.

Related

Go : Correctly running external program with arguments

Good evening,
I'm working on converting some tools written in python to Go in order to better understand it.
I need the program to call an external .exe with some arguments in order for it to correctly format some data. In the windows shell I can do C:\path_to_exe\file.exe arg1 arg2 "C:\path_to_output\output.txt"
I believe the correct method to do this in Go would be using exec.Command, but I'm not getting any...meaningful results.
out, err := exec.Command("cmd", "C:\\path\\tools\\util\\Utility.exe C:\\file_Location \"select * from TABLE\" C:\\output_path\\output.txt").Output()
fmt.Printf("\n", string(out))
if err != nil {
println(" Error running decomp ", err)
}
This appears to be running command, as the output I am receiving is:
%!(EXTRA string=Microsoft Windows [Version 10.0.22000.739]
(c) Microsoft Corporation. All rights reserved.
Process finished with the exit code 0
Just for giggles I tried breaking up the arguments, but the same result was achieved
out, err := exec.Command("cmd", exPath, utilPath, statement, textOutputPath+"test.txt").Output()
I'm expecting the executed program to run, parse the correct file based on the input, and output the specified txt file. I am left with no .txt file, and the go program runs much faster then the parsing should take.
There must be something I'm missing, could someone please provide some insight on the correct usage of exec.Command, because every example I can find appears to show that this should work.
Why are you spawning cmd.exe and having it run your utility.exe?
You can just spawn utility on its own.
For instance, suppose you have two binaries, hello and say-hello living in the same directory, compiled from
hello.go → hello:
package main
import (
"fmt"
"os"
)
func main() {
argv := os.Args[1:]
if len(argv) == 0 {
argv = []string{"world"}
}
for _, arg := range argv {
fmt.Printf("Hello, %s!\n", arg)
}
}
say-hello.go → say-hello:
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
process := exec.Command("./hello", os.Args[1:]...)
process.Stdin = os.Stdin
process.Stdout = os.Stdout
process.Stderr = os.Stderr
if err := process.Run(); err != nil {
fmt.Printf("Command failed with exit code %d\n", process.ProcessState.ExitCode())
fmt.Println(err)
}
}
You can then run the command:
$ ./say-hello Arawn Gywdion Sarah Hannah
And get back the expected
Hello, Arawn!
Hello, Gwydion!
Hello, Sarah!
Hello, Hannah!
It appears to be working correctly according to the outputs in your question.
A few suggestions:
It might be useful to print the command out as a string before running it, to check it's what you want.
You may find backticks useful when you have a string containing backslashes and quotation marks.
You have not supplied any format to fmt.Printf, hence the EXTRA in that output.
Using println to print the error will not stringify it, so use fmt.Printf for that too.
package main
import (
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("cmd", `C:\path\tools\util\Utility.exe C:\file_Location "select * from TABLE" C:\output_path\output.txt`)
fmt.Printf("%s\n", cmd.String())
out, err := cmd.Output()
fmt.Printf("%s\n", string(out))
if err != nil {
fmt.Printf(" Error running decomp %s\n", err)
}
}
Playground: https://go.dev/play/p/3t0aOxAZRtU

exec : hangman.go Executable file not found in $PATH

i have problem trying to run my hangman game (hangman.go) into an other program (server.go)
package main
import (
"log"
"os/exec"
)
func main() {
cmd := exec.Command("hangman.go")
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
}
Ive tried to build a hangman.exe too but i still have the same error when i run server.go
2021/12/03 10:42:19 exec: "hangman.go": executable file not found in $PATH
exit status 1
You have two problems:
You cannot execute a *.go source file, you must use your compiled hangman.exe.
If your command "contains no path separators" then exec.Command() looks for the command in your PATH environment variable, it is not in any of those directories so it is not run. You need to specify a relative or fully qualified path to the file, if it is in the current working directory this can just be .\hangman.exe (or ./hangman on unix like systems):
package main
import (
"log"
"os/exec"
)
func main() {
cmd := exec.Command(".\hangman.exe")
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
}

GO making multiple goroutines that use nmap

I'm trying to use Go's concurrency to create a script that runs multiple nmap scans with different options but whenever I try to run the program it exits after the 1st nmap scan completes. Is there a way to prevent this?
here's the code:
package main
import (
"syscall"
"os"
"os/exec"
"fmt"
)
func main(){
args1 := []string{"nmap","-sS","127.0.0.1"}
args2 := []string{"nmap","-sN","127.0.0.1"}
args3 := []string{"nmap","-sV","127.0.0.1"}
go funccmd(args1)
go funccmd(args2)
go funccmd(args3)
fmt.Scanln()
}
func funccmd(args []string){
env := os.Environ()
cmdpath, runErr := exec.LookPath("/usr/bin/nmap")
if runErr != nil {
panic(runErr)
}
execErr := syscall.Exec(cmdpath, args, env)
if execErr != nil {
panic(execErr)
}
}
Do not use syscall.Exec. That calls execve which replaces the current program with nmap. Use exec.Cmd to execute nmap instead.

go generate stdout piped to gofmt to file

What is the syntax so go generate can pipe stdout from go run to gofmt and ultimately to a file? Below is simple example of what I have tried. Its in the file main.go. I can't find any examples of this after searching. Thank you.
Edit: ultimately I would like to use go generate and have it write a formatted file.
//go:generate go run main.go | go fmt > foo.go
package main
import "fmt"
const content = `
package main
func foo() string {return "Foo"}
`
func main() {
fmt.Print(content)
}
Use the format package directly instead of running a shell:
//go:generate go run main.go
package main
import (
"go/format"
"io/ioutil"
"log"
)
const content = `
package main
func foo() string {return "Foo"}
`
func main() {
formattedContent, err := format.Source([]byte(content))
if err != nil {
log.Fatal(err)
}
err = ioutil.WriteFile("foo.go", formattedContent, 0666)
if err != nil {
log.Fatal(err)
}
}
Avoid using a shell like bash because the shell may not be available on all systems where the Go tools run.

exec with double quoted argument

I want to execute find Windows command using exec package, but windows is doing some weird escaping.
I have something like:
out, err := exec.Command("find", `"SomeText"`).Output()
but this is throwing error because Windows is converting this to
find /SomeText"
Does anyone know why? How I can execute find on windows using exec package?
Thanks!
OK, it's a bit more complicated than you might have expected, but there is a solution:
package main
import (
"fmt"
"os/exec"
"syscall"
)
func main() {
cmd := exec.Command(`find`)
cmd.SysProcAttr = &syscall.SysProcAttr{}
cmd.SysProcAttr.CmdLine = `find "SomeText" test.txt`
out, err := cmd.Output()
fmt.Printf("%s\n", out)
fmt.Printf("%v\n", err)
}
Unfortunately, although support for this was added in 2011, it doesn't appear to have made it into the documentation yet. (Although perhaps I just don't know where to look.)
FYI, running:
package main
import (
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("find", `"SomeText"`)
fmt.Printf("Path: %q, args[1]: %q\n", cmd.Path, cmd.Args[1])
}
playground
On unix gives:
Path: "/usr/bin/find", args[1]: "\"SomeText\""
And cross compiled to Windows and run on Win7 gives:
Path: "C:\\Windows\\system32\\find.exe", args[1]: "\"SomeText\""
Both look correct to me.
Adding out, err := cmd.Output() to the Windows cross-compile gives the following for fmt.Printf("%#v\%v\n", err, err):
&exec.ExitError{ProcessState:(*os.ProcessState)(0xc0820046a0)}
exit status 1
But I imagine that's just because find fails to find anything.

Resources