From b15c8c352a87a9b3b1dece28af0287ef71ca02d0 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 08:46:54 -0700 Subject: [PATCH 01/13] simplify state variables --- jc/parsers/iptables.py | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/jc/parsers/iptables.py b/jc/parsers/iptables.py index 2d6756e2..bbc0c0d3 100644 --- a/jc/parsers/iptables.py +++ b/jc/parsers/iptables.py @@ -325,42 +325,40 @@ $ sudo iptables -vnL -t filter | jc --iptables -p """ -class state(): +def parse(data): output = [] chain = {} headers = [] - -def parse(data): cleandata = data.splitlines() for line in cleandata: if line.find('Chain') == 0: - state.output.append(state.chain) - state.chain = {} - state.headers = [] + output.append(chain) + chain = {} + headers = [] parsed_line = line.split() - state.chain['chain'] = parsed_line[1] - state.chain['rules'] = [] + chain['chain'] = parsed_line[1] + chain['rules'] = [] continue if line.find('target') == 0 or line.find('pkts') == 1: - state.headers = [] - state.headers = [h for h in ' '.join(line.strip().split()).split() if h] - state.headers.append("options") + headers = [] + headers = [h for h in ' '.join(line.strip().split()).split() if h] + headers.append("options") continue else: - rule = line.split(maxsplit=len(state.headers) - 1) - temp_rule = dict(zip(state.headers, rule)) + rule = line.split(maxsplit=len(headers) - 1) + temp_rule = dict(zip(headers, rule)) if temp_rule: - state.chain['rules'].append(temp_rule) + chain['rules'].append(temp_rule) - state.output = list(filter(None, state.output)) + output = list(filter(None, output)) - return state.output + return output From 679ae6d5dc7af26240dc00d8bc6499950f81d457 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 09:20:11 -0700 Subject: [PATCH 02/13] version bump --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 43fef882..6bc1a35b 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open('README.md', 'r') as f: setuptools.setup( name='jc', - version='0.8.1', + version='0.9.0', author='Kelly Brazil', author_email='kellyjonbrazil@gmail.com', description='This tool serializes the output of popular command line tools to structured JSON output.', From 56901788dee154890e70269ad48d4b22bb8c5437 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 09:51:29 -0700 Subject: [PATCH 03/13] stop blocking when no pipe and enhance help text --- jc/jc.py | 49 ++++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/jc/jc.py b/jc/jc.py index 2dc20eb5..4ccaf7ee 100755 --- a/jc/jc.py +++ b/jc/jc.py @@ -20,13 +20,41 @@ import jc.parsers.route import jc.parsers.uname +def helptext(): + print('Usage: jc [parser] [options]\n', file=sys.stderr) + print('Parsers:', file=sys.stderr) + print(' --df df parser', file=sys.stderr) + print(' --env env parser', file=sys.stderr) + print(' --free free parser', file=sys.stderr) + print(' --ifconfig iconfig parser', file=sys.stderr) + print(' --iptables iptables parser', file=sys.stderr) + print(' --ls ls parser', file=sys.stderr) + print(' --lsblk lsblk parser', file=sys.stderr) + print(' --mount mount parser', file=sys.stderr) + print(' --netstat netstat parser', file=sys.stderr) + print(' --ps ps parser', file=sys.stderr) + print(' --route route parser', file=sys.stderr) + print(' --uname uname parser\n', file=sys.stderr) + print('Options:', file=sys.stderr) + print(' -p pretty print output\n', file=sys.stderr) + print('Example:', file=sys.stderr) + print(' ls -al | jc --ls -p\n', file=sys.stderr) + + def main(): + if sys.stdin.isatty(): + print('jc: missing piped data\n', file=sys.stderr) + helptext() + exit() + data = sys.stdin.read() pretty = False + # options if '-p' in sys.argv: pretty = True + # parsers if '--df' in sys.argv: result = jc.parsers.df.parse(data) @@ -64,25 +92,8 @@ def main(): result = jc.parsers.uname.parse(data) else: - print('jc: missing arguments\n', file=sys.stderr) - print('Usage: jc [parser] [options]\n', file=sys.stderr) - print('Parsers:', file=sys.stderr) - print(' --df df parser', file=sys.stderr) - print(' --env env parser', file=sys.stderr) - print(' --free free parser', file=sys.stderr) - print(' --ifconfig iconfig parser', file=sys.stderr) - print(' --iptables iptables parser', file=sys.stderr) - print(' --ls ls parser', file=sys.stderr) - print(' --lsblk lsblk parser', file=sys.stderr) - print(' --mount mount parser', file=sys.stderr) - print(' --netstat netstat parser', file=sys.stderr) - print(' --ps ps parser', file=sys.stderr) - print(' --route route parser', file=sys.stderr) - print(' --uname uname parser\n', file=sys.stderr) - print('Options:', file=sys.stderr) - print(' -p pretty print output\n', file=sys.stderr) - print('Example:', file=sys.stderr) - print(' ls -al | jc --ls -p\n', file=sys.stderr) + print('jc: missing or incorrect arguments\n', file=sys.stderr) + helptext() exit() # output resulting dictionary as json From 802f1510eb6d621f9c760f28b83f16a4781b8d93 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 10:27:05 -0700 Subject: [PATCH 04/13] tighten if statements --- jc/parsers/iptables.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jc/parsers/iptables.py b/jc/parsers/iptables.py index bbc0c0d3..bb0a1328 100644 --- a/jc/parsers/iptables.py +++ b/jc/parsers/iptables.py @@ -346,7 +346,7 @@ def parse(data): continue - if line.find('target') == 0 or line.find('pkts') == 1: + elif line.find('target') == 0 or line.find('pkts') == 1: headers = [] headers = [h for h in ' '.join(line.strip().split()).split() if h] headers.append("options") From 3db758764e50666e5ae40de8d89180de2ef5bc28 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 14:05:47 -0700 Subject: [PATCH 05/13] add jobs parser --- changelog.txt | 6 ++++ jc/jc.py | 5 ++++ jc/parsers/jobs.py | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 jc/parsers/jobs.py diff --git a/changelog.txt b/changelog.txt index 57f7fa74..89a2ca63 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ jc changelog +2019xxxx v0.9.0 +- No blocking if no piped data +- Better help text +- Add jobs parser +- Clean up iptables parser code + 20191022 v0.8.1 - Add env parser - Add df parser diff --git a/jc/jc.py b/jc/jc.py index 4ccaf7ee..b3be5805 100755 --- a/jc/jc.py +++ b/jc/jc.py @@ -11,6 +11,7 @@ import jc.parsers.env import jc.parsers.free import jc.parsers.ifconfig import jc.parsers.iptables +import jc.parsers.jobs import jc.parsers.ls import jc.parsers.lsblk import jc.parsers.mount @@ -28,6 +29,7 @@ def helptext(): print(' --free free parser', file=sys.stderr) print(' --ifconfig iconfig parser', file=sys.stderr) print(' --iptables iptables parser', file=sys.stderr) + print(' --jobs jobs parser', file=sys.stderr) print(' --ls ls parser', file=sys.stderr) print(' --lsblk lsblk parser', file=sys.stderr) print(' --mount mount parser', file=sys.stderr) @@ -70,6 +72,9 @@ def main(): elif '--iptables' in sys.argv: result = jc.parsers.iptables.parse(data) + elif '--jobs' in sys.argv: + result = jc.parsers.jobs.parse(data) + elif '--ls' in sys.argv: result = jc.parsers.ls.parse(data) diff --git a/jc/parsers/jobs.py b/jc/parsers/jobs.py new file mode 100644 index 00000000..70d7606f --- /dev/null +++ b/jc/parsers/jobs.py @@ -0,0 +1,72 @@ +"""jc - JSON CLI output utility jobs Parser + +Usage: + specify --jobs as the first argument if the piped input is coming from jobs + +Examples: + + +""" + + +import string + + +def parse(data): + output = [] + + linedata = data.splitlines() + + # Clear any blank lines + cleandata = list(filter(None, linedata)) + + if cleandata: + + for entry in cleandata: + output_line = {} + remainder = [] + job_number = '' + pid = '' + job_history = '' + + parsed_line = entry.split(maxsplit=2) + + # check if -l was used + if parsed_line[1][0] in string.digits: + pid = parsed_line.pop(1) + remainder = parsed_line.pop(1) + job_number = parsed_line.pop(0) + remainder = remainder.split(maxsplit=1) + + # rebuild parsed_line + parsed_line = [] + + for r in remainder: + parsed_line.append(r) + + parsed_line.insert(0, job_number) + + # check for + or - in first field + if parsed_line[0].find('+') != -1: + job_history = 'current' + parsed_line[0] = parsed_line[0].rstrip('+') + + if parsed_line[0].find('-') != -1: + job_history = 'previous' + parsed_line[0] = parsed_line[0].rstrip('-') + + # clean up first field + parsed_line[0] = parsed_line[0].lstrip('[').rstrip(']') + + # create list of dictionaries + output_line['job_number'] = int(parsed_line[0]) + if pid: + output_line['pid'] = int(pid) + if job_history: + output_line['history'] = job_history + output_line['status'] = parsed_line[1] + output_line['command'] = parsed_line[2] + + output.append(output_line) + + return output From 649c0aa7c157f87691cc8eeac64c747e81f63594 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 14:10:10 -0700 Subject: [PATCH 06/13] add documentation --- README.md | 39 +++++++++++++++++++++++++++++++++++++++ jc/parsers/jobs.py | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f5cd1281..df9a2fd4 100755 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ jc [parser] [options] - `--free` enables the `free` parser - `--ifconfig` enables the `ifconfig` parser - `--iptables` enables the `iptables` parser +- `--jobs` enables the `jobs` parser - `--ls` enables the `ls` parser - `--lsblk` enables the `lsblk` parser - `--mount` enables the `mount` parser @@ -549,6 +550,44 @@ $ sudo iptables -vnL -t filter | jc --iptables -p ... ] ``` +### jobs +``` +$ jobs -l | jc --jobs -p +[ + { + "job_number": 1, + "pid": 14798, + "status": "Running", + "command": "sleep 10000 &" + }, + { + "job_number": 2, + "pid": 14799, + "status": "Running", + "command": "sleep 10001 &" + }, + { + "job_number": 3, + "pid": 14800, + "status": "Running", + "command": "sleep 10002 &" + }, + { + "job_number": 4, + "pid": 14814, + "history": "previous", + "status": "Running", + "command": "sleep 10003 &" + }, + { + "job_number": 5, + "pid": 14815, + "history": "current", + "status": "Running", + "command": "sleep 10004 &" + } +] +``` ### ls ``` $ ls -l /bin | jc --ls -p diff --git a/jc/parsers/jobs.py b/jc/parsers/jobs.py index 70d7606f..2ebac438 100644 --- a/jc/parsers/jobs.py +++ b/jc/parsers/jobs.py @@ -3,9 +3,45 @@ Usage: specify --jobs as the first argument if the piped input is coming from jobs + Also supports the -l option + Examples: - +$ jobs -l | jc --jobs -p +[ + { + "job_number": 1, + "pid": 14798, + "status": "Running", + "command": "sleep 10000 &" + }, + { + "job_number": 2, + "pid": 14799, + "status": "Running", + "command": "sleep 10001 &" + }, + { + "job_number": 3, + "pid": 14800, + "status": "Running", + "command": "sleep 10002 &" + }, + { + "job_number": 4, + "pid": 14814, + "history": "previous", + "status": "Running", + "command": "sleep 10003 &" + }, + { + "job_number": 5, + "pid": 14815, + "history": "current", + "status": "Running", + "command": "sleep 10004 &" + } +] """ From 9c47fd05bf716c2e18ebf4da41b1a46b972b2518 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 14:11:13 -0700 Subject: [PATCH 07/13] doco fix --- jc/parsers/jobs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jc/parsers/jobs.py b/jc/parsers/jobs.py index 2ebac438..bc3ec39b 100644 --- a/jc/parsers/jobs.py +++ b/jc/parsers/jobs.py @@ -5,7 +5,7 @@ Usage: Also supports the -l option -Examples: +Example: $ jobs -l | jc --jobs -p [ From a1a3de32ec14d6ef433e334b9694856698c26d41 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 17:22:25 -0700 Subject: [PATCH 08/13] add lsof parser --- jc/jc.py | 5 +++++ jc/parsers/lsof.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 jc/parsers/lsof.py diff --git a/jc/jc.py b/jc/jc.py index b3be5805..598f6dae 100755 --- a/jc/jc.py +++ b/jc/jc.py @@ -14,6 +14,7 @@ import jc.parsers.iptables import jc.parsers.jobs import jc.parsers.ls import jc.parsers.lsblk +import jc.parsers.lsof import jc.parsers.mount import jc.parsers.netstat import jc.parsers.ps @@ -32,6 +33,7 @@ def helptext(): print(' --jobs jobs parser', file=sys.stderr) print(' --ls ls parser', file=sys.stderr) print(' --lsblk lsblk parser', file=sys.stderr) + print(' --lsof lsof parser', file=sys.stderr) print(' --mount mount parser', file=sys.stderr) print(' --netstat netstat parser', file=sys.stderr) print(' --ps ps parser', file=sys.stderr) @@ -81,6 +83,9 @@ def main(): elif '--lsblk' in sys.argv: result = jc.parsers.lsblk.parse(data) + elif '--lsof' in sys.argv: + result = jc.parsers.lsof.parse(data) + elif '--mount' in sys.argv: result = jc.parsers.mount.parse(data) diff --git a/jc/parsers/lsof.py b/jc/parsers/lsof.py new file mode 100644 index 00000000..8a102f38 --- /dev/null +++ b/jc/parsers/lsof.py @@ -0,0 +1,54 @@ +"""jc - JSON CLI output utility lsof Parser + +Usage: + specify --lsof as the first argument if the piped input is coming from lsof + + Limitations: + No additional columns are supported + +Example: + + +""" + + +def parse(data): + output = [] + + linedata = data.splitlines() + + # Clear any blank lines + cleandata = list(filter(None, linedata)) + + if cleandata: + + # find column value of last character of each header + header_row = cleandata.pop(0) + headers = header_row.split() + header_spec = [] + + for i, h in enumerate(headers): + # header tuple is (index, header_name, col) + header_spec.append((i, h, header_row.find(h) + len(h))) + + # parse lines + for entry in cleandata: + output_line = {} + + # normalize data by inserting -- for missing data + temp_line = entry.split(maxsplit=len(headers) - 1) + + for spec in header_spec: + if spec[1] == 'COMMAND' or spec[1] == 'NAME': + continue + if entry[spec[2] - 1] == ' ': + temp_line.insert(spec[0], '--') + + name = ' '.join(temp_line[9:]) + fixed_line = temp_line[0:9] + fixed_line.append(name) + + output_line = dict(zip(headers, fixed_line)) + output.append(output_line) + + return output From 91eb9a4d13e9254bd5bbde931196904c1947a28e Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 17:27:23 -0700 Subject: [PATCH 09/13] use None instead of -- --- jc/parsers/lsof.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jc/parsers/lsof.py b/jc/parsers/lsof.py index 8a102f38..04dccb78 100644 --- a/jc/parsers/lsof.py +++ b/jc/parsers/lsof.py @@ -35,14 +35,14 @@ def parse(data): for entry in cleandata: output_line = {} - # normalize data by inserting -- for missing data + # normalize data by inserting Null for missing data temp_line = entry.split(maxsplit=len(headers) - 1) for spec in header_spec: if spec[1] == 'COMMAND' or spec[1] == 'NAME': continue if entry[spec[2] - 1] == ' ': - temp_line.insert(spec[0], '--') + temp_line.insert(spec[0], None) name = ' '.join(temp_line[9:]) fixed_line = temp_line[0:9] From 29c47c03a64f9c6b0f44d34be5449396654849b5 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 17:37:25 -0700 Subject: [PATCH 10/13] documentation update --- README.md | 68 ++++++++++++++++++++++++++++++++++++++++++++++ changelog.txt | 3 +- jc/parsers/lsof.py | 65 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 134 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index df9a2fd4..8914fe92 100755 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ jc [parser] [options] - `--jobs` enables the `jobs` parser - `--ls` enables the `ls` parser - `--lsblk` enables the `lsblk` parser +- `--lsof` enables the `lsof` parser - `--mount` enables the `mount` parser - `--netstat` enables the `netstat` parser - `--ps` enables the `ps` parser @@ -670,6 +671,73 @@ $ lsblk | jc --lsblk -p } ] ``` +### lsof +``` +$ sudo lsof | jc --lsof -p +[ + { + "COMMAND": "systemd", + "PID": "1", + "TID": null, + "USER": "root", + "FD": "cwd", + "TYPE": "DIR", + "DEVICE": "253,0", + "SIZE/OFF": "224", + "NODE": "64", + "NAME": "/" + }, + { + "COMMAND": "systemd", + "PID": "1", + "TID": null, + "USER": "root", + "FD": "rtd", + "TYPE": "DIR", + "DEVICE": "253,0", + "SIZE/OFF": "224", + "NODE": "64", + "NAME": "/" + }, + { + "COMMAND": "systemd", + "PID": "1", + "TID": null, + "USER": "root", + "FD": "txt", + "TYPE": "REG", + "DEVICE": "253,0", + "SIZE/OFF": "1624520", + "NODE": "50360451", + "NAME": "/usr/lib/systemd/systemd" + }, + { + "COMMAND": "systemd", + "PID": "1", + "TID": null, + "USER": "root", + "FD": "mem", + "TYPE": "REG", + "DEVICE": "253,0", + "SIZE/OFF": "20064", + "NODE": "8146", + "NAME": "/usr/lib64/libuuid.so.1.3.0" + }, + { + "COMMAND": "systemd", + "PID": "1", + "TID": null, + "USER": "root", + "FD": "mem", + "TYPE": "REG", + "DEVICE": "253,0", + "SIZE/OFF": "265600", + "NODE": "8147", + "NAME": "/usr/lib64/libblkid.so.1.1.0" + }, + ... +] +``` ### mount ``` $ mount | jc --mount -p diff --git a/changelog.txt b/changelog.txt index 89a2ca63..19881397 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,9 +1,10 @@ jc changelog 2019xxxx v0.9.0 +- Add jobs parser +- Add lsof parser - No blocking if no piped data - Better help text -- Add jobs parser - Clean up iptables parser code 20191022 v0.8.1 diff --git a/jc/parsers/lsof.py b/jc/parsers/lsof.py index 04dccb78..ea26d757 100644 --- a/jc/parsers/lsof.py +++ b/jc/parsers/lsof.py @@ -8,7 +8,70 @@ Usage: Example: - +$ sudo lsof | jc --lsof -p +[ + { + "COMMAND": "systemd", + "PID": "1", + "TID": null, + "USER": "root", + "FD": "cwd", + "TYPE": "DIR", + "DEVICE": "253,0", + "SIZE/OFF": "224", + "NODE": "64", + "NAME": "/" + }, + { + "COMMAND": "systemd", + "PID": "1", + "TID": null, + "USER": "root", + "FD": "rtd", + "TYPE": "DIR", + "DEVICE": "253,0", + "SIZE/OFF": "224", + "NODE": "64", + "NAME": "/" + }, + { + "COMMAND": "systemd", + "PID": "1", + "TID": null, + "USER": "root", + "FD": "txt", + "TYPE": "REG", + "DEVICE": "253,0", + "SIZE/OFF": "1624520", + "NODE": "50360451", + "NAME": "/usr/lib/systemd/systemd" + }, + { + "COMMAND": "systemd", + "PID": "1", + "TID": null, + "USER": "root", + "FD": "mem", + "TYPE": "REG", + "DEVICE": "253,0", + "SIZE/OFF": "20064", + "NODE": "8146", + "NAME": "/usr/lib64/libuuid.so.1.3.0" + }, + { + "COMMAND": "systemd", + "PID": "1", + "TID": null, + "USER": "root", + "FD": "mem", + "TYPE": "REG", + "DEVICE": "253,0", + "SIZE/OFF": "265600", + "NODE": "8147", + "NAME": "/usr/lib64/libblkid.so.1.1.0" + }, + ... +] """ From 66772392ae78ef394e22070b127416b1d5b01332 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 18:04:54 -0700 Subject: [PATCH 11/13] add lsmod parser --- changelog.txt | 1 + jc/jc.py | 5 +++++ jc/parsers/lsmod.py | 26 ++++++++++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 jc/parsers/lsmod.py diff --git a/changelog.txt b/changelog.txt index 19881397..f006c53f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,7 @@ jc changelog 2019xxxx v0.9.0 - Add jobs parser - Add lsof parser +- Add lsmod parser - No blocking if no piped data - Better help text - Clean up iptables parser code diff --git a/jc/jc.py b/jc/jc.py index 598f6dae..f9de4665 100755 --- a/jc/jc.py +++ b/jc/jc.py @@ -14,6 +14,7 @@ import jc.parsers.iptables import jc.parsers.jobs import jc.parsers.ls import jc.parsers.lsblk +import jc.parsers.lsmod import jc.parsers.lsof import jc.parsers.mount import jc.parsers.netstat @@ -33,6 +34,7 @@ def helptext(): print(' --jobs jobs parser', file=sys.stderr) print(' --ls ls parser', file=sys.stderr) print(' --lsblk lsblk parser', file=sys.stderr) + print(' --lsmod lsmod parser', file=sys.stderr) print(' --lsof lsof parser', file=sys.stderr) print(' --mount mount parser', file=sys.stderr) print(' --netstat netstat parser', file=sys.stderr) @@ -83,6 +85,9 @@ def main(): elif '--lsblk' in sys.argv: result = jc.parsers.lsblk.parse(data) + elif '--lsmod' in sys.argv: + result = jc.parsers.lsmod.parse(data) + elif '--lsof' in sys.argv: result = jc.parsers.lsof.parse(data) diff --git a/jc/parsers/lsmod.py b/jc/parsers/lsmod.py new file mode 100644 index 00000000..446f857a --- /dev/null +++ b/jc/parsers/lsmod.py @@ -0,0 +1,26 @@ +"""jc - JSON CLI output utility lsmod Parser + +Usage: + specify --lsmod as the first argument if the piped input is coming from lsmod + +Example: + + +""" + + +def parse(data): + + # code adapted from Conor Heine at: + # https://gist.github.com/cahna/43a1a3ff4d075bcd71f9d7120037a501 + + cleandata = data.splitlines() + headers = [h for h in ' '.join(cleandata[0].strip().split()).split() if h] + + raw_data = map(lambda s: s.strip().split(None, len(headers) - 1), cleandata[1:]) + output = [dict(zip(headers, r)) for r in raw_data] + + for entry in output: + entry['NAME'] = entry['NAME'].encode('ascii', errors='ignore').decode() + + return output From 58ae976db0165730a75dd7450c698d2727a354ca Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 18:30:55 -0700 Subject: [PATCH 12/13] documentation update --- README.md | 55 +++++++++++++++++++++++++++++++++++++++++ jc/parsers/lsmod.py | 60 ++++++++++++++++++++++++++++++++++++++++++--- setup.py | 2 +- 3 files changed, 113 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8914fe92..98d9a00f 100755 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ jc [parser] [options] - `--jobs` enables the `jobs` parser - `--ls` enables the `ls` parser - `--lsblk` enables the `lsblk` parser +- `--lsmod` enables the `lsmod` parser - `--lsof` enables the `lsof` parser - `--mount` enables the `mount` parser - `--netstat` enables the `netstat` parser @@ -671,6 +672,60 @@ $ lsblk | jc --lsblk -p } ] ``` +### lsmod +``` +$ lsmod | jc --lsmod -p +[ + { + "Module": "nf_nat_ipv4", + "Size": "14115", + "Used": "1", + "By": [ + "iptable_nat" + ] + }, + { + "Module": "nf_nat", + "Size": "26583", + "Used": "3", + "By": [ + "nf_nat_ipv4", + "nf_nat_ipv6", + "nf_nat_masquerade_ipv4" + ] + }, + { + "Module": "iptable_mangle", + "Size": "12695", + "Used": "1" + }, + { + "Module": "iptable_security", + "Size": "12705", + "Used": "1" + }, + { + "Module": "iptable_raw", + "Size": "12678", + "Used": "1" + }, + { + "Module": "nf_conntrack", + "Size": "139224", + "Used": "7", + "By": [ + "nf_nat", + "nf_nat_ipv4", + "nf_nat_ipv6", + "xt_conntrack", + "nf_nat_masquerade_ipv4", + "nf_conntrack_ipv4", + "nf_conntrack_ipv6" + ] + }, + ... +] +``` ### lsof ``` $ sudo lsof | jc --lsof -p diff --git a/jc/parsers/lsmod.py b/jc/parsers/lsmod.py index 446f857a..625e38cd 100644 --- a/jc/parsers/lsmod.py +++ b/jc/parsers/lsmod.py @@ -5,7 +5,57 @@ Usage: Example: - +$ lsmod | jc --lsmod -p +[ + { + "Module": "nf_nat_ipv4", + "Size": "14115", + "Used": "1", + "By": [ + "iptable_nat" + ] + }, + { + "Module": "nf_nat", + "Size": "26583", + "Used": "3", + "By": [ + "nf_nat_ipv4", + "nf_nat_ipv6", + "nf_nat_masquerade_ipv4" + ] + }, + { + "Module": "iptable_mangle", + "Size": "12695", + "Used": "1" + }, + { + "Module": "iptable_security", + "Size": "12705", + "Used": "1" + }, + { + "Module": "iptable_raw", + "Size": "12678", + "Used": "1" + }, + { + "Module": "nf_conntrack", + "Size": "139224", + "Used": "7", + "By": [ + "nf_nat", + "nf_nat_ipv4", + "nf_nat_ipv6", + "xt_conntrack", + "nf_nat_masquerade_ipv4", + "nf_conntrack_ipv4", + "nf_conntrack_ipv6" + ] + }, + ... +] """ @@ -17,10 +67,14 @@ def parse(data): cleandata = data.splitlines() headers = [h for h in ' '.join(cleandata[0].strip().split()).split() if h] + headers.pop(-1) + headers.append('By') + raw_data = map(lambda s: s.strip().split(None, len(headers) - 1), cleandata[1:]) output = [dict(zip(headers, r)) for r in raw_data] - for entry in output: - entry['NAME'] = entry['NAME'].encode('ascii', errors='ignore').decode() + for mod in output: + if 'By' in mod: + mod['By'] = mod['By'].split(',') return output diff --git a/setup.py b/setup.py index 6bc1a35b..f9d24df8 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open('README.md', 'r') as f: setuptools.setup( name='jc', - version='0.9.0', + version='0.9.1', author='Kelly Brazil', author_email='kellyjonbrazil@gmail.com', description='This tool serializes the output of popular command line tools to structured JSON output.', From 2cc1b1bd5451f31d71b0e2236bdee0ce2b25b5d7 Mon Sep 17 00:00:00 2001 From: Kelly Brazil Date: Wed, 23 Oct 2019 18:39:24 -0700 Subject: [PATCH 13/13] version bump --- changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index f006c53f..df94d9ca 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,6 @@ jc changelog -2019xxxx v0.9.0 +20191023 v0.9.1 - Add jobs parser - Add lsof parser - Add lsmod parser