$ ruby mini-netstat.rb
local address remote address state username (uid)
0.0.0.0:8060 0.0.0.0:0 LISTEN root (0)
127.0.0.1:9121 0.0.0.0:0 LISTEN gitlab-redis (997)
127.0.0.1:9090 0.0.0.0:0 LISTEN gitlab-prometheus (992)
127.0.0.1:9187 0.0.0.0:0 LISTEN gitlab-psql (996)
127.0.0.1:9093 0.0.0.0:0 LISTEN gitlab-prometheus (992)
127.0.0.1:9229 0.0.0.0:0 LISTEN git (998)
127.0.0.1:8080 0.0.0.0:0 LISTEN git (998)
127.0.0.1:9168 0.0.0.0:0 LISTEN git (998)
0.0.0.0:80 0.0.0.0:0 LISTEN root (0)
127.0.0.1:8082 0.0.0.0:0 LISTEN git (998)
127.0.0.1:9236 0.0.0.0:0 LISTEN git (998)
0.0.0.0:22 0.0.0.0:0 LISTEN root (0)
127.0.0.1:8080 127.0.0.1:37976 TIME_WAIT root (0)
127.0.0.1:57568 127.0.0.1:9090 ESTABLISHED gitlab-prometheus (992)
127.0.0.1:57562 127.0.0.1:9090 ESTABLISHED gitlab-prometheus (992)
127.0.0.1:58602 127.0.0.1:8082 ESTABLISHED gitlab-prometheus (992)
127.0.0.1:56314 127.0.0.1:9229 ESTABLISHED gitlab-prometheus (992)
127.0.0.1:8080 127.0.0.1:37978 TIME_WAIT root (0)
127.0.0.1:36808 127.0.0.1:9187 ESTABLISHED gitlab-prometheus (992)
127.0.0.1:55434 127.0.0.1:9168 ESTABLISHED gitlab-prometheus (992)
172.17.0.2:33956 10.10.14.135:4444 ESTABLISHED git (998)
127.0.0.1:8082 127.0.0.1:58602 ESTABLISHED git (998)
127.0.0.1:51426 127.0.0.1:80 TIME_WAIT root (0)
127.0.0.1:9229 127.0.0.1:56314 ESTABLISHED git (998)
127.0.0.1:9090 127.0.0.1:57562 ESTABLISHED gitlab-prometheus (992)
127.0.0.1:9168 127.0.0.1:55420 ESTABLISHED git (998)
127.0.0.1:9187 127.0.0.1:36808 ESTABLISHED gitlab-psql (996)
127.0.0.1:8080 127.0.0.1:37984 TIME_WAIT root (0)
127.0.0.1:55420 127.0.0.1:9168 ESTABLISHED gitlab-prometheus (992)
127.0.0.1:9168 127.0.0.1:55436 ESTABLISHED git (998)
127.0.0.1:9121 127.0.0.1:46208 ESTABLISHED gitlab-redis (997)
127.0.0.1:55436 127.0.0.1:9168 ESTABLISHED gitlab-prometheus (992)
127.0.0.1:8060 127.0.0.1:56772 ESTABLISHED gitlab-www (999)
127.0.0.1:8080 127.0.0.1:37982 TIME_WAIT root (0)
127.0.0.1:46208 127.0.0.1:9121 ESTABLISHED gitlab-prometheus (992)
172.17.0.2:60588 10.10.14.179:4444 ESTABLISHED git (998)
127.0.0.1:9090 127.0.0.1:57568 ESTABLISHED gitlab-prometheus (992)
127.0.0.1:9236 127.0.0.1:32882 ESTABLISHED git (998)
127.0.0.1:32882 127.0.0.1:9236 ESTABLISHED gitlab-prometheus (992)
127.0.0.1:56772 127.0.0.1:8060 ESTABLISHED gitlab-prometheus (992)
127.0.0.1:9168 127.0.0.1:55434 ESTABLISHED git (998)
Last active
March 2, 2023 22:29
-
-
Save noraj/d6f7ca3a73aeefeb09299d3299cfea6f to your computer and use it in GitHub Desktop.
netstat -ta4 or ss -ta4 equivalent in Ruby and Crystal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'etc' | |
TCP_STATES = { # /usr/src/linux/include/net/tcp_states.h | |
'00': 'UNKNOWN', | |
'FF': 'UNKNOWN', | |
'01': 'ESTABLISHED', | |
'02': 'SYN_SENT', | |
'03': 'SYN_RECV', | |
'04': 'FIN_WAIT1', | |
'05': 'FIN_WAIT2', | |
'06': 'TIME_WAIT', | |
'07': 'CLOSE', | |
'08': 'CLOSE_WAIT', | |
'09': 'LAST_ACK', | |
'0A': 'LISTEN', | |
'0B': 'CLOSING', | |
'0C': 'NEW_SYN_RECV' | |
} | |
def decode_addr(addr) | |
ip, port = addr.split(':') | |
ip = ip.scan(/.{2}/).map{|x|x.hex.to_s}.reverse.join('.') | |
port = port.hex.to_s | |
"#{ip}:#{port}" | |
end | |
puts 'local address'.ljust(22) + 'remote address'.ljust(22) + 'state'.ljust(12) + 'username (uid)' | |
File.readlines('/proc/net/tcp').each_with_index do |line, i| | |
entry = line.split(' ') | |
unless i == 0 # skip headers | |
laddr = decode_addr(entry[1]) | |
raddr = decode_addr(entry[2]) | |
state = TCP_STATES[entry[3].to_sym] | |
uid = entry[7] | |
uname = Etc.getpwuid(uid.to_i).name | |
puts "#{laddr.ljust(22)}#{raddr.ljust(22)}#{state.ljust(12)}#{uname} (#{uid})" | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TCP_STATES = { # /usr/src/linux/include/net/tcp_states.h | |
"00" => "UNKNOWN", | |
"FF" => "UNKNOWN", | |
"01" => "ESTABLISHED", | |
"02" => "SYN_SENT", | |
"03" => "SYN_RECV", | |
"04" => "FIN_WAIT1", | |
"05" => "FIN_WAIT2", | |
"06" => "TIME_WAIT", | |
"07" => "CLOSE", | |
"08" => "CLOSE_WAIT", | |
"09" => "LAST_ACK", | |
"0A" => "LISTEN", | |
"0B" => "CLOSING", | |
"0C" => "NEW_SYN_RECV" | |
} | |
module Etc | |
def self.getpwuid(uid) | |
File.read_lines("/etc/passwd").each_with_index do |line, i| | |
entry = line.split(":", remove_empty: false) | |
return entry[0] if entry[2] == uid | |
end | |
end | |
end | |
def decode_addr(addr) | |
ip, port = addr.split(":", remove_empty: true) | |
ip = ip.scan(/.{2}/).reverse_each.join('.'){ |x| x[0].to_i(16) } | |
port = port.to_i(16).to_s | |
"#{ip}:#{port}" | |
end | |
puts "local address".ljust(22) + "remote address".ljust(22) + "state".ljust(12) + "username (uid)" | |
File.read_lines("/proc/net/tcp").each_with_index do |line, i| | |
entry = line.split(" ", remove_empty: true) | |
unless i == 0 # skip headers | |
laddr = decode_addr(entry[1]) | |
raddr = decode_addr(entry[2]) | |
state = TCP_STATES[entry[3]] | |
uid = entry[7] | |
uname = Etc.getpwuid(uid) | |
puts "#{laddr.ljust(22)}#{raddr.ljust(22)}#{state.ljust(12)}#{uname} (#{uid})" | |
end | |
end |
Ruby to Crystal conversion required the following changes:
- replaced
File.readlines
withFile.read_lines
- replaced
String.hex
withString.to_i(16)
- Regex return
Regex::MatchData
and not a string you need to access a[0]
like for capture groups String.to_sym
doesn't exist in Crystal so changed key from symbol to string- added
remove_empty: true
tosplit()
as it's not done by default when a separator is provided - replaced
Etc.getpwuid
witch custom code since theetc
module is not implemented in Crystal - changed all single quotes to doubles quotes
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment