Formatting the parameter of exec.Command - golang [duplicate] - go

This question already has answers here:
fork/exec . no such file or directory exit status 1
(3 answers)
call 'go build' command from golang os.exec
(1 answer)
Why is this curl command not working?
(2 answers)
calling command with some arguments works but not with others but works from console
(1 answer)
How to pass a flag to a command in go lang?
(1 answer)
Closed 2 days ago.
I have this command lsblk | grep /snap/snapd/18357 | awk '{ print $1 }' that I want to execute within golang code:
import (
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("lsblk","|", "grep", "/snap/snapd/18357", "|", "awk", "'{ print $1 }'")
out, err := cmd.Output()
if err != nil {
fmt.Println(err)
}
fmt.Println(string(out))
}
It return error exit status 32. I think the problem lies the parameter of exec.Command. How should I break this command down?

Related

Is there a concept of reading the output of a program line by line, as a stream? [duplicate]

This question already has answers here:
Capture stdout from command exec in real time
(2 answers)
How to call an external program and process its output?
(2 answers)
Trying to return live/realtime output from shell command as string data from function to main function
(2 answers)
Closed 3 months ago.
I have a shell command (e.g. journalctl -f -o json) that continuously streams lines to the standard output.
I would like to retrieve this output line by line and process it further.
The documentation of os/exec addresses how to read the output of a command, and io deals with stream buffering.
Everywhere I looked, the handling goes through a fixed buffer that is read into, handled, and written further. My problem is that the size of this buffer is fixed and independent of the content.
Is there a way to read an incoming stream (in my case - the output of a shell command) line by line? Possibly with a library more high-level than io readers?
Use Cmd.StdoutPipe() to obtain the (piped) output of the process before you start it with Cmd.Start() (Start() starts the command but does not wait for it to complete).
And use a bufio.Scanner to read an input (io.Reader) line-by-line.
For example I'm gonna use this bash script that prints the current time 3 times, sleeping 1 second between them:
for i in {1..3}; do date; sleep 1; done
Example executing this and reading its output line-by-line:
cmd := exec.Command("bash", "-c", "for i in {1..3}; do date; sleep 1; done")
out, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
defer out.Close()
err = cmd.Start()
if err != nil {
log.Fatal(err)
}
scanner := bufio.NewScanner(out)
for scanner.Scan() {
line := scanner.Text()
fmt.Println("Output:", line)
}
Example output:
2022/11/29 14:38:48 Output: Tue Nov 29 02:38:48 PM CET 2022
2022/11/29 14:38:49 Output: Tue Nov 29 02:38:49 PM CET 2022
2022/11/29 14:38:50 Output: Tue Nov 29 02:38:50 PM CET 2022
(The first date-time at the beginning of each line is from the log package, to verify each line is printed after a second delay, the other timestamp is the output of the date command.)

I ran scp -i ssh "<filepath of remote linux machine> . " using Go from my client machine, but it is returning "no such file or directory" [duplicate]

This question already has answers here:
fork/exec . no such file or directory exit status 1
(3 answers)
call 'go build' command from golang os.exec
(1 answer)
Why is this curl command not working?
(2 answers)
calling command with some arguments works but not with others but works from console
(1 answer)
Closed 3 years ago.
How to execute the scp -i ssh " . " using Go?
I have used the following code snippet.
cmd := exec.Command("scp -i dragonstone.pem <user>#ubuntu:<file location> .")
err = cmd.Run()
I will do this.
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
cmd := "scp"
args := []string{"-i", "dragonstone.pem", "<user>#ubuntu:<file location>", "."}
if err := exec.Command(cmd, args...).Run(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Println("Successfully.")
}

Exit Status 2 on running Grep command using Golang

