How to stop fmt.print() from printing to the output? - go

I'm using a package which has some fmt.print()s in the code, and I want to stop them from printing to the output. I want to suppress them without changing the code inside the package and only by adding some lines to my main.go.
Is it possible to force fmt not to log prints to the output?

Yes, just divert os.Stdout and/or os.Stderr e.g.:
package main
import (
"fmt"
"os"
)
func main() {
temp := os.Stdout
os.Stdout = nil // turn it off
packageFunctions() // call you package functions here
os.Stdout = temp // restore it
fmt.Println("Bye")
}
func packageFunctions() {
fmt.Println("Hi")
}
Output:
Bye
You may divert it to a temp file:
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
)
func main() {
tmpfile, err := ioutil.TempFile("", "example")
if err != nil {
log.Fatal(err)
}
fmt.Println(tmpfile.Name())
// defer os.Remove(tmpfile.Name()) // clean up
temp := os.Stdout
os.Stdout = tmpfile
packageFunctions() // call you package functions here
if err := tmpfile.Close(); err != nil {
log.Fatal(err)
}
os.Stdout = temp // restore it
fmt.Println("Bye")
}
func packageFunctions() {
fmt.Println("Hi")
}
And see:
How to copy os.Stdout output to string variable
How can stdout be captured or suppressed for Go(lang) testing?

Related

How to get the output of a command

I am calling a python script from Go code:
package main
import (
"os/exec"
"os"
"fmt"
"time"
"encoding/json"
)
func main() {
cmd := exec.Command("python","/home/devendra/Desktop/sync/blur_multithread.py","http://4.imimg.com/data4/TP/ED/NSDMERP-28759633/audiovideojocks.png")
var logs=make(map[string]interface{})
logs["tes"]=os.Stdout
_ = cmd.Run()
WriteLogs(logs)//Writelog is my function which logs everything in a file
}
func WriteLogs(logs map[string]interface{}){
currentTime := time.Now().Local()
jsonLog, err := json.Marshal(logs)
if err != nil {
fmt.Println(err.Error())
}
jsonLogString := string(jsonLog[:len(jsonLog)])
logfile := "/home/devendra/ImageServiceLogs/"+ "ImageServiceLogs_" + currentTime.Format("2006-01-02") + ".txt"
if logfile == "" {
fmt.Println("Could not find logfile in configuration ...!!!")
} else {
jsonLogFile, err := os.OpenFile(logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
defer jsonLogFile.Close()
if err != nil {
fmt.Println(err.Error())
}
jsonLogFile.WriteString(jsonLogString + "\n")
}
}
But in the logs value of tes field is null while my python script is giving me output. How to get the output of python script in my code?
As per official documentation examples, exec.Cmd.Ouput() ([]byte, error) will give you the sdout of the command after it has finished running.
https://golang.org/pkg/os/exec/#Cmd.Output
package main
import (
"fmt"
"log"
"os/exec"
)
func main() {
out, err := exec.Command("date").Output()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)
}
To receive both stdout and stderr of the process, writer should use exec.Cmd.CombinedOutput
https://golang.org/pkg/os/exec/#Cmd.CombinedOutput
If someone wants to receive the command output in real time to its terminal, then the writer should set exec.Cmd.Stdout and exec.Cmd.Stderr properties to, respectively, os.Stdout and os.Stderr and invoke the exec.Cmd.Run() error method.
https://golang.org/pkg/os/exec/#Cmd
https://golang.org/pkg/os/exec/#Cmd.Run
package main
import (
"fmt"
"log"
"os"
"os/exec"
)
func main() {
cmd := exec.Command("date")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)
}
To forward outputs and capture it at the same time, writer should seek help of the io package to use an io.MultiWriter
https://golang.org/pkg/io/#MultiWriter
package main
import (
"fmt"
"io"
"log"
"os"
"os/exec"
)
func main() {
stdout := new(bytes.Bufer)
stderr := new(bytes.Bufer)
cmd := exec.Command("date")
cmd.Stdout = io.MultiWriter(os.Stdout, stdout)
cmd.Stderr = io.MultiWriter(os.Stderr, stderr)
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
fmt.Printf("The date is %s\n", out)
}
Alternatively, you can make use of the exec.Cmd.{Stdout,Stderr}Pipe() see the official documentation examples https://golang.org/pkg/os/exec/#Cmd.StdoutPipe

How open other tools like htop, vim by os's package

I'm writing a new project like a CLI with Go and I'm using the package termui, but in a time, I need that CLI open a file with editor like VIM without exit the current CLI, when close the VIM I can back to current CLI. Is it possible?
I've tried with this example below:
package main
import (
"log"
"os/exec"
)
func main() {
// render the termui
path := "SomeFile.bash"
cmd := exec.Command("vim", path)
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
}
I did resolve with instance of os like os.Stdin or os.Stdout
Example:
package main
import (
"log"
"os/exec"
)
func main() {
// render the termui
path := "SomeFile.bash"
cmd := exec.Command("vim", path)
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
}
Thanks #Peter by commentary :)

Continuously execute tshark from Go script

