mirror of
https://github.com/kellyjonbrazil/jc.git
synced 2025-06-17 00:07:37 +02:00
add ss parser
This commit is contained in:
@ -25,6 +25,7 @@ import jc.parsers.mount
|
|||||||
import jc.parsers.netstat
|
import jc.parsers.netstat
|
||||||
import jc.parsers.ps
|
import jc.parsers.ps
|
||||||
import jc.parsers.route
|
import jc.parsers.route
|
||||||
|
import jc.parsers.ss
|
||||||
import jc.parsers.uname
|
import jc.parsers.uname
|
||||||
import jc.parsers.uptime
|
import jc.parsers.uptime
|
||||||
import jc.parsers.w
|
import jc.parsers.w
|
||||||
@ -58,6 +59,7 @@ def helptext(message):
|
|||||||
--netstat netstat parser
|
--netstat netstat parser
|
||||||
--ps ps parser
|
--ps ps parser
|
||||||
--route route parser
|
--route route parser
|
||||||
|
--ss ss parser
|
||||||
--uname uname -a parser
|
--uname uname -a parser
|
||||||
--uptime uptime parser
|
--uptime uptime parser
|
||||||
--w w parser
|
--w w parser
|
||||||
@ -119,6 +121,7 @@ def main():
|
|||||||
'--netstat': jc.parsers.netstat.parse,
|
'--netstat': jc.parsers.netstat.parse,
|
||||||
'--ps': jc.parsers.ps.parse,
|
'--ps': jc.parsers.ps.parse,
|
||||||
'--route': jc.parsers.route.parse,
|
'--route': jc.parsers.route.parse,
|
||||||
|
'--ss': jc.parsers.ss.parse,
|
||||||
'--uname': jc.parsers.uname.parse,
|
'--uname': jc.parsers.uname.parse,
|
||||||
'--uptime': jc.parsers.uptime.parse,
|
'--uptime': jc.parsers.uptime.parse,
|
||||||
'--w': jc.parsers.w.parse
|
'--w': jc.parsers.w.parse
|
||||||
|
117
jc/parsers/ss.py
Normal file
117
jc/parsers/ss.py
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
"""jc - JSON CLI output utility ss Parser
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
specify --ss as the first argument if the piped input is coming from ss
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
$ ss | jc --ss -p
|
||||||
|
[]
|
||||||
|
|
||||||
|
$ ss | jc --ss -p -r
|
||||||
|
[]
|
||||||
|
"""
|
||||||
|
import string
|
||||||
|
import jc.utils
|
||||||
|
|
||||||
|
|
||||||
|
def process(proc_data):
|
||||||
|
"""
|
||||||
|
Final processing to conform to the schema.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
proc_data (dictionary) raw structured data to process
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
dictionary structured data with the following schema:
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"ss": string,
|
||||||
|
"bar": boolean,
|
||||||
|
"baz": integer
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
|
||||||
|
# rebuild output for added semantic information
|
||||||
|
return proc_data
|
||||||
|
|
||||||
|
|
||||||
|
def parse(data, raw=False, quiet=False):
|
||||||
|
"""
|
||||||
|
Main text parsing function
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
data: (string) text data to parse
|
||||||
|
raw: (boolean) output preprocessed JSON if True
|
||||||
|
quiet: (boolean) suppress warning messages if True
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
dictionary raw or processed structured data
|
||||||
|
"""
|
||||||
|
|
||||||
|
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||||
|
compatible = ['linux']
|
||||||
|
|
||||||
|
if not quiet:
|
||||||
|
jc.utils.compatibility(__name__, compatible)
|
||||||
|
|
||||||
|
contain_colon = ['nl', 'p_raw', 'raw', 'udp', 'tcp', 'v_str', 'icmp6']
|
||||||
|
raw_output = []
|
||||||
|
cleandata = data.splitlines()
|
||||||
|
|
||||||
|
# Clear any blank lines
|
||||||
|
cleandata = list(filter(None, cleandata))
|
||||||
|
|
||||||
|
if cleandata:
|
||||||
|
# fix 'local address' to 'local_address', same with 'peer_address'
|
||||||
|
# split headers by whitespace and : = 8 columns
|
||||||
|
|
||||||
|
# only parse lines if col 0 is not whitespace
|
||||||
|
|
||||||
|
# These require additional rsplit(':') and replace/add cols 4,5,6,7
|
||||||
|
# check if ':' is in the field first...
|
||||||
|
# final columns may not have x:y and may just have *
|
||||||
|
# nl
|
||||||
|
# p_raw
|
||||||
|
# raw
|
||||||
|
# udp
|
||||||
|
# tcp
|
||||||
|
# v_str
|
||||||
|
# icmp6
|
||||||
|
|
||||||
|
# if % in col 4 or 6 then split that out to 'interface' field
|
||||||
|
header_text = cleandata[0].lower()
|
||||||
|
header_text = header_text.replace('local address:port', 'local_address:port')
|
||||||
|
header_text = header_text.replace('peer address:port', 'peer_address:port')
|
||||||
|
header_text = header_text.replace(':', ' ')
|
||||||
|
|
||||||
|
header_list = header_text.split()
|
||||||
|
|
||||||
|
for entry in cleandata[1:]:
|
||||||
|
if entry[0] not in string.whitespace:
|
||||||
|
entry_list = entry.split()
|
||||||
|
|
||||||
|
if entry[0] in contain_colon and ':' in entry_list[4]:
|
||||||
|
l_address = entry_list[4].rsplit(':', maxsplit=1)[0]
|
||||||
|
l_port = entry_list[4].rsplit(':', maxsplit=1)[1]
|
||||||
|
entry_list[4] = l_address
|
||||||
|
entry_list[5] = l_port
|
||||||
|
|
||||||
|
if entry[0] in contain_colon and ':' in entry_list[6]:
|
||||||
|
l_address = entry_list[6].rsplit(':', maxsplit=1)[0]
|
||||||
|
l_port = entry_list[6].rsplit(':', maxsplit=1)[1]
|
||||||
|
entry_list[6] = l_address
|
||||||
|
entry_list[7] = l_port
|
||||||
|
|
||||||
|
raw_output.append(entry_list)
|
||||||
|
|
||||||
|
if raw:
|
||||||
|
return raw_output
|
||||||
|
else:
|
||||||
|
return process(raw_output)
|
Reference in New Issue
Block a user