Continuously check if tcp port is in use - go

I'm running a bash command to start up a server in the background : "./starServer &" However, my server takes a few seconds to start up. I'm wondering what I can do to continuously check the port that it's running on to ensure it's up before I actually move on and do other things. I couldn't find anything in the golang api that helped with this. Any help is appreciated!
c := exec.Command("/bin/sh", "-c", command)
err := c.Start()
if err != nil {
log.Fatalf("error: %v", err)
}
l, err1 := net.Listen("tcp", ":" + port)

You could connect to the port using net.DialTimeout or net.Dial, and if successful, immediately close it. You can do this in a loop until successful.
for {
conn, err := net.DialTimeout("tcp", net.JoinHostPort("", port), timeout)
if conn != nil {
conn.Close()
break
}
}
A simple tiny library (I wrote) for a similar purpose might also be of interest: portping.

Related

How to restart heroku server within golang app?

I am trying to restart heroku server conditionally. SO I wrote following code for restarting heroku server
go func() {
time.Sleep(10 * time.Second)
cmd := exec.Command("heroku", "restart")
b, err := cmd.CombinedOutput()
if err != nil {
log.Fatalf("\n======> error restarting server: %v", err)
}
fmt.Printf("\n======> server restart response : %s", string(b))
}()
But first time it is restarting successfully, from second time onwards, it is not restarting. Is there any other way to restart or Am I doing anything wrong here?
go func() {
t := time.NewTicker(time.Second * 10)
for range t.C{
cmd := exec.Command("sh", "-c","heroku restart")
var outb, errb bytes.Buffer
cmd.Stdout = &outb
cmd.Stderr = &errb
err := cmd.Run()
if err != nil {
log.Fatalf("\n======> error restarting server: %v", err)
}
fmt.Printf("\n======> server restart response : %s, %s", outb.String(), errb.String())
}
}()
check https://golang.org/pkg/time/#NewTicker
NewTicker returns a new Ticker containing a channel that will send the time with a period specified by the duration argument. It adjusts the intervals or drops ticks to make up for slow receivers. The duration d must be greater than zero; if not, NewTicker will panic. Stop the ticker to release associated resources.

goexpect, fastest way to check if telnet is open

I'm using goexpect for connection to multiple wi-fi access points.
For some of them I need to use telnet, and SSH for others.
So, I need fastest way to check if telnet is open for some IP.
Code now looks like
e, _, err := expect.Spawn(fmt.Sprintf("telnet %s", ip), -1)
res, _, err := e.Expect(userRE, timeout) // we expect user prompt
if err != nil {
// if timeout, pass control to code block which handle SSH connection
}
I suppose there is a better and faster way to tell if telnet is open.
Any suggestions?
This worked for me after getting the github.com/reiver/go-telnet package:
package main
import (
"fmt"
"github.com/reiver/go-telnet"
)
func main() {
address := "127.0.0.1:8080"
_, err := telnet.DialTo(address)
if err != nil {
fmt.Println(err)
fmt.Println("Telnet closed")
} else {
fmt.Println("Telnet open")
}
}

Keep-alive: dead peers detection

