Devendra Verma
Devendra Verma

Reputation: 1015

How to get the output of a command

I am calling a python script from Go code:

package main
import (
    "os/exec"
    "os"
    "fmt"
    "time"
    "encoding/json"
)

func main() {
    cmd := exec.Command("python","/home/devendra/Desktop/sync/blur_multithread.py","http://4.imimg.com/data4/TP/ED/NSDMERP-28759633/audiovideojocks.png")
    var logs=make(map[string]interface{})
    logs["tes"]=os.Stdout
    _ = cmd.Run()   
    WriteLogs(logs)//Writelog is my function which logs everything in a file
}

func WriteLogs(logs map[string]interface{}){
  currentTime := time.Now().Local()
  jsonLog, err := json.Marshal(logs)
  if err != nil {
    fmt.Println(err.Error())
  }

  jsonLogString := string(jsonLog[:len(jsonLog)])
  logfile := "/home/devendra/ImageServiceLogs/"+ "ImageServiceLogs_" + currentTime.Format("2006-01-02") + ".txt"
  if logfile == "" {
    fmt.Println("Could not find logfile in configuration ...!!!")
  } else {

    jsonLogFile, err := os.OpenFile(logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
    defer jsonLogFile.Close()
    if err != nil {
      fmt.Println(err.Error())
    }

    jsonLogFile.WriteString(jsonLogString + "\n")
  }
}

But in the logs value of tes field is null while my python script is giving me output. How to get the output of python script in my code?

Upvotes: 1

Views: 4226

Answers (1)

user4466350
user4466350

Reputation:

As per official documentation examples, exec.Cmd.Ouput() ([]byte, error) will give you the sdout of the command after it has finished running.

https://golang.org/pkg/os/exec/#Cmd.Output

package main

import (
    "fmt"
    "log"
    "os/exec"
)

func main() {
    out, err := exec.Command("date").Output()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("The date is %s\n", out)
}

To receive both stdout and stderr of the process, writer should use exec.Cmd.CombinedOutput https://golang.org/pkg/os/exec/#Cmd.CombinedOutput

If someone wants to receive the command output in real time to its terminal, then the writer should set exec.Cmd.Stdout and exec.Cmd.Stderr properties to, respectively, os.Stdout and os.Stderr and invoke the exec.Cmd.Run() error method.

https://golang.org/pkg/os/exec/#Cmd https://golang.org/pkg/os/exec/#Cmd.Run

package main

import (
    "fmt"
    "log"
    "os"
    "os/exec"
)

func main() {
    cmd := exec.Command("date")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    err := cmd.Run()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("The date is %s\n", out)
}

To forward outputs and capture it at the same time, writer should seek help of the io package to use an io.MultiWriter

https://golang.org/pkg/io/#MultiWriter

package main

import (
    "fmt"
    "io"
    "log"
    "os"
    "os/exec"
)

func main() {
    stdout := new(bytes.Bufer)
    stderr := new(bytes.Bufer)
    cmd := exec.Command("date")
    cmd.Stdout = io.MultiWriter(os.Stdout, stdout)
    cmd.Stderr = io.MultiWriter(os.Stderr, stderr)
    err := cmd.Run()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("The date is %s\n", out)
}

Alternatively, you can make use of the exec.Cmd.{Stdout,Stderr}Pipe() see the official documentation examples https://golang.org/pkg/os/exec/#Cmd.StdoutPipe

Upvotes: 2

Related Questions