Reputation: 89
I am trying to execute a netstat command to find out number of ports in use using golang,
I am using the following code for that,
func PortCheck() int {
cmd := exec.Command("netstat", "-an")
grep := exec.Command("grep", "8000")
wc := exec.Command("wc", "-l")
pipe, _ := cmd.StdoutPipe()
defer pipe.Close()
grep.Stdin = pipe
pipe2, _ := grep.StdoutPipe()
defer pipe2.Close()
wc.Stdin = pipe2
// Run ps first.
cmd.Start()
grep.Start()
out, err := wc.Output()
if err != nil {
// if there was any error, print it here
fmt.Println("could not run command: ", err)
}
// otherwise, print the output from running the command
fmt.Println("Output: ", string(out))
fmt.Println(cmd)
ports, err := strconv.Atoi(strings.Split(string(out), "\n")[0])
if err != nil {
fmt.Println(err)
}
return ports
}
I am running this function concurrently, let's say for 10,000 iterations,
it starts giving error:-
fork/exec /usr/bin/wc: resource temporarily unavailable
Please help me out with the solution, Is this function will be more optimized, to find out the number of ports in use?
I am expecting to run the given function concurrently 1 million times.
Upvotes: 1
Views: 1333
Reputation: 1364
Your implementation is not waiting for the processes to exit. After the ulimit for max user proceses is reached the program is unable to fork new processes.
You must call (*Cmd).Wait to wait for every process to exit before returning from the PortCheck
implementation.
You should also connect your processes using os.Pipe
. This is more or less how your shell implements pipes. Only use (*Cmd).StdoutPipe
to read the result from the final command.
If you want to improve performance:
grep 8000 | wc -l
in Go. This can also be less buggy. Eg, I assume you don't want to match port 48000? Or perhaps you only want TCP, instead of UDP or unix sockets with "8000" in the inode?netstat
reads and interprets /proc/net/{tcp,tcp6,udp,...}
. These files are easier to parse than the netstat output. It also avoids forking new processes and parsing irrelevant files. This can be massively faster. It is also less portable, but there can be subtle differences between OS netstat
implementations so this function may need OS specific variations anyway.Upvotes: 4