I am trying to execute tskarh from golang script using the example from
https://tutorialedge.net/golang/executing-system-commands-with-golang/
The script works fine, but i don't receive any kind of output
What i want to get is the following:
Continuously run the script,
capture some packets,
extract some fields values,
and assign to variables
Any help please ?
https://pastebin.com/PeAz7vh9
package main
import (
"fmt"
"os/exec"
"runtime"
)
func execute() {
// here we perform the pwd command.
// we can store the output of this in our out variable
// and catch any errors in err
out, err := exec.Command("tshark", "-i", "em1").CombinedOutput()
// if there is an error with our execution
// handle it here
if err != nil {
fmt.Printf("%s", err)
}
fmt.Println("Command Successfully Executed")
// as the out variable defined above is of type []byte we need to convert
// this to a string or else we will see garbage printed out in our console
// this is how we convert it to a string
output := string(out[:])
// once we have converted it to a string we can then output it.
fmt.Println(output)
}
func main() {
fmt.Println("Simple Shell")
fmt.Println("---------------------")
if runtime.GOOS == "windows" {
fmt.Println("Can't Execute this on a windows machine")
} else {
execute()
}
}
I have no idea of tshark, but here is a code that will work continously, you need os.Interrupt, and select.
package main
import (
"os"
"os/exec"
"os/signal"
)
func main() {
out := exec.Command("ping", "8.8.8.8")
f1, _ := os.OpenFile("./outfile.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0755)
f2, _ := os.OpenFile("./errfile.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0755)
out.Stdout = f1
out.Stderr = f2
defer func() {
f1.Close()
f2.Close()
}()
err := out.Run()
if err != nil {
panic(err)
}
var ctrlcInt chan os.Signal
ctrlcInt = make(chan os.Signal, 1)
signal.Notify(ctrlcInt, os.Interrupt)
for {
select {
case <-ctrlcInt:
break
default:
continue
}
}
return
}
this code pings 8.8.8.8 and writes out put to outfile.txt, it will exit when you press ctrl+c. If there is error it will write to errfile.txt. You can tail the files and see the output. Hope this helps.

How to create new file using go script

I am new to go lang. I am able to create a new file from the terminal using go script. like this
go run ../myscript.go > ../filename.txt
but I want to create the file from the script.
package main
import "fmt"
func main() {
fmt.Println("Hello") > filename.txt
}
If you are trying to print some text to a file one way to do it is like below, however if the file already exists its contents will be lost:
package main
import (
"fmt"
"os"
)
func main() {
err := os.WriteFile("filename.txt", []byte("Hello"), 0755)
if err != nil {
fmt.Printf("Unable to write file: %v", err)
}
}
The following way will allow you to append to an existing file if it already exists, or creates a new file if it doesn't exist:
package main
import (
"os"
"log"
)
func main() {
// If the file doesn't exist, create it, or append to the file
f, err := os.OpenFile("access.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
_, err = f.Write([]byte("Hello"))
if err != nil {
log.Fatal(err)
}
f.Close()
}
you just need to check the API documentation. This is one way to do it, there is others (with os or bufio)
package main
import (
"io/ioutil"
)
func main() {
// read the whole file at once
b, err := ioutil.ReadFile("input.txt")
if err != nil {
panic(err)
}
// write the whole body at once
err = ioutil.WriteFile("output.txt", b, 0644)
if err != nil {
panic(err)
}
}
Fprintln is pretty close to what you were trying to do:
package main
import (
"fmt"
"os"
)
func main() {
f, e := os.Create("filename.txt")
if e != nil {
panic(e)
}
defer f.Close()
fmt.Fprintln(f, "Hello")
}
https://golang.org/pkg/fmt#Fprintln

Writing buffer to file doesn't return error, so why is file empty afterwords?

I'm trying to read all standard input and write it to a file. It's writing nothing to the file provided. Why is it not working?
package main
import (
"os"
"bytes"
"fmt"
"bufio"
)
func main() {
fn := os.Args[1]
var input bytes.Buffer
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Fprintf(&input, scanner.Text())
fmt.Fprintf(&input, "\n")
}
fi, _ := os.Open(fn)
defer fi.Close()
fi.Write(input.Bytes())
}
And then...
touch writetothis.txt
echo "input text" | go run main.go writetothis.txt
# writetothis.txt is empty
Open opens a file in read-only mode.
Refer to documentation: https://golang.org/pkg/os/#Open
Instead, use OpenFile.
Also, always check for errors whenever you code. It'll save you at least weeks of work-hours in your lifetime.
Here is a working code:
package main
import (
"bufio"
"bytes"
"fmt"
"os"
)
func main() {
fn := os.Args[1]
var input bytes.Buffer
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Fprintf(&input, scanner.Text())
fmt.Fprintf(&input, "\n")
}
fmt.Println(input.Bytes())
fi, err := os.OpenFile(fn, os.O_RDWR|os.O_CREATE, 0755)
if err != nil {
fmt.Println("Error with Open()",err)
}
defer fi.Close()
n, err := fi.Write(input.Bytes())
if err != nil {
fmt.Println("Error with Write()", err)
}
fmt.Println("Bytes written to file: ",n)
}
In your code you can silently fail because you aren't checking the error. It's likely a path issue. You can change your code slightly and let ioutil handle file creation so that paths aren't so much of an issue. Remember to always check the errs
package main
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
)
func main() {
fn := os.Args[1]
var input bytes.Buffer
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
fmt.Fprintf(&input, scanner.Text())
fmt.Fprintf(&input, "\n")
}
err := ioutil.WriteFile(fn, input.Bytes(), 0644)
if err != nil {
log.Fatal(err)
}
}

Resources