I write simple script using Golang to grep a log file with some parameters. Here's my shell command
grep CRON var/log/sys | tail -5 | grep "cd /home/raka/repo && git status"
I want to run command above in Golang using os/exec package. Here's my code sniped.
var (
reader io.Reader
out []byte
err error
commandName string = "grep"
)
args := []string{"CRON", "/var/log/syslog", "| tail -6", "| grep \"git status\""}
cmd := exec.Command(commandName, args...)
r, err = cmd.StdoutPipe()
err = cmd.Start()
out, err = ioutil.ReadAll(r)
err = cmd.Wait()
return strings.Split(string(out), "\n")```
Currently, the sniped above doesn't work, because of exit status 2.
Any of you guys/ladies have solution for this problem? thank you so much.
Pipes (|) are implemented by a shell program (like bash). If you want to use them you should execute shell passing a command containing piped program invocations:
exec.Command("/bin/sh", "-c",
"grep CRON var/log/sys | tail -5 | grep \"cd /home/raka/repo && git status\"")

Call source from inside a Go program

For fun and to better learn Go, I'm trying to re-implement antigen in Go.
Problem is: source is a shell built-in function, so I can't call it with os/exec Command function, because it expects an executable in PATH.
How can I do this? And, is it possible to make a source from inside a go program affect the user shell?
You can write the command directly in the terminal device. But, to do that, first you need to know which device is using the user. A script that executes your program can be a solution.
#!/bin/bash
echo Running from foo script, pid = $$
go run foo.go `tty`
Then, the program has to write the commands to the terminal device.
package main
import (
"C"
"fmt"
"os"
"syscall"
"unsafe"
)
func main() {
// Get tty path
if len(os.Args) < 2 {
fmt.Printf("no tty path\n")
os.Exit(1)
}
ttyPath := os.Args[1]
// Open tty
tty, err := os.Open(ttyPath)
if err != nil {
fmt.Printf("error opening tty: %s\n", err.Error())
os.Exit(2)
}
defer tty.Close()
// Write a command
cmd := "echo Hello from go, pid = $$\n"
cmdstr := C.CString(cmd)
cmdaddr := uintptr(unsafe.Pointer(cmdstr))
for i := range []byte(cmd) {
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, tty.Fd(), syscall.TIOCSTI, cmdaddr+uintptr(i))
if uintptr(err) != 0 {
fmt.Printf("syscall error: %s\n", err.Error())
os.Exit(3)
}
}
}
Here is an example output:
$ echo $$
70318
$ ./foo
Running from foo script, pid = 83035
echo Hello from go, pid = $$
$ echo Hello from go, pid = $$
Hello from go, pid = 70318
Note that I am executing the script with ./ not source, so the PID of the script differs. But later, the command executed by the go program has the same PID.

os.Exec and /bin/sh: executing multiple commands

I've run into an issue with the os/exec library. I want to run a shell and pass it multiple commands to run, but it's failing when I do. Here's my test code:
package main
import (
"fmt"
"os/exec"
)
func main() {
fmt.Printf("-- Test 1 --\n`")
command1 := fmt.Sprintf("\"%s\"", "pwd") // this one succeeds
fmt.Printf("Running: %s\n", command1)
cmd1 := exec.Command("/bin/sh", "-c", command1)
output1,err1 := cmd1.CombinedOutput()
if err1 != nil {
fmt.Printf("error: %v\n", err1)
return
}
fmt.Printf(string(output1))
fmt.Printf("-- Test 2 --\n")
command2 := fmt.Sprintf("\"%s\"", "pwd && pwd") // this one fails
fmt.Printf("Running: %s\n", command2)
cmd2 := exec.Command("/bin/sh", "-c", command2)
output2,err2 := cmd2.CombinedOutput()
if err2 != nil {
fmt.Printf("error: %v\n", err2)
return
}
fmt.Printf(string(output2))
}
When running this I get an error 127 on the second example. It seems like it's looking for a literal "pwd && pwd" command instead of evaluating it as a script.
If I do the same thing from the command line it works just fine.
$ /bin/sh -c "pwd && pwd"
I'm using Go 1.4 on OS X 10.10.2.
the quotes are for your shell where you typed the command line, they should not be included when programatically launching an app
just make this change and it will work:
command2 := "pwd && pwd" // you don't want the extra quotes

Resources