Installing virtual Machine with virt-install - go

virt-install \
-n "NAME" \
-r 1024 \
--import \
--disk path="1703_Disk.img" \
--accelerate \
--network network=default \
--connect=qemu:///system \
--vnc \
-v
Can someone explain me how to execute this in Go.

The os/exec package is what you're looking for:
cmdName := "virt-install"
args := []string{
"-n", "NAME",
"-r", "1024",
"--import",
"--disk", "path=1703_Disk.img"
"--accelerate",
"--network", "network=default",
"--connect=qemu:///system",
"-vnc",
"-v",
}
cmd := exec.Command(cmdName, args...)
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
if err := cmd.Wait(); err != nil {
log.Fatal(err)
}

There is a Go API for libvirt, either the one at https://gitlab.com/libvirt/libvirt-go-module or the https://github.com/digitalocean/go-libvirt one. For some tasks, it makes more sense to use that, instead of running libvirt commands as a subprocess.
The virt-install case probably makes most sense as a subprocess, however.

Related

curl command return 404 when using os/exec

I try to get file from private gitlab repository using os/exec with curl and get 404 response status:
func Test_curl(t *testing.T) {
cmd := exec.Command(
`curl`,
`-H`, `PRIVATE-TOKEN:token`,
`https://gitlab.some.com/api/v4/projects/23/repository/files/.gitignore/raw\?ref\=master`,
)
t.Log(cmd.String())
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
t.Fatal(err)
}
t.Log(out.String())
}
=== RUN Test_curl
t_test.go:166: /usr/bin/curl -H PRIVATE-TOKEN:token https://gitlab.some.com/api/v4/projects/23/repository/files/.gitignore/raw\?ref\=master
t_test.go:175: {"error":"404 Not Found"}
--- PASS: Test_curl (0.25s)
but when I try to use the same command from zsh, I get right response:
% /usr/bin/curl -H PRIVATE-TOKEN:token https://gitlab.some.com/api/v4/projects/23/repository/files/.gitignore/raw\?ref\=master
.DS_Store
.vs/
.vscode/
.idea/
I think the problem in the url, but don't understand how to fix one.
? and = must not be quoted:
cmd := exec.Command(
`curl`,
`-H`, `PRIVATE-TOKEN:token`,
`https://gitlab.some.com/api/v4/projects/23/repository/files/.gitignore/raw?ref=master`,
)
exec.Command does not spawn a shell, therefore shell globs do not need escaping.

golang exec with cmd as argument does not print stdout

cmdstr := "ssh -i ....... blah blah blah" ssh to an ip and run rpm command to install rpm
cmd := exec.Command("/bin/bash", "-c", cmdstr)
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
fmt.Println(out.String())
}
out.String() does not print anything
if I have ping command without /bin/bash it prints the out. Anyone knows why ?
cmd.Stdout captures the output of a successful command execution
cmd.Stderr captures the command output if an error occurs during execution
You could try the cmd.Output() variant and capture execution errors from Stderr using
cmdstr := "ssh -i ....... blah blah blah" // ssh to an ip and run rpm command to install rpm
cmd := exec.Command("/bin/bash", "-c", cmdstr)
var errb bytes.Buffer
cmd.Stderr = &errb
output, err := cmd.Output()
if err != nil {
fmt.Printf("error: %s", errb.String()) // capture any error output
}
fmt.Println(string(output)) // when successful

Go "exec.Command" of tcpdump not doing anything

