Merge pull request #1 from BraydonKains/LtnpRecords
Added functionality to check for process on portpull/2/head
commit
f4bb5013a8
@ -0,0 +1,2 @@
|
|||||||
|
*.swp
|
||||||
|
eznet
|
@ -0,0 +1,24 @@
|
|||||||
|
# eznetstat: A command line application with netstat shortcuts
|
||||||
|
|
||||||
|
Have you ever needed to remember how to check what process is on a port and forgotten how to do it? There are loads of netstat commands that can be tricky to remember. This is a work in progress command line application to give direct shortcuts to those netstat operations.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
### -v, --version
|
||||||
|
Show application version.
|
||||||
|
|
||||||
|
### -h, --help
|
||||||
|
Show help menu.
|
||||||
|
|
||||||
|
### -c PORT, --check-port=PORT
|
||||||
|
Get the name and process ID of the process running on a given port
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
* Add the ability to kill process on port
|
||||||
|
* Come up with other useful stuff
|
||||||
|
* Write up contributors guide
|
||||||
|
* Decide how to do documentation (probably Github wiki?)
|
||||||
|
* Write man page (figure out how to do that lol)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
I don't know that I'm ready for contributors yet because I don't have a good contributors guide. I do plan to eventually open this up to contributors. If you have any ideas for future operations, please feel free to open an issue, I am happy to discuss ideas!
|
@ -0,0 +1,18 @@
|
|||||||
|
require "./ltnp_record"
|
||||||
|
|
||||||
|
class LtnpOperator
|
||||||
|
def initialize(cmd_output : String)
|
||||||
|
records = cmd_output.each_line
|
||||||
|
records = records.each.select(/^tcp/)
|
||||||
|
@ltnp_records = Array(LtnpRecord).new
|
||||||
|
records.each { |s| @ltnp_records << LtnpRecord.new s }
|
||||||
|
end
|
||||||
|
|
||||||
|
def say_hi
|
||||||
|
@ltnp_records.each { |r| puts r.to_s }
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_port_record(port : String) : LtnpRecord | Nil
|
||||||
|
@ltnp_records.find { |r| r.port == port }
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,53 @@
|
|||||||
|
require "../modules/record_helpers"
|
||||||
|
|
||||||
|
class LtnpRecord
|
||||||
|
getter proto : String
|
||||||
|
getter state : String
|
||||||
|
getter address : String
|
||||||
|
getter port : String
|
||||||
|
getter f_address : String
|
||||||
|
getter f_port : String
|
||||||
|
getter state : String
|
||||||
|
getter pid : String
|
||||||
|
getter p_name : String
|
||||||
|
|
||||||
|
def initialize(record : String)
|
||||||
|
ser_record = RecordHelpers.clean_record(record)
|
||||||
|
@proto = ser_record[0]
|
||||||
|
@address, @port = ser_address_port ser_record[3].split(':')
|
||||||
|
@f_address, @f_port = ser_address_port ser_record[4].split(':')
|
||||||
|
@state = ser_record[5]
|
||||||
|
@pid, @p_name = ser_pid_p_name ser_record[6]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
puts "%s, " * 8 % [
|
||||||
|
@proto, @state, @address, @port,
|
||||||
|
@f_address, @f_port, @pid, @p_name
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def ser_address_port(address_port : Array) : {String, String}
|
||||||
|
address = String.new
|
||||||
|
port = String.new
|
||||||
|
unless address_port.size > 2
|
||||||
|
address = address_port[0]
|
||||||
|
port = address_port[1]
|
||||||
|
else
|
||||||
|
port = address_port[-1]
|
||||||
|
end
|
||||||
|
{address, port}
|
||||||
|
end
|
||||||
|
|
||||||
|
def ser_pid_p_name(pid_pro_str : String) : {String, String}
|
||||||
|
pid = String.new
|
||||||
|
p_name = String.new
|
||||||
|
unless pid_pro_str == "-"
|
||||||
|
pid_pro = pid_pro_str.split('/')
|
||||||
|
pid = pid_pro[0]
|
||||||
|
p_name = pid_pro[1]
|
||||||
|
end
|
||||||
|
{pid, p_name}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -0,0 +1,34 @@
|
|||||||
|
require "option_parser"
|
||||||
|
require "./ltnp/ltnp_operator"
|
||||||
|
require "./modules/netstat_runner"
|
||||||
|
|
||||||
|
OptionParser.parse do |parser|
|
||||||
|
parser.banner = "Welcome to eznetstat!"
|
||||||
|
|
||||||
|
parser.on "-v", "--version", "Show version" do
|
||||||
|
puts "0.1"
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on "-h", "--help", "Show help" do
|
||||||
|
puts parser
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on "-c PORT", "--check-port=PORT", "Get the process name and ID of process on port" do |port|
|
||||||
|
ltnp_operator = NetstatRunner.run_ltnp
|
||||||
|
record = ltnp_operator.get_port_record port
|
||||||
|
unless record.nil?
|
||||||
|
puts "Port: %s, Process: %s" % [record.port, record.p_name]
|
||||||
|
else
|
||||||
|
puts "No processes found on port %s" % port
|
||||||
|
end
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on "-k", "--kill-port", "Kill process on port" do
|
||||||
|
ltnp_operator = NetstatRunner.run_ltnp
|
||||||
|
ltnp_operator.say_hi
|
||||||
|
exit
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,7 @@
|
|||||||
|
module NetstatRunner
|
||||||
|
def self.run_ltnp() : LtnpOperator
|
||||||
|
io = IO::Memory.new
|
||||||
|
Process.run("sudo netstat -ltnp", shell: true, output: io)
|
||||||
|
LtnpOperator.new io.to_s
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,7 @@
|
|||||||
|
module RecordHelpers
|
||||||
|
def self.clean_record(record : String) : Array(String)
|
||||||
|
tokenized_record = record.split(" ")
|
||||||
|
tokenized_record = tokenized_record.reject { |s| s == "" }
|
||||||
|
tokenized_record
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,8 @@
|
|||||||
|
Active Internet connections (only servers)
|
||||||
|
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
|
||||||
|
tcp 0 0 127.0.0.1:8081 0.0.0.0:* LISTEN 166475/polymer
|
||||||
|
tcp 0 0 0.0.0.0:57621 0.0.0.0:* LISTEN 163077/spotify --fo
|
||||||
|
tcp 0 0 192.168.122.1:53 0.0.0.0:* LISTEN 1286/dnsmasq
|
||||||
|
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 35841/sshd
|
||||||
|
tcp 0 0 0.0.0.0:53323 0.0.0.0:* LISTEN 163077/spotify --fo
|
||||||
|
tcp6 0 0 :::22 :::* LISTEN 35841/sshd
|
@ -0,0 +1,19 @@
|
|||||||
|
require "spec"
|
||||||
|
require "../../ltnp/ltnp_operator.cr"
|
||||||
|
|
||||||
|
describe LtnpOperator do
|
||||||
|
sut = LtnpOperator.new File.read("./spec/input/ltnp_example.txt")
|
||||||
|
|
||||||
|
describe "#get_port_record" do
|
||||||
|
existing_port = "8081"
|
||||||
|
nonsense_port = "1234"
|
||||||
|
|
||||||
|
it "should find record when port exists" do
|
||||||
|
sut.get_port_record(existing_port).nil?.should be_false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not find record when port doesn't exist" do
|
||||||
|
sut.get_port_record(nonsense_port).nil?.should be_true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,29 @@
|
|||||||
|
require "spec"
|
||||||
|
require "../../ltnp/ltnp_record.cr"
|
||||||
|
|
||||||
|
describe LtnpRecord do
|
||||||
|
sut_normal = LtnpRecord.new "tcp 0 0 127.0.0.1:8081 0.0.0.0:* LISTEN 69/myproc"
|
||||||
|
sut_address = LtnpRecord.new "tcp 0 0 :::8081 0.0.0.0:* LISTEN 69/myproc"
|
||||||
|
sut_process = LtnpRecord.new "tcp 0 0 :::8081 0.0.0.0:* LISTEN -"
|
||||||
|
|
||||||
|
it "should have expected properties under normal circumstance" do
|
||||||
|
sut_normal.proto.should eq("tcp")
|
||||||
|
sut_normal.address.should eq("127.0.0.1")
|
||||||
|
sut_normal.port.should eq("8081")
|
||||||
|
sut_normal.f_address.should eq("0.0.0.0")
|
||||||
|
sut_normal.f_port.should eq("*")
|
||||||
|
sut_normal.state.should eq("LISTEN")
|
||||||
|
sut_normal.pid.should eq("69")
|
||||||
|
sut_normal.p_name.should eq("myproc")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have expected properties when Local Address column is edge case" do
|
||||||
|
sut_address.address.empty?.should be_true
|
||||||
|
sut_address.port.should eq("8081")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have expected properties when PID/ProcessName column is edge case" do
|
||||||
|
sut_process.pid.empty?.should be_true
|
||||||
|
sut_process.p_name.empty?.should be_true
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue