1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-07-15 01:24:29 +02:00

Merge pull request #2 from kellyjonbrazil/dev

Dev v0.6.2
This commit is contained in:
Kelly Brazil
2019-10-21 17:36:33 -07:00
committed by GitHub
5 changed files with 319 additions and 429 deletions

312
README.md
View File

@ -18,58 +18,38 @@ $ ls -l /usr/bin | jc --ls | jq .[] | jq 'select(.bytes > 50000000)'
} }
``` ```
The `jc` parsers can also be used as python modules by referencing them via:
```
import jc.parsers.[parser]
data = 'data to parse'
jc.parsers.[parser].parse(data)
```
In this case the output will be a python dictionary instead of JSON.
## Installation ## Installation
``` ```
$ pip3 install jc $ pip3 install jc
``` ```
## Usage ## Usage
```
jc [parser] [options]
```
`jc` accepts piped input from `STDIN` and outputs a JSON representation of the previous command's output to `STDOUT`. The JSON output can be compact or pretty formatted. `jc` accepts piped input from `STDIN` and outputs a JSON representation of the previous command's output to `STDOUT`. The JSON output can be compact or pretty formatted.
The first argument is required and identifies the command that is piping output to `jc` input. For example: Parsers:
- `--ls` enables the `ls` parser
- `--ifconfig` enables the `ifconfig` parser - `--ifconfig` enables the `ifconfig` parser
- `--ls` enables the `ls` parser
- `--netstat` enables the `netstat` parser - `--netstat` enables the `netstat` parser
- `--ps` enables the `ps` parser - `--ps` enables the `ps` parser
- `--route` enables the `route` parser - `--route` enables the `route` parser
The second `-p` argument is optional and specifies whether to pretty format the JSON output. Options:
- `-p` specifies whether to pretty format the JSON output
## Examples ## Examples
### ls
```
$ ls -l /bin | jc --ls -p
[
{
"filename": "bash",
"flags": "-r-xr-xr-x",
"links": 1,
"owner": "root",
"group": "wheel",
"bytes": 618416,
"date": "May 3 22:26"
},
{
"filename": "cat",
"flags": "-rwxr-xr-x",
"links": 1,
"owner": "root",
"group": "wheel",
"bytes": 23648,
"date": "May 3 22:26"
},
{
"filename": "chmod",
"flags": "-rwxr-xr-x",
"links": 1,
"owner": "root",
"group": "wheel",
"bytes": 30016,
"date": "May 3 22:26"
},
...
]
```
### ifconfig ### ifconfig
``` ```
$ ifconfig | jc --ifconfig -p $ ifconfig | jc --ifconfig -p
@ -154,132 +134,152 @@ $ ifconfig | jc --ifconfig -p
} }
] ]
``` ```
### ls
```
$ ls -l /bin | jc --ls -p
[
{
"filename": "bash",
"flags": "-r-xr-xr-x",
"links": 1,
"owner": "root",
"group": "wheel",
"bytes": 618416,
"date": "May 3 22:26"
},
{
"filename": "cat",
"flags": "-rwxr-xr-x",
"links": 1,
"owner": "root",
"group": "wheel",
"bytes": 23648,
"date": "May 3 22:26"
},
{
"filename": "chmod",
"flags": "-rwxr-xr-x",
"links": 1,
"owner": "root",
"group": "wheel",
"bytes": 30016,
"date": "May 3 22:26"
},
...
]
```
### netstat ### netstat
``` ```
$ netstat -p | jc --netstat -p $ netstat -p | jc --netstat -p
{ [
"client": { {
"tcp": { "session_protocol": "tcp",
"ipv4": [ "network_protocol": "ipv4",
{ "local_address": "localhost.localdo",
"local_address": "localhost.localdo", "local_port": "34480",
"local_port": "34480", "foreign_address": "lb-192-30-255-113",
"foreign_address": "lb-192-30-255-113", "foreign_port": "https",
"foreign_port": "https", "state": "ESTABLISHED",
"state": "ESTABLISHED", "pid": 53550,
"pid": 53550, "program_name": "git-remote-ht",
"program_name": "git-remote-ht", "receive_q": 0,
"receive_q": 0, "send_q": 0
"send_q": 0 },
}, {
{ "session_protocol": "tcp",
"local_address": "localhost.localdo", "network_protocol": "ipv4",
"local_port": "34478", "local_address": "localhost.localdo",
"foreign_address": "lb-192-30-255-113", "local_port": "34478",
"foreign_port": "https", "foreign_address": "lb-192-30-255-113",
"state": "ESTABLISHED", "foreign_port": "https",
"pid": 53550, "state": "ESTABLISHED",
"program_name": "git-remote-ht", "pid": 53550,
"receive_q": 0, "program_name": "git-remote-ht",
"send_q": 0 "receive_q": 0,
} "send_q": 0
]
}
} }
} ]
``` ```
``` ```
$ netstat -lp | jc --netstat -p $ netstat -lpn | jc --netstat -p
{ [
"server": { {
"tcp": { "session_protocol": "tcp",
"ipv4": [ "network_protocol": "ipv4",
{ "local_address": "127.0.0.1",
"local_address": "localhost", "local_port": "42351",
"local_port": "smtp", "foreign_address": "0.0.0.0",
"foreign_address": "0.0.0.0", "foreign_port": "*",
"foreign_port": "*", "state": "LISTEN",
"state": "LISTEN", "pid": 1112,
"pid": 1594, "program_name": "containerd",
"program_name": "master", "receive_q": 0,
"receive_q": 0, "send_q": 0
"send_q": 0 },
}, {
{ "session_protocol": "tcp",
"local_address": "0.0.0.0", "network_protocol": "ipv4",
"local_port": "ssh", "local_address": "127.0.0.53",
"foreign_address": "0.0.0.0", "local_port": "53",
"foreign_port": "*", "foreign_address": "0.0.0.0",
"state": "LISTEN", "foreign_port": "*",
"pid": 21918, "state": "LISTEN",
"program_name": "sshd", "pid": 885,
"receive_q": 0, "program_name": "systemd-resolve",
"send_q": 0 "receive_q": 0,
} "send_q": 0
], },
"ipv6": [ {
{ "session_protocol": "tcp",
"local_address": "localhost", "network_protocol": "ipv4",
"local_port": "smtp", "local_address": "0.0.0.0",
"foreign_address": "[::]", "local_port": "22",
"foreign_port": "*", "foreign_address": "0.0.0.0",
"state": "LISTEN", "foreign_port": "*",
"pid": 1594, "state": "LISTEN",
"program_name": "master", "pid": 1127,
"receive_q": 0, "program_name": "sshd",
"send_q": 0 "receive_q": 0,
}, "send_q": 0
{ },
"local_address": "[::]", {
"local_port": "ssh", "session_protocol": "tcp",
"foreign_address": "[::]", "network_protocol": "ipv6",
"foreign_port": "*", "local_address": "::",
"state": "LISTEN", "local_port": "22",
"pid": 21918, "foreign_address": "::",
"program_name": "sshd", "foreign_port": "*",
"receive_q": 0, "state": "LISTEN",
"send_q": 0 "pid": 1127,
} "program_name": "sshd",
] "receive_q": 0,
}, "send_q": 0
"udp": { },
"ipv4": [ {
{ "session_protocol": "udp",
"local_address": "0.0.0.0", "network_protocol": "ipv4",
"local_port": "bootpc", "local_address": "127.0.0.53",
"foreign_address": "0.0.0.0", "local_port": "53",
"foreign_port": "*", "foreign_address": "0.0.0.0",
"pid": 13903, "foreign_port": "*",
"program_name": "dhclient", "pid": 885,
"receive_q": 0, "program_name": "systemd-resolve",
"send_q": 0 "receive_q": 0,
}, "send_q": 0
{ },
"local_address": "localhost", {
"local_port": "323", "session_protocol": "udp",
"foreign_address": "0.0.0.0", "network_protocol": "ipv4",
"foreign_port": "*", "local_address": "192.168.71.131",
"pid": 30926, "local_port": "68",
"program_name": "chronyd", "foreign_address": "0.0.0.0",
"receive_q": 0, "foreign_port": "*",
"send_q": 0 "pid": 867,
} "program_name": "systemd-network",
], "receive_q": 0,
"ipv6": [ "send_q": 0
{
"local_address": "localhost",
"local_port": "323",
"foreign_address": "[::]",
"foreign_port": "*",
"pid": 30926,
"program_name": "chronyd",
"receive_q": 0,
"send_q": 0
}
]
}
} }
} ]
``` ```
### ps ### ps
``` ```

