exec.Command call java cli - go

How can I make the exec.Command command call a command from another file?
func main() {
fmt.Println("Iniciando...")
command := exec.Command("java -version")
command.Dir = "."
output, err := command.Output()
if err != nil {
fmt.Println("Erro: ", err)
}
fmt.Printf("%s", output)
}
Erro: exec: "java -version": executable file not found in $PATH

Each argument needs to be in its own separate string. Try exec.Command("java", "-version")

Related

Golang exec command chmod returning error

Familiarizing myself with Golang here and i am trying to execute shell commands, i need to chmod for any .pem file so i decided to use the wildcard *
func main() {
cmd := exec.Command( "chmod", "400", "*.pem" )
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stdout
if err := cmd.Run(); err != nil {
fmt.Println( "Error:", err )
}
I keep get this error while executing:
chmod: cannot access '*.pem': No such file or directory
Error: exit status 1
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.
So here, * will not be expanded. As a workaround, you should use next to make it work:
cmd := exec.Command("sh", "-c", "chmod 400 *.pem" )
Here is another approach to change a file permission using os package
filepath.WalkDir(".", func(filePath string, f fs.DirEntry, e error) error {
if e != nil {
log.Fatal(e)
}
if filepath.Ext(f.Name()) == ".pem" {
err := os.Chmod(filePath, 0400)
if err != nil {
log.Fatal(err)
}
fmt.Println(fmt.Sprintf("Successfully changed file permission, file: %s", filePath))
}
return nil
})
Complete code can be found at https://play.golang.org/p/x_3WsYg4t52

How to create an os.exec Command struct from a string with spaces

I want my method to receive a command to exec as a string. If the input string has spaces, how do I split it into cmd, args for os.exec?
The documentation says to create my Exec.Cmd struct like
cmd := exec.Command("tr", "a-z", "A-Z")
This works fine:
a := string("ifconfig")
cmd := exec.Command(a)
output, err := cmd.CombinedOutput()
fmt.Println(output) // prints ifconfig output
This fails:
a := string("ifconfig -a")
cmd := exec.Command(a)
output, err := cmd.CombinedOutput()
fmt.Println(output) // 'ifconfig -a' not found
I tried strings.Split(a), but receive an error message: cannot use (type []string) as type string in argument to exec.Command
args := strings.Fields("ifconfig -a ")
exec.Command(args[0], args[1:]...)
strings.Fields() splits on whitespace, and returns a slice
... expands slice into individual string arguments
Please, check out:
https://golang.org/pkg/os/exec/#example_Cmd_CombinedOutput
Your code fails because exec.Command expects command arguments to be separated from actual command name.
strings.Split signature (https://golang.org/pkg/strings/#Split):
func Split(s, sep string) []string
What you tried to achieve:
command := strings.Split("ifconfig -a", " ")
if len(command) < 2 {
// TODO: handle error
}
cmd := exec.Command(command[0], command[1:]...)
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
// TODO: handle error more gracefully
log.Fatal(err)
}
// do something with output
fmt.Printf("%s\n", stdoutStderr)
I like to use the exec.Command() like this:
args=[]string{
"-l",
fmt.Sprintf(xxxxx),
}
cmd := exec.Command("ls", args...)
cmd.Stdout = os.Stderr
cmd.Stderr = os.Stderr

Start detached command with redirect to file

I'm trying to start a command in a detached process so that it can continue after go program exits. I need to redirect the output of the command to a file.
What I need is something like this:
func main() {
command := exec.Command("/tmp/test.sh", ">", "/tmp/out")
if err := command.Start(); err != nil {
fmt.Fprintln(os.Stderr, "Command failed.", err)
os.Exit(1)
}
fmt.Println("Process ID:", command.Process.Pid)
}
Obviously such redirect doesn't work. As I immediately exit from the program after starting the long running command, I cannot open a file and bind it to the Stdout.
Is there any way to achieve such a redirect?
You may start a shell which executes your command / app, and you may redirect its output to a file. The shell will continue to run and execute your script / app even if your Go app exits.
Example:
cmd := exec.Command("sh", "-c", "/tmp/test.sh > /tmp/out")
if err := cmd.Start(); err != nil {
panic(err)
}
fmt.Println("Process ID:", cmd.Process.Pid)
Test it with this simple Go app (replace /tmp/test.sh with the name of the executable binary you compile this into):
package main
import ("fmt"; "time")
func main() {
for i := 0; i < 10; i++ {
fmt.Printf("%d.: %v\n", i, time.Now())
time.Sleep(time.Second)
}
}
This app simply prints a line to the standard output once every second. You can see how the output file is being written e.g. with tail -f /tmp/out.
Note that you may use other shells to execute your scripts to your liking (and to what the test.sh script dictates).
For example to use bash:
cmd := exec.Command("/bin/bash", "-c", "/tmp/test.sh > /tmp/out")
// rest is unchanged
Note that the command to be executed by the shell is passed as a single string argument, and it is not broken down into multiple as you would do it if you were to execute it directly in the command prompt.
Maybe you can try to use this: https://stackoverflow.com/a/28918814/2728768
Opening a file (and os.File implements io.Writer), and then passing it as the command.Stdout could do the trick:
func main() {
command := exec.Command("./tmp/test.sh")
f, err := os.OpenFile("/tmp/out", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
fmt.Printf("error opening file: %v", err)
}
defer f.Close()
// On this line you're going to redirect the output to a file
command.Stdout = f
if err := command.Start(); err != nil {
fmt.Fprintln(os.Stderr, "Command failed.", err)
os.Exit(1)
}
fmt.Println("Process ID:", command.Process.Pid)
}
Not sure this could be a viable solution for your case. I've tried it locally and it seems working... remember that your user should be able to create/update the file.

Run Multiple Exec Commands in the same shell golang

I'm having trouble figuring out how to run multiple commands using the os/exec package. I've trolled the net and stackoverflow and haven't found anything that works for me case. Here's my source:
package main
import (
_ "bufio"
_ "bytes"
_ "errors"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
)
func main() {
ffmpegFolderName := "ffmpeg-2.8.4"
path, err := filepath.Abs("")
if err != nil {
fmt.Println("Error locating absulte file paths")
os.Exit(1)
}
folderPath := filepath.Join(path, ffmpegFolderName)
_, err2 := folderExists(folderPath)
if err2 != nil {
fmt.Println("The folder: %s either does not exist or is not in the same directory as make.go", folderPath)
os.Exit(1)
}
cd := exec.Command("cd", folderPath)
config := exec.Command("./configure", "--disable-yasm")
build := exec.Command("make")
cd_err := cd.Start()
if cd_err != nil {
log.Fatal(cd_err)
}
log.Printf("Waiting for command to finish...")
cd_err = cd.Wait()
log.Printf("Command finished with error: %v", cd_err)
start_err := config.Start()
if start_err != nil {
log.Fatal(start_err)
}
log.Printf("Waiting for command to finish...")
start_err = config.Wait()
log.Printf("Command finished with error: %v", start_err)
build_err := build.Start()
if build_err != nil {
log.Fatal(build_err)
}
log.Printf("Waiting for command to finish...")
build_err = build.Wait()
log.Printf("Command finished with error: %v", build_err)
}
func folderExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return true, err
}
I want to the command like I would from terminal. cd path; ./configure; make
So I need run each command in order and wait for the last command to finish before moving on. With my current version of the code it currently says that ./configure: no such file or directory I assume that is because cd path executes and in a new shell ./configure executes, instead of being in the same directory from the previous command. Any ideas?
UPDATE I solved the issue by changing the working directory and then executing the ./configure and make command
err = os.Chdir(folderPath)
if err != nil {
fmt.Println("File Path Could not be changed")
os.Exit(1)
}
Still now i'm curious to know if there is a way to execute commands in the same shell.
If you want to run multiple commands within a single shell instance, you will need to invoke the shell with something like this:
cmd := exec.Command("/bin/sh", "-c", "command1; command2; command3; ...")
err := cmd.Run()
This will get the shell to interpret the given commands. It will also let you execute shell builtins like cd. Note that this can be non-trivial to substitute in user data to these commands in a safe way.
If instead you just want to run a command in a particular directory, you can do that without the shell. You can set the current working directory to execute the command like so:
config := exec.Command("./configure", "--disable-yasm")
config.Dir = folderPath
build := exec.Command("make")
build.Dir = folderPath
... and continue on like you were before.

