Written by: Robert R. Russell on Friday, August 7, 2020.
Welcome to Part 4 of my series on my tool for backing up ZFS Snapshots to an external device. In this part, I am discussing how to exec a command and read its output.
To deal with external commands in Go, you use
the os/exec
package. The
primary pieces of the package that I need for now are
exec.Command()
and
CombinedOutput()
.
exec.Command()
sets up the Command structure with the command and any
arguments that I am passing to it.
var listCommand = exec.Command("zfs", "list", "-Hrt", "snapshot", "dpool")
That code creates a variable called listCommand, which is ready to run the command zfs with the arguments list, -Hrt, and snapshot as individual arguments.
var snapList, err = listCommand.CombinedOutput()
That line of code runs the command I previously prepared, puts both its
Standard Output and Standard Error in a slice of bytes. If the command exited
with an error code other than 0
, CombinedOutput sets err to a non-nil value.
snapList will have the Standard Error of the executed command, so printing
snapList’s contents will be useful for debugging.
var snapScanner = bufio.NewScanner(bytes.NewReader(snapList))
if err != nil {
fmt.Println(listCommand)
fmt.Println("Error trying to list snapshots:", err.Error())
for snapScanner.Scan() {
fmt.Println(snapScanner.Text())
}
}
I will need to use the more complicated IO redirection tools provided in the os/exec package for the zfs send and zfs receive commands. However, for a test run today, I can use a modification of the loop I used to print the output from zfs if it errored.
for snapScanner.Scan() {
if snapshotLineRegex.MatchString(snapScanner.Text()) {
var temp = strings.SplitN(snapScanner.Text(), "\t", 2)
var snapshot = ParseSnapshot(temp[0])
if snapshot != nil {
fmt.Println("I found snapshot", snapshot.Name(), "at", snapshot.Path())
}
}
}
}
©2020 Robert R. Russell — All rights reserved