View File

@ -1,5 +1,9 @@
jc changelog jc changelog
20191021 v0.6.1
- Flatten netstat parser output
- Clean up argument parsing
20191018 v0.5.5 20191018 v0.5.5
- Fix netstat -p parsing for Ubuntu - Fix netstat -p parsing for Ubuntu
- Add ps parser - Add ps parser

View File

@ -14,33 +14,42 @@ import jc.parsers.route
def main(): def main():
pretty = False
data = sys.stdin.read() data = sys.stdin.read()
pretty = False
if len(sys.argv) < 2: if '-p' in sys.argv:
print('Error: jc') pretty = True
print(' Must specify parser. (e.g. --ls, --netstat, --ifconfig, etc.)')
print(' Use -p to pretty print')
print('Example: ls -al | jc --ls -p\n')
exit()
arg = sys.argv[1] if '--ifconfig' in sys.argv:
if len(sys.argv) > 2:
if sys.argv[2] == '-p':
pretty = True
if arg == '--ifconfig':
result = jc.parsers.ifconfig.parse(data) result = jc.parsers.ifconfig.parse(data)
elif arg == '--ls':
elif '--ls' in sys.argv:
result = jc.parsers.ls.parse(data) result = jc.parsers.ls.parse(data)
elif arg == '--netstat':
elif '--netstat' in sys.argv:
result = jc.parsers.netstat.parse(data) result = jc.parsers.netstat.parse(data)
elif arg == '--ps':
elif '--ps' in sys.argv:
result = jc.parsers.ps.parse(data) result = jc.parsers.ps.parse(data)
elif arg == '--route':
elif '--route' in sys.argv:
result = jc.parsers.route.parse(data) result = jc.parsers.route.parse(data)
else:
print('jc: missing arguments', file=sys.stderr)
print('Usage: jc [parser] [options]\n', file=sys.stderr)
print('Parsers:', file=sys.stderr)
print(' --ifconfig iconfig parser', file=sys.stderr)
print(' --ls ls parser', file=sys.stderr)
print(' --netstat netstat parser', file=sys.stderr)
print(' --ps ps parser', file=sys.stderr)
print(' --route route 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 -p --ls\n', file=sys.stderr)
exit()
# output resulting dictionary as json # output resulting dictionary as json
if pretty: if pretty:
print(json.dumps(result, indent=2)) print(json.dumps(result, indent=2))

View File

@ -11,154 +11,145 @@ Limitations:
Examples: Examples:
$ netstat -p | jc --netstat -p $ netstat -p | jc --netstat -p
{ [
"client": { {
"tcp": { "session_protocol": "tcp",
"ipv4": [ "network_protocol": "ipv4",
{ "local_address": "localhost.localdo",
"local_address": "localhost.localdo", "local_port": "34480",
"local_port": "34480", "foreign_address": "lb-192-30-255-113",
"foreign_address": "lb-192-30-255-113", "foreign_port": "https",
"foreign_port": "https", "state": "ESTABLISHED",
"state": "ESTABLISHED", "pid": 53550,
"pid": 53550, "program_name": "git-remote-ht",
"program_name": "git-remote-ht", "receive_q": 0,
"receive_q": 0, "send_q": 0
"send_q": 0 },
}, {
{ "session_protocol": "tcp",
"local_address": "localhost.localdo", "network_protocol": "ipv4",
"local_port": "34478", "local_address": "localhost.localdo",
"foreign_address": "lb-192-30-255-113", "local_port": "34478",
"foreign_port": "https", "foreign_address": "lb-192-30-255-113",
"state": "ESTABLISHED", "foreign_port": "https",
"pid": 53550, "state": "ESTABLISHED",
"program_name": "git-remote-ht", "pid": 53550,
"receive_q": 0, "program_name": "git-remote-ht",
"send_q": 0 "receive_q": 0,
} "send_q": 0
]
}
} }
} ]
$ netstat -lp | jc --netstat -p $ netstat -lpn | jc --netstat -p
{ [
"server": { {
"tcp": { "session_protocol": "tcp",
"ipv4": [ "network_protocol": "ipv4",
{ "local_address": "127.0.0.1",
"local_address": "localhost", "local_port": "42351",
"local_port": "smtp", "foreign_address": "0.0.0.0",
"foreign_address": "0.0.0.0", "foreign_port": "*",
"foreign_port": "*", "state": "LISTEN",
"state": "LISTEN", "pid": 1112,
"pid": 1594, "program_name": "containerd",
"program_name": "master", "receive_q": 0,
"receive_q": 0, "send_q": 0
"send_q": 0 },
}, {
{ "session_protocol": "tcp",
"local_address": "0.0.0.0", "network_protocol": "ipv4",
"local_port": "ssh", "local_address": "127.0.0.53",
"foreign_address": "0.0.0.0", "local_port": "53",
"foreign_port": "*", "foreign_address": "0.0.0.0",
"state": "LISTEN", "foreign_port": "*",
"pid": 21918, "state": "LISTEN",
"program_name": "sshd", "pid": 885,
"receive_q": 0, "program_name": "systemd-resolve",
"send_q": 0 "receive_q": 0,
} "send_q": 0
], },
"ipv6": [ {
{ "session_protocol": "tcp",
"local_address": "localhost", "network_protocol": "ipv4",
"local_port": "smtp", "local_address": "0.0.0.0",
"foreign_address": "[::]", "local_port": "22",
"foreign_port": "*", "foreign_address": "0.0.0.0",
"state": "LISTEN", "foreign_port": "*",
"pid": 1594, "state": "LISTEN",
"program_name": "master", "pid": 1127,
"receive_q": 0, "program_name": "sshd",
"send_q": 0 "receive_q": 0,
}, "send_q": 0
{ },
"local_address": "[::]", {
"local_port": "ssh", "session_protocol": "tcp",
"foreign_address": "[::]", "network_protocol": "ipv6",
"foreign_port": "*", "local_address": "::",
"state": "LISTEN", "local_port": "22",
"pid": 21918, "foreign_address": "::",
"program_name": "sshd", "foreign_port": "*",
"receive_q": 0, "state": "LISTEN",
"send_q": 0 "pid": 1127,
} "program_name": "sshd",
] "receive_q": 0,
}, "send_q": 0
"udp": { },
"ipv4": [ {
{ "session_protocol": "udp",
"local_address": "0.0.0.0", "network_protocol": "ipv4",
"local_port": "bootpc", "local_address": "127.0.0.53",
"foreign_address": "0.0.0.0", "local_port": "53",
"foreign_port": "*", "foreign_address": "0.0.0.0",
"pid": 13903, "foreign_port": "*",
"program_name": "dhclient", "pid": 885,
"receive_q": 0, "program_name": "systemd-resolve",
"send_q": 0 "receive_q": 0,
}, "send_q": 0
{ },
"local_address": "localhost", {
"local_port": "323", "session_protocol": "udp",
"foreign_address": "0.0.0.0", "network_protocol": "ipv4",
"foreign_port": "*", "local_address": "192.168.71.131",
"pid": 30926, "local_port": "68",
"program_name": "chronyd", "foreign_address": "0.0.0.0",
"receive_q": 0, "foreign_port": "*",
"send_q": 0 "pid": 867,
} "program_name": "systemd-network",
], "receive_q": 0,
"ipv6": [ "send_q": 0
{
"local_address": "localhost",
"local_port": "323",
"foreign_address": "[::]",
"foreign_port": "*",
"pid": 30926,
"program_name": "chronyd",
"receive_q": 0,
"send_q": 0
}
]
}
} }
} ]
""" """
import string import string
output = {} output = []
class state():
section = ''
session = ''
network = ''
client_tcp_ip4 = []
client_tcp_ip6 = []
client_udp_ip4 = []
client_udp_ip6 = []
server_tcp_ip4 = []
server_tcp_ip6 = []
server_udp_ip4 = []
server_udp_ip6 = []
def parse_line(entry): def parse_line(entry):
parsed_line = entry.split()
output_line = {} output_line = {}
if entry.find('tcp') == 0:
output_line['session_protocol'] = 'tcp'
if entry.find('p6') == 2:
output_line['network_protocol'] = 'ipv6'
else:
output_line['network_protocol'] = 'ipv4'
elif entry.find('udp') == 0:
output_line['session_protocol'] = 'udp'
if entry.find('p6') == 2:
output_line['network_protocol'] = 'ipv6'
else:
output_line['network_protocol'] = 'ipv4'
else:
return
parsed_line = entry.split()
output_line['local_address'] = parsed_line[3].rsplit(':', 1)[0] output_line['local_address'] = parsed_line[3].rsplit(':', 1)[0]
output_line['local_port'] = parsed_line[3].rsplit(':', 1)[-1] output_line['local_port'] = parsed_line[3].rsplit(':', 1)[-1]
output_line['foreign_address'] = parsed_line[4].rsplit(':', 1)[0] output_line['foreign_address'] = parsed_line[4].rsplit(':', 1)[0]
@ -189,11 +180,9 @@ def parse(data):
for line in cleandata: for line in cleandata:
if line.find('Active Internet connections (w/o servers)') == 0: if line.find('Active Internet connections (w/o servers)') == 0:
state.section = 'client'
continue continue
if line.find('Active Internet connections (only servers)') == 0: if line.find('Active Internet connections (only servers)') == 0:
state.section = 'server'
continue continue
if line.find('Proto') == 0: if line.find('Proto') == 0:
@ -202,119 +191,7 @@ def parse(data):
if line.find('Active UNIX') == 0: if line.find('Active UNIX') == 0:
break break
if state.section == 'client': output.append(parse_line(line))
if line.find('tcp') == 0:
state.session = 'tcp'
if line.find('p6') == 2:
state.network = 'ipv6'
else:
state.network = 'ipv4'
elif line.find('udp') == 0:
state.session = 'udp'
if line.find('p6') == 2:
state.network = 'ipv6'
else:
state.network = 'ipv4'
elif state.section == 'server':
if line.find('tcp') == 0:
state.session = 'tcp'
if line.find('p6') == 2:
state.network = 'ipv6'
else:
state.network = 'ipv4'
elif line.find('udp') == 0:
state.session = 'udp'
if line.find('p6') == 2:
state.network = 'ipv6'
else:
state.network = 'ipv4'
# client section clean_output = list(filter(None, output))
if state.section == 'client' and state.session == 'tcp' and state.network == 'ipv4': return clean_output
state.client_tcp_ip4.append(parse_line(line))
if state.section == 'client' and state.session == 'tcp' and state.network == 'ipv6':
state.client_tcp_ip6.append(parse_line(line))
if state.section == 'client' and state.session == 'udp' and state.network == 'ipv4':
state.client_udp_ip4.append(parse_line(line))
if state.section == 'client' and state.session == 'udp' and state.network == 'ipv6':
state.client_udp_ip6.append(parse_line(line))
# server section
if state.section == 'server' and state.session == 'tcp' and state.network == 'ipv4':
state.server_tcp_ip4.append(parse_line(line))
if state.section == 'server' and state.session == 'tcp' and state.network == 'ipv6':
state.server_tcp_ip6.append(parse_line(line))
if state.section == 'server' and state.session == 'udp' and state.network == 'ipv4':
state.server_udp_ip4.append(parse_line(line))
if state.section == 'server' and state.session == 'udp' and state.network == 'ipv6':
state.server_udp_ip6.append(parse_line(line))
state.session = ''
state.network = ''
# build dictionary
# client section
if state.client_tcp_ip4:
if 'client' not in output:
output['client'] = {}
if 'tcp' not in output['client']:
output['client']['tcp'] = {}
output['client']['tcp']['ipv4'] = state.client_tcp_ip4
if state.client_tcp_ip6:
if 'client' not in output:
output['client'] = {}
if 'tcp' not in output['client']:
output['client']['tcp'] = {}
output['client']['tcp']['ipv6'] = state.client_tcp_ip6
if state.client_udp_ip4:
if 'client' not in output:
output['client'] = {}
if 'udp' not in output['client']:
output['client']['udp'] = {}
output['client']['udp']['ipv4'] = state.client_udp_ip4
if state.client_udp_ip6:
if 'client' not in output:
output['client'] = {}
if 'udp' not in output['client']:
output['client']['udp'] = {}
output['client']['udp']['ipv6'] = state.client_udp_ip6
# server section
if state.server_tcp_ip4:
if 'server' not in output:
output['server'] = {}
if 'tcp' not in output['server']:
output['server']['tcp'] = {}
output['server']['tcp']['ipv4'] = state.server_tcp_ip4
if state.server_tcp_ip6:
if 'server' not in output:
output['server'] = {}
if 'tcp' not in output['server']:
output['server']['tcp'] = {}
output['server']['tcp']['ipv6'] = state.server_tcp_ip6
if state.server_udp_ip4:
if 'server' not in output:
output['server'] = {}
if 'udp' not in output['server']:
output['server']['udp'] = {}
output['server']['udp']['ipv4'] = state.server_udp_ip4
if state.server_udp_ip6:
if 'server' not in output:
output['server'] = {}
if 'udp' not in output['server']:
output['server']['udp'] = {}
output['server']['udp']['ipv6'] = state.server_udp_ip6
return output

View File

@ -5,7 +5,7 @@ with open('README.md', 'r') as f:
setuptools.setup( setuptools.setup(
name='jc', name='jc',
version='0.5.5', version='0.6.2',
author='Kelly Brazil', author='Kelly Brazil',
author_email='kellyjonbrazil@gmail.com', author_email='kellyjonbrazil@gmail.com',
description='This tool serializes the output of popular command line tools to structured JSON output.', description='This tool serializes the output of popular command line tools to structured JSON output.',