Please consider the following go code, which I wrote to scan a TCP port (os.Arg[2]) of hostnames from a given filename (os.Arg[1]). It reads each hostname, tries to connect. If the connect failed, it would append the failed hostname to outfile.
package main
import(
"fmt"
"os"
"log"
"bufio"
"time"
"net"
)
func main(){
argc := len(os.Args)
if argc < 3 {
fmt.Printf("Invalid usage")
log.Fatal("Invalid usage")
}
stamp := time.Now().UnixNano()
outfile := fmt.Sprintf("%s%d.txt", "/tmp/port_check", stamp)
filename := os.Args[1]
file, err := os.Open(filename)
checkerr(err)
f, err := os.OpenFile(outfile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
checkerr(err)
defer f.Close()
port := os.Args[2]
channel := make(chan string,17)
fscanner := bufio.NewScanner(file)
for fscanner.Scan(){
_line := fscanner.Text()
go check_sender(_line,port,f,channel)
}
_count := 0
for out := range channel{
fmt.Println("_count is:", _count, out)
_count += 1
}
close(channel)
}
func checkerr(err error){
if err != nil {
fmt.Println(err)
log.Fatal(err)
}
}
func check_sender(sender string, port string, f *os.File, channel chan string){
address_string := fmt.Sprintf("%s:%s", sender, port)
_, err := net.DialTimeout("tcp", address_string,4 * time.Second)
if err != nil {
write_this := fmt.Sprintf("%s
", sender)
f.WriteString(write_this)
}
channel <- sender
}
Generate some content for it operate on:
$ for i in `seq 1 5`; do echo "someblog$RANDOM$RANDOM.blogspot.com"; done > /tmp/meh.txt
And when run as:
$ go run port_scan.go /tmp/meh.txt 80
_count is: 0 someblog50063432.blogspot.com
_count is: 1 someblog922816893.blogspot.com
_count is: 2 someblog622823698.blogspot.com
_count is: 3 someblog1074223783.blogspot.com
_count is: 4 someblog1876411881.blogspot.com
^Csignal: interrupt < ----------------------- this
It hangs after the last hostname, and does not exit until a ctlr-c is sent.
I would like it to exit by itself, what am I doing wrong here?
update 1:
channel := make(chan string,17)
fscanner := bufio.NewScanner(file)
+ spin := 0
for fscanner.Scan(){
_line := fscanner.Text()
go check_sender(_line,port,f,channel)
+ spin += 1
}
_count := 0
for out := range channel{
fmt.Println("_count is:", _count, out)
_count += 1
+ if _count == spin {
+ close(channel)
+ }
}
- close(channel)
}