Go: Run External Python script

I have tried following the Go Docs in order to call a python script which just outputs "Hello" from GO, but have failed until now.
exec.Command("script.py")
or I've also tried calling a shell script which simply calls the python script, but also failed:
exec.Command("job.sh")
Any ideas how would I achieve this?
EDIT
I solved following the suggestion in the comments and adding the full path to exec.Command().
Did you try adding Run() or Output(), as in:
exec.Command("script.py").Run()
exec.Command("job.sh").Run()
You can see it used in "How to execute a simple Windows DOS command in Golang?" (for Windows, but the same idea applies for Unix)
c := exec.Command("job.sh")
if err := c.Run(); err != nil {
fmt.Println("Error: ", err)
}
Or, with Output() as in "Exec a shell command in Go":
cmd := exec.Command("job.sh")
out, err := cmd.Output()
if err != nil {
println(err.Error())
return
}
fmt.Println(string(out))
First of all do not forget to make your python script executable (permissions and #!/usr/local/bin/python at the beginning).
After this you can just run something similar to this (notice that it will report you errors and standard output).
package main
import (
"log"
"os"
"os/exec"
)
func main() {
cmd := exec.Command("script.py")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
log.Println(cmd.Run())
}
Below worked for me on Windows 10
python := path.Clean(strings.Join([]string{os.Getenv("userprofile"), "Anaconda3", "python.exe"}, "/"))
script := "my_script.py"
cmd := exec.Command("cmd", python, script)
out, err := cmd.Output()
fmt.Println(string(out))
if err != nil {
log.Fatal(err)
}

Resources