I am attempting to run the following code in Go. I have tried both of the following ways:
out, err := exec.Command("sh", "-c", "tcpdump -i ens0 host 192.168.1.100 -F ./testfile").Output()
fmt.Println(string(out)) // Prints nothing
fmt.Println(err) // exit status 1
I have also tried replacing sh with /bin/bash.
I have also tried the following, with and without sh as the first argument:
out, err := exec.Command("tcpdump", "-i", "ens0", "host", "192.168.1.100", "-F", "./testfile").Output()
fmt.Println(string(out)) // Prints nothing
fmt.Println(err) // exit status 1
None of this is working. Can someone see what I am doing wrong? I have also tried this go package "github.com/kami-zh/go-capturer" to read stderr and again it prints nothing.
Normally I have to use sudo to execute tcpdump from shell, so I build the go binary and execute it as root user.
Something like this should work, i am not sure if there is any specific command like -F available in tcp dump,
If you want to capture plain output of the tcp dump , you can direct the output to file using > file . The -w option is for wireshark/tcpdump format , to read and display
cmd := exec.Command("sh", "-c", "sudo tcpdump -i <eth> host <ip> -w ./testfile")
err := cmd.Run()
if err != nil {
fmt.Println(err)
}
Thanks, #torek, the -c option can be used with tcpdump to exit after capturing n packets
cmd := exec.Command("sh", "-c", "sudo tcpdump -i ens33 -c 100 host localhost -w ./testfile")
err := cmd.Run()
if err != nil {
fmt.Println(err)
}
The other way is to use cmd.Start
cmd := exec.Command("sh", "-c", "sudo tcpdump -i ens33 -c 100 host localhost -w ./testfile")
err := cmd.Start()
if err != nil {
log.Fatal(err)
}
log.Printf("Waiting for command to finish...")
err = cmd.Wait()
log.Printf("Command finished with error: %v", err)
The tcpdump command continue to run infinitely if you use cmd.run without -c option with tcpdump cmd.So you can't see if you put print statement after cmd.Run() call, the reason being the exec.Command failed is, it just work the same way on how it works from the cli, so if you need sodo in front for it , you should put it in command as well or run it from the root user.

Unable to run netstat for docker in Go using exec

Trying to run terminal commands in Go using exec to get docker network usage but unable to. The following link shows how to get docker container's network usage using terminal and it works fine in terminal but not using Go. https://docs.docker.com/config/containers/runmetrics/
I get exit code 1, 2, 125, etc. with different combinations.
stdin, err := cmd.StdinPipe()
if err != nil {
log.Fatal(err)
}
defer stdin.Close()
io.WriteString(stdin, "CID="+CID) // container ID
io.WriteString(stdin,"TASKS=/sys/fs/cgroup/devices/docker/$CID*/tasks")
io.WriteString(stdin, "PID=$(head -n 1 $TASKS)")
io.WriteString(stdin, "mkdir -p /var/run/netns")
io.WriteString(stdin, "ln -sf /proc/$PID/ns/net /var/run/netns/$CID")
io.WriteString(stdin, "ip netns exec $CID netstat -i")
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", out)
Expected output:
Kernel Interface table
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
eth0 1450 1228323 0 0 0 1761314 0 0 0 BMRU
If someone looks for the same in the future, here's a working solution
cmd := exec.Command("/bin/sh", "-c", "CID="+CID+" ; TASKS=/sys/fs/cgroup/devices/docker/$CID*/tasks ; PID=$(head -n 1 $TASKS); mkdir -p /var/run/netns ; ln -sf /proc/$PID/ns/net /var/run/netns/$CID ; ip netns exec $CID netstat -i")
out, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s\n", out)

GPG command works in shell but not in Go exec.Command()

I am using gnupg to encrypt files with the following command:
gpg --encrypt --sign --armor -r person#email.com name_of_file
This command works fine in shell. But it fails in go program with following error :
gpg: cannot open '/dev/tty': Device not configured
Here is the Code:
func main() {
var stdout, stderr bytes.Buffer
cmd := exec.Command("/bin/sh", "-c", `gpg --encrypt --sign --armor -r person#email.com file_name.csv`)
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
log.Println(err)
}
out := stdout.String() + stderr.String()
fmt.Println(out)
}
Why am I getting this error and how can I fix it?

Resources