Home > Back-end >  Best way to bind shell output to a struct in Go?
Best way to bind shell output to a struct in Go?

Time:09-21

I have some chips running on some hardware and I want to bind the output of a shell command to a struct to do reporting/logging on.

Num decoders: 2
INDEX LOAD MODEL_LOAD INST MEM  SHARE_MEM P2P_MEM DEVICE         NAMESPACE
1     2    3          4    50    600         700       /dev/nvme0     /dev/nvme0n1
1a     2b    3c          4c    5d    6e         7f       /dev/nvme1     /dev/nvme1n1
Num encoders: 2
INDEX LOAD MODEL_LOAD INST MEM  SHARE_MEM P2P_MEM DEVICE         NAMESPACE
2a     2b    2c          3    0    0         0       /dev/nvme0     /dev/nvme0n1
1     0    0          0    0    0         0       /dev/nvme1     /dev/nvme1n1
Num scalers: 2
INDEX LOAD MODEL_LOAD INST MEM  SHARE_MEM P2P_MEM DEVICE         NAMESPACE
0     0    0          0    0    0         0       /dev/nvme0     /dev/nvme0n1
1     0    0          0    0    0         0       /dev/nvme1     /dev/nvme1n1
**************************************************

Attempt

cat out.txt | grep -i "Num $1" -A 3 | grep -i nvme | tr -s ' ' | cut -d' ' -f1-7

This actually isn't too bad, I can pass in an arg like decoders or encoders and get the load metrics for each chip. However, I'm curious now the best way to bind this to a struct in Go.

Currently, what I can do is code up a custom deserializer from something like:

func main() {
    out, err := exec.Command("/bin/sh", "metrics.sh", "encoders").Output()
    if err != nil {
        fmt.Println(err)
        log.Fatal(err)
    }

    fmt.Println(string(out))
}

But I feel like there has to be a better way, like outputting as JSON and binding to a struct or something.

CodePudding user response:

I would convert your input to CSV; the Go language have a CSV encoder/decoder in its standard library:

awk -v OFS=',' '
    /^Num/ {
        count = $3
        type = $2

        getline
        if ( !header   ) {
            $(NF 1) = "ID"
            print
        }
        for ( id = 1; id <= count; id   ) {
            getline
            $(NF 1) = type id
            print
        }
    }
' file.txt

Warning: the code doesn't CSV-escape the fields

INDEX,LOAD,MODEL_LOAD,INST,MEM,SHARE_MEM,P2P_MEM,DEVICE,NAMESPACE,ID
1,2,3,4,50,600,700,/dev/nvme0,/dev/nvme0n1,decoders:1
1a,2b,3c,4c,5d,6e,7f,/dev/nvme1,/dev/nvme1n1,decoders:2
2a,2b,2c,3,0,0,0,/dev/nvme0,/dev/nvme0n1,encoders:1
1,0,0,0,0,0,0,/dev/nvme1,/dev/nvme1n1,encoders:2
0,0,0,0,0,0,0,/dev/nvme0,/dev/nvme0n1,scalers:1
1,0,0,0,0,0,0,/dev/nvme1,/dev/nvme1n1,scalers:2

remark: the parsing and conversion could be written in GO

  • Related