hookenz
hookenz

Reputation: 38997

How to connect xml decoder to stdoutPipe() of go exec

I'm having some trouble linking things up here. What am I doing incorrectly?

package main

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

func checkError(err error) {
    if err != nil {
        log.Fatalf("Error: %s", err)
    }
}

func metrics() {
    cmd := exec.Command(
        "nvidia-smi",
        "--query",
        "--xml-format")

    out, err := cmd.StdoutPipe()
    checkError(err)

    cmd.Start()

    defer cmd.Wait()

    go func() {
        var data interface{}
        dec := xml.NewDecoder(out)
        dec.Decode(&data)
        fmt.Printf("Data: %+v\n", data)
    }()

    //go io.Copy(os.Stdout, out)
}

func main() {
    metrics()
}

Result after running program is: Data:

Upvotes: 1

Views: 163

Answers (1)

eugenioy
eugenioy

Reputation: 12403

Things seem to be "linked" correctly.

Problem is likely to be here:

var data interface{}

You then do:

dec.Decode(&data)

But that won't work.

You need to pass in a struct that can actually be used to decode the fields in the XML that the nvidia-smi command returns.

Find below a modified example (replacing your nvidia-smi for an echo command to make it return a sample XML).

You should adjust the struct to be able to map to the actual XML you'll receive.

By the way:

  • You should check the error returned by decode just in case
  • I don't understand why you are decoding in a separate goroutine. I left it like that in the modified example, but it would work if you do it right in the same goroutine as well.

Example:

package main

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

func checkError(err error) {
    if err != nil {
        log.Fatalf("Error: %s", err)
    }
}

type Result struct {
    Value int `xml:"value"`
}

func metrics() {
    cmd := exec.Command(
        "echo", "-n",
        `<result><value>1</value></result>`)

    out, err := cmd.StdoutPipe()
    checkError(err)

    cmd.Start()

    defer cmd.Wait()

    go func() {
        var data Result
        dec := xml.NewDecoder(out)
        err = dec.Decode(&data)
        checkError(err)
        fmt.Printf("Data: %+v\n", data)
    }()

    //go io.Copy(os.Stdout, out)
}

func main() {
    metrics()
}

Upvotes: 2

Related Questions