I run client and socket server written in Go (1.12) on macOS localhost.
Server sets SetKeepAlive and SetKeepAlivePeriod on net.TCPConn.
Client sends a packet and then closes connection (FIN) or client abruptly terminated.
Tcpdump shows that even after client closes the connection, server keeps sending keep-alive probes.
Shouldn't it detect that peer is "dead" and close the connection?
The question is generic, feel free to clarify if I'm missing some basics.
package main
import (
"flag"
"fmt"
"net"
"os"
"time"
)
func main() {
var client bool
flag.BoolVar(&client, "client", false, "")
flag.Parse()
if client {
fmt.Println("Client mode")
conn, err := net.Dial("tcp", "127.0.0.1:12345")
checkErr("Dial", err)
written, err := conn.Write([]byte("howdy"))
checkErr("Write", err)
fmt.Printf("Written: %v\n", written)
fmt.Println("Holding conn")
time.Sleep(60 * time.Second)
err = conn.Close()
checkErr("Close", err)
fmt.Println("Closed conn")
return
}
fmt.Println("Server mode")
l, err := net.Listen("tcp", "127.0.0.1:12345")
checkErr("listen", err)
defer l.Close()
for {
c, err := l.Accept()
checkErr("accept", err)
defer c.Close()
tcpConn := c.(*net.TCPConn)
err = tcpConn.SetKeepAlive(true)
checkErr("SetKeepAlive", err)
err = tcpConn.SetKeepAlivePeriod(5 * time.Second)
checkErr("SetKeepAlivePeriod", err)
b := make([]byte, 1024)
n, err := c.Read(b)
checkErr("read", err)
fmt.Printf("Received: %v\n", string(b[:n]))
}
}
func checkErr(location string, err error) {
if err != nil {
fmt.Printf("%v: %v\n", location, err)
os.Exit(-1)
}
}
The response to that question:
Sending keepalives is only necessary when you need the connection opened but idle. In that cases there is a risk that the connection is broken, so keep alive will try to detect broken connections.
If you had close the connection at server side with a proper con.Close() the keep alive would not be triggered (you did defer it to the end of the main function).
If you test your server code, it will start sending the keep alive after the timeout you set.
You notice that only after all keep alive proves (default 9 from kernel) and the time between the proves (8x), you get an io.EOF error on the server side Read (yes, the server stop sending)!
Currently the GO implementation is the same at Linux and OSX and it set both TCP_KEEPINTVL and TCP_KEEPIDLE to the value you pass to the setKeepAlivePeriod function, so, the behavior will depend of the kernel version.
func setKeepAlivePeriod(fd *netFD, d time.Duration) error {
// The kernel expects seconds so round to next highest second.
d += (time.Second - time.Nanosecond)
secs := int(d.Seconds())
if err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, secs); err != nil {
return wrapSyscallError("setsockopt", err)
}
err := fd.pfd.SetsockoptInt(syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, secs)
runtime.KeepAlive(fd)
return wrapSyscallError("setsockopt", err)
}
There is a request opened since 2014 to provide a way to set keepalive time and interval separately.
Some references:
rfc1122
net: enable TCP keepalive on new connections from net.Dial
net: enable TCP keepalives by default
TCP keep-alive to determine if client disconnected in netty
Using TCP keepalive with Go

Go with tcpdump as external command: how to close external command properly?

I have a Go function to capture network traffic with tcpdumb (external command) on macOS:
func start_tcpdump() {
// Run tcpdump with parameters
cmd := exec.Command("tcpdump", "-I", "-i", "en1", "-w", "capture.pcap")
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
timer := time.AfterFunc(3 * time.Second, func() {
cmd.Process.Kill()
})
err := cmd.Wait()
if err != nil{
log.Fatal(err)
}
timer.Stop()
}
When this function complete work, I'm trying to open output .pcap file in Wireshark and getting this error:
"The capture file appears to have been cut short in the middle of a packet."
Probably, cmd.Process.Kill() interrupts correct closing of .pcap-file.
What solution could be applied for "proper" closing of tcpdumb external process?
You should use cmd.Process.signal(os.Interrupt) to signal tcpdump to exit, Kill() internally calls signal(Kill) which is equivalent to kill -9 to force the process to exit.

Go - close an external application

I'm using Go on an OSX machine and trying to make a program to open an external application and then after few seconds, close it - the application, not exit the Go script.
I'm using the library available on https://github.com/skratchdot/open-golang to start the app and it works fine. I also already have the timeout running. But the problem comes when I have to close the application.
Would someone give a hint of how I would be able to exit the app?
Thanks in advance.
It looks like that library is hiding details that you'd use to close the program, specifically the process ID (PID).
If you launch instead with the os/exec package or get a handle on that PID then you can use the Process object to kill or send signals to the app to try and close it gracefully.
https://golang.org/pkg/os/#Process
Thank you guys for the help. I would able to do what I was trying with the following code.
cmd := exec.Command(path string)
err := cmd.Start()
if err != nil {
log.Printf("Command finished with error: %v", err)
}
done := make(chan error, 1)
go func() {
done <- cmd.Wait()
}()
select {
case <-time.After(30 * time.Second): // Kills the process after 30 seconds
if err := cmd.Process.Kill(); err != nil {
log.Fatal("failed to kill: ", err)
}
<-done // allow goroutine to exit
log.Println("process killed")
indexInit()
case err := <-done:
if err!=nil{
log.Printf("process done with error = %v", err)
}
}
if err != nil {
log.Fatal(err)
}
log.Printf("Waiting for command to finish...")
//timer() // The time goes by...
err = cmd.Wait()
}
I placed that right after start the app with the os/exec package as #JimB recommended.

Resources