mirror of
https://github.com/kellyjonbrazil/jc.git
synced 2025-07-15 01:24:29 +02:00
507
README.md
507
README.md
@ -1,7 +1,7 @@
|
|||||||
# JC
|
# JC
|
||||||
JSON CLI output utility
|
JSON CLI output utility
|
||||||
|
|
||||||
`jc` is used to JSONify the output of many standard linux cli tools for easier parsing in scripts. Parsers for `ls`, `ifconfig`, `ps`, `route`, and `netstat` are currently included and more can be added via modules.
|
`jc` is used to JSONify the output of many standard linux cli tools for easier parsing in scripts. See the **Parsers** section for supported commands.
|
||||||
|
|
||||||
This allows further command line processing of output with tools like `jq` simply by piping commands:
|
This allows further command line processing of output with tools like `jq` simply by piping commands:
|
||||||
|
|
||||||
@ -59,17 +59,93 @@ 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.
|
||||||
|
|
||||||
Parsers:
|
### Parsers
|
||||||
|
- `--df` enables the `df` parser
|
||||||
|
- `--env` enables the `env` parser
|
||||||
|
- `--free` enables the `free` parser
|
||||||
- `--ifconfig` enables the `ifconfig` parser
|
- `--ifconfig` enables the `ifconfig` parser
|
||||||
|
- `--iptables` enables the `iptables` parser
|
||||||
- `--ls` enables the `ls` parser
|
- `--ls` enables the `ls` parser
|
||||||
|
- `--lsblk` enables the `lsblk` parser
|
||||||
|
- `--mount` enables the `mount` 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
|
||||||
|
- `--uname` enables the `uname -a` parser
|
||||||
|
|
||||||
Options:
|
### Options
|
||||||
- `-p` specifies whether to pretty format the JSON output
|
- `-p` specifies whether to pretty format the JSON output
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
### df
|
||||||
|
```
|
||||||
|
$ df | jc --df -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"Filesystem": "udev",
|
||||||
|
"1K-blocks": "977500",
|
||||||
|
"Used": "0",
|
||||||
|
"Available": "977500",
|
||||||
|
"Use%": "0%",
|
||||||
|
"Mounted": "/dev"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Filesystem": "tmpfs",
|
||||||
|
"1K-blocks": "201732",
|
||||||
|
"Used": "1180",
|
||||||
|
"Available": "200552",
|
||||||
|
"Use%": "1%",
|
||||||
|
"Mounted": "/run"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Filesystem": "/dev/sda2",
|
||||||
|
"1K-blocks": "20508240",
|
||||||
|
"Used": "5747284",
|
||||||
|
"Available": "13696152",
|
||||||
|
"Use%": "30%",
|
||||||
|
"Mounted": "/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Filesystem": "tmpfs",
|
||||||
|
"1K-blocks": "1008648",
|
||||||
|
"Used": "0",
|
||||||
|
"Available": "1008648",
|
||||||
|
"Use%": "0%",
|
||||||
|
"Mounted": "/dev/shm"
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
|
### env
|
||||||
|
```
|
||||||
|
$ env | jc --env -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"TERM": "xterm-256color"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHELL": "/bin/bash"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"USER": "root"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PATH": "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PWD": "/bin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"LANG": "en_US.UTF-8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"HOME": "/root"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_": "/usr/bin/env"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
### ifconfig
|
### ifconfig
|
||||||
```
|
```
|
||||||
$ ifconfig | jc --ifconfig -p
|
$ ifconfig | jc --ifconfig -p
|
||||||
@ -154,6 +230,325 @@ $ ifconfig | jc --ifconfig -p
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
### iptables
|
||||||
|
```
|
||||||
|
$ sudo iptables -L -t nat | jc --iptables -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"chain": "PREROUTING",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"target": "PREROUTING_direct",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"source": "anywhere",
|
||||||
|
"destination": "anywhere"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "PREROUTING_ZONES_SOURCE",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"source": "anywhere",
|
||||||
|
"destination": "anywhere"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "PREROUTING_ZONES",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"source": "anywhere",
|
||||||
|
"destination": "anywhere"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "DOCKER",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"source": "anywhere",
|
||||||
|
"destination": "anywhere",
|
||||||
|
"options": "ADDRTYPE match dst-type LOCAL"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chain": "INPUT",
|
||||||
|
"rules": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chain": "OUTPUT",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"target": "OUTPUT_direct",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"source": "anywhere",
|
||||||
|
"destination": "anywhere"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "DOCKER",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"source": "anywhere",
|
||||||
|
"destination": "!loopback/8",
|
||||||
|
"options": "ADDRTYPE match dst-type LOCAL"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
|
```
|
||||||
|
$ sudo iptables -vnL -t filter | jc --iptables -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"chain": "INPUT",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"pkts": "1571",
|
||||||
|
"bytes": "3394K",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "ctstate RELATED,ESTABLISHED"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "lo",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "711",
|
||||||
|
"bytes": "60126",
|
||||||
|
"target": "INPUT_direct",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "711",
|
||||||
|
"bytes": "60126",
|
||||||
|
"target": "INPUT_ZONES_SOURCE",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "711",
|
||||||
|
"bytes": "60126",
|
||||||
|
"target": "INPUT_ZONES",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "DROP",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "ctstate INVALID"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "710",
|
||||||
|
"bytes": "60078",
|
||||||
|
"target": "REJECT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "reject-with icmp-host-prohibited"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chain": "FORWARD",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "DOCKER-ISOLATION",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "DOCKER",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "docker0",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "docker0",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "ctstate RELATED,ESTABLISHED"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "docker0",
|
||||||
|
"out": "!docker0",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "docker0",
|
||||||
|
"out": "docker0",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "ctstate RELATED,ESTABLISHED"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "lo",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "FORWARD_direct",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "FORWARD_IN_ZONES_SOURCE",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "FORWARD_IN_ZONES",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "FORWARD_OUT_ZONES_SOURCE",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "FORWARD_OUT_ZONES",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "DROP",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "ctstate INVALID"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "REJECT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "reject-with icmp-host-prohibited"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
### ls
|
### ls
|
||||||
```
|
```
|
||||||
$ ls -l /bin | jc --ls -p
|
$ ls -l /bin | jc --ls -p
|
||||||
@ -188,6 +583,98 @@ $ ls -l /bin | jc --ls -p
|
|||||||
...
|
...
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
### lsblk
|
||||||
|
```
|
||||||
|
$ lsblk | jc --lsblk -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"NAME": "loop0",
|
||||||
|
"MAJ:MIN": "7:0",
|
||||||
|
"RM": "0",
|
||||||
|
"SIZE": "54.5M",
|
||||||
|
"RO": "1",
|
||||||
|
"TYPE": "loop",
|
||||||
|
"MOUNTPOINT": "/snap/core18/1223"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"NAME": "sda",
|
||||||
|
"MAJ:MIN": "8:0",
|
||||||
|
"RM": "0",
|
||||||
|
"SIZE": "20G",
|
||||||
|
"RO": "0",
|
||||||
|
"TYPE": "disk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"NAME": "sda1",
|
||||||
|
"MAJ:MIN": "8:1",
|
||||||
|
"RM": "0",
|
||||||
|
"SIZE": "1M",
|
||||||
|
"RO": "0",
|
||||||
|
"TYPE": "part"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"NAME": "sda2",
|
||||||
|
"MAJ:MIN": "8:2",
|
||||||
|
"RM": "0",
|
||||||
|
"SIZE": "20G",
|
||||||
|
"RO": "0",
|
||||||
|
"TYPE": "part",
|
||||||
|
"MOUNTPOINT": "/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"NAME": "sr0",
|
||||||
|
"MAJ:MIN": "11:0",
|
||||||
|
"RM": "1",
|
||||||
|
"SIZE": "64.8M",
|
||||||
|
"RO": "0",
|
||||||
|
"TYPE": "rom"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
### mount
|
||||||
|
```
|
||||||
|
$ mount | jc --mount -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"filesystem": "sysfs",
|
||||||
|
"mount_point": "/sys",
|
||||||
|
"type": "sysfs",
|
||||||
|
"access": [
|
||||||
|
"rw",
|
||||||
|
"nosuid",
|
||||||
|
"nodev",
|
||||||
|
"noexec",
|
||||||
|
"relatime"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filesystem": "proc",
|
||||||
|
"mount_point": "/proc",
|
||||||
|
"type": "proc",
|
||||||
|
"access": [
|
||||||
|
"rw",
|
||||||
|
"nosuid",
|
||||||
|
"nodev",
|
||||||
|
"noexec",
|
||||||
|
"relatime"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filesystem": "udev",
|
||||||
|
"mount_point": "/dev",
|
||||||
|
"type": "devtmpfs",
|
||||||
|
"access": [
|
||||||
|
"rw",
|
||||||
|
"nosuid",
|
||||||
|
"relatime",
|
||||||
|
"size=977500k",
|
||||||
|
"nr_inodes=244375",
|
||||||
|
"mode=755"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
### netstat
|
### netstat
|
||||||
```
|
```
|
||||||
$ netstat -p | jc --netstat -p
|
$ netstat -p | jc --netstat -p
|
||||||
@ -394,6 +881,20 @@ $ route -n | jc --route -p
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
### uname -a
|
||||||
|
```
|
||||||
|
$ uname -a | jc --uname -p
|
||||||
|
{
|
||||||
|
"kernel_name": "Linux",
|
||||||
|
"node_name": "user-ubuntu",
|
||||||
|
"kernel_release": "4.15.0-65-generic",
|
||||||
|
"operating_system": "GNU/Linux",
|
||||||
|
"hardware_platform": "x86_64",
|
||||||
|
"processor": "x86_64",
|
||||||
|
"machine": "x86_64",
|
||||||
|
"kernel_version": "#74-Ubuntu SMP Tue Sep 17 17:06:04 UTC 2019"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
Feel free to add/improve code or parsers!
|
Feel free to add/improve code or parsers!
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
jc changelog
|
jc changelog
|
||||||
|
|
||||||
|
20191022 v0.8.1
|
||||||
|
- Add env parser
|
||||||
|
- Add df parser
|
||||||
|
- Add free parser
|
||||||
|
- Add lsblk parser
|
||||||
|
- Add mount parser
|
||||||
|
- Add uname parser
|
||||||
|
- Add iptables parser
|
||||||
|
|
||||||
20191021 v0.6.4
|
20191021 v0.6.4
|
||||||
- Flatten netstat parser output
|
- Flatten netstat parser output
|
||||||
- Clean up argument parsing
|
- Clean up argument parsing
|
||||||
|
41
jc/jc.py
41
jc/jc.py
@ -6,11 +6,18 @@ Main input module
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
import jc.parsers.df
|
||||||
|
import jc.parsers.env
|
||||||
|
import jc.parsers.free
|
||||||
import jc.parsers.ifconfig
|
import jc.parsers.ifconfig
|
||||||
|
import jc.parsers.iptables
|
||||||
import jc.parsers.ls
|
import jc.parsers.ls
|
||||||
|
import jc.parsers.lsblk
|
||||||
|
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.uname
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@ -20,12 +27,30 @@ def main():
|
|||||||
if '-p' in sys.argv:
|
if '-p' in sys.argv:
|
||||||
pretty = True
|
pretty = True
|
||||||
|
|
||||||
if '--ifconfig' in sys.argv:
|
if '--df' in sys.argv:
|
||||||
|
result = jc.parsers.df.parse(data)
|
||||||
|
|
||||||
|
elif '--env' in sys.argv:
|
||||||
|
result = jc.parsers.env.parse(data)
|
||||||
|
|
||||||
|
elif '--free' in sys.argv:
|
||||||
|
result = jc.parsers.free.parse(data)
|
||||||
|
|
||||||
|
elif '--ifconfig' in sys.argv:
|
||||||
result = jc.parsers.ifconfig.parse(data)
|
result = jc.parsers.ifconfig.parse(data)
|
||||||
|
|
||||||
|
elif '--iptables' in sys.argv:
|
||||||
|
result = jc.parsers.iptables.parse(data)
|
||||||
|
|
||||||
elif '--ls' in sys.argv:
|
elif '--ls' in sys.argv:
|
||||||
result = jc.parsers.ls.parse(data)
|
result = jc.parsers.ls.parse(data)
|
||||||
|
|
||||||
|
elif '--lsblk' in sys.argv:
|
||||||
|
result = jc.parsers.lsblk.parse(data)
|
||||||
|
|
||||||
|
elif '--mount' in sys.argv:
|
||||||
|
result = jc.parsers.mount.parse(data)
|
||||||
|
|
||||||
elif '--netstat' in sys.argv:
|
elif '--netstat' in sys.argv:
|
||||||
result = jc.parsers.netstat.parse(data)
|
result = jc.parsers.netstat.parse(data)
|
||||||
|
|
||||||
@ -35,15 +60,25 @@ def main():
|
|||||||
elif '--route' in sys.argv:
|
elif '--route' in sys.argv:
|
||||||
result = jc.parsers.route.parse(data)
|
result = jc.parsers.route.parse(data)
|
||||||
|
|
||||||
|
elif '--uname' in sys.argv:
|
||||||
|
result = jc.parsers.uname.parse(data)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print('jc: missing arguments', file=sys.stderr)
|
print('jc: missing arguments\n', file=sys.stderr)
|
||||||
print('Usage: jc [parser] [options]\n', file=sys.stderr)
|
print('Usage: jc [parser] [options]\n', file=sys.stderr)
|
||||||
print('Parsers:', 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(' --ifconfig iconfig parser', file=sys.stderr)
|
||||||
|
print(' --iptables iptables parser', file=sys.stderr)
|
||||||
print(' --ls ls 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(' --netstat netstat parser', file=sys.stderr)
|
||||||
print(' --ps ps parser', file=sys.stderr)
|
print(' --ps ps parser', file=sys.stderr)
|
||||||
print(' --route route parser\n', file=sys.stderr)
|
print(' --route route parser', file=sys.stderr)
|
||||||
|
print(' --uname uname parser\n', file=sys.stderr)
|
||||||
print('Options:', file=sys.stderr)
|
print('Options:', file=sys.stderr)
|
||||||
print(' -p pretty print output\n', file=sys.stderr)
|
print(' -p pretty print output\n', file=sys.stderr)
|
||||||
print('Example:', file=sys.stderr)
|
print('Example:', file=sys.stderr)
|
||||||
|
55
jc/parsers/df.py
Normal file
55
jc/parsers/df.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
"""jc - JSON CLI output utility df Parser
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
specify --df as the first argument if the piped input is coming from df
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
$ df | jc --df -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"Filesystem": "udev",
|
||||||
|
"1K-blocks": "977500",
|
||||||
|
"Used": "0",
|
||||||
|
"Available": "977500",
|
||||||
|
"Use%": "0%",
|
||||||
|
"Mounted": "/dev"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Filesystem": "tmpfs",
|
||||||
|
"1K-blocks": "201732",
|
||||||
|
"Used": "1180",
|
||||||
|
"Available": "200552",
|
||||||
|
"Use%": "1%",
|
||||||
|
"Mounted": "/run"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Filesystem": "/dev/sda2",
|
||||||
|
"1K-blocks": "20508240",
|
||||||
|
"Used": "5747284",
|
||||||
|
"Available": "13696152",
|
||||||
|
"Use%": "30%",
|
||||||
|
"Mounted": "/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Filesystem": "tmpfs",
|
||||||
|
"1K-blocks": "1008648",
|
||||||
|
"Used": "0",
|
||||||
|
"Available": "1008648",
|
||||||
|
"Use%": "0%",
|
||||||
|
"Mounted": "/dev/shm"
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
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:])
|
||||||
|
return [dict(zip(headers, r)) for r in raw_data]
|
53
jc/parsers/env.py
Normal file
53
jc/parsers/env.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
"""jc - JSON CLI output utility env Parser
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
specify --env as the first argument if the piped input is coming from env
|
||||||
|
|
||||||
|
Example:
|
||||||
|
$ env | jc --env -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"TERM": "xterm-256color"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SHELL": "/bin/bash"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"USER": "root"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PATH": "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"PWD": "/bin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"LANG": "en_US.UTF-8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"HOME": "/root"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_": "/usr/bin/env"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def parse(data):
|
||||||
|
output = []
|
||||||
|
|
||||||
|
linedata = data.splitlines()
|
||||||
|
|
||||||
|
# Clear any blank lines
|
||||||
|
cleandata = list(filter(None, linedata))
|
||||||
|
|
||||||
|
if cleandata:
|
||||||
|
|
||||||
|
for entry in cleandata:
|
||||||
|
output_line = {}
|
||||||
|
parsed_line = entry.split('=', maxsplit=1)
|
||||||
|
output_line[parsed_line[0]] = parsed_line[1]
|
||||||
|
output.append(output_line)
|
||||||
|
|
||||||
|
return output
|
45
jc/parsers/free.py
Normal file
45
jc/parsers/free.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
"""jc - JSON CLI output utility free Parser
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
specify --free as the first argument if the piped input is coming from free
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
$ free | jc --free -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"type": "Mem",
|
||||||
|
"total": "2017300",
|
||||||
|
"used": "213104",
|
||||||
|
"free": "1148452",
|
||||||
|
"shared": "1176",
|
||||||
|
"buff/cache": "655744",
|
||||||
|
"available": "1622204"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Swap",
|
||||||
|
"total": "2097148",
|
||||||
|
"used": "0",
|
||||||
|
"free": "2097148"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
headers.insert(0, "type")
|
||||||
|
|
||||||
|
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['type'] = entry['type'].rstrip(':')
|
||||||
|
|
||||||
|
return output
|
366
jc/parsers/iptables.py
Normal file
366
jc/parsers/iptables.py
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
"""jc - JSON CLI output utility ipables Parser
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
Specify --iptables as the first argument if the piped input is coming from iptables
|
||||||
|
|
||||||
|
Supports -vLn for all tables
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
$ sudo iptables -L -t nat | jc --iptables -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"chain": "PREROUTING",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"target": "PREROUTING_direct",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"source": "anywhere",
|
||||||
|
"destination": "anywhere"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "PREROUTING_ZONES_SOURCE",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"source": "anywhere",
|
||||||
|
"destination": "anywhere"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "PREROUTING_ZONES",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"source": "anywhere",
|
||||||
|
"destination": "anywhere"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "DOCKER",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"source": "anywhere",
|
||||||
|
"destination": "anywhere",
|
||||||
|
"options": "ADDRTYPE match dst-type LOCAL"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chain": "INPUT",
|
||||||
|
"rules": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chain": "OUTPUT",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"target": "OUTPUT_direct",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"source": "anywhere",
|
||||||
|
"destination": "anywhere"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "DOCKER",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"source": "anywhere",
|
||||||
|
"destination": "!loopback/8",
|
||||||
|
"options": "ADDRTYPE match dst-type LOCAL"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
$ sudo iptables -vnL -t filter | jc --iptables -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"chain": "INPUT",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"pkts": "1571",
|
||||||
|
"bytes": "3394K",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "ctstate RELATED,ESTABLISHED"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "lo",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "711",
|
||||||
|
"bytes": "60126",
|
||||||
|
"target": "INPUT_direct",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "711",
|
||||||
|
"bytes": "60126",
|
||||||
|
"target": "INPUT_ZONES_SOURCE",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "711",
|
||||||
|
"bytes": "60126",
|
||||||
|
"target": "INPUT_ZONES",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "DROP",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "ctstate INVALID"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "710",
|
||||||
|
"bytes": "60078",
|
||||||
|
"target": "REJECT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "reject-with icmp-host-prohibited"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"chain": "FORWARD",
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "DOCKER-ISOLATION",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "DOCKER",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "docker0",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "docker0",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "ctstate RELATED,ESTABLISHED"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "docker0",
|
||||||
|
"out": "!docker0",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "docker0",
|
||||||
|
"out": "docker0",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "ctstate RELATED,ESTABLISHED"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "ACCEPT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "lo",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "FORWARD_direct",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "FORWARD_IN_ZONES_SOURCE",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "FORWARD_IN_ZONES",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "FORWARD_OUT_ZONES_SOURCE",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "FORWARD_OUT_ZONES",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "DROP",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "ctstate INVALID"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pkts": "0",
|
||||||
|
"bytes": "0",
|
||||||
|
"target": "REJECT",
|
||||||
|
"prot": "all",
|
||||||
|
"opt": "--",
|
||||||
|
"in": "*",
|
||||||
|
"out": "*",
|
||||||
|
"source": "0.0.0.0/0",
|
||||||
|
"destination": "0.0.0.0/0",
|
||||||
|
"options": "reject-with icmp-host-prohibited"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class state():
|
||||||
|
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 = []
|
||||||
|
|
||||||
|
parsed_line = line.split()
|
||||||
|
|
||||||
|
state.chain['chain'] = parsed_line[1]
|
||||||
|
state.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")
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
|
else:
|
||||||
|
rule = line.split(maxsplit=len(state.headers) - 1)
|
||||||
|
temp_rule = dict(zip(state.headers, rule))
|
||||||
|
if temp_rule:
|
||||||
|
state.chain['rules'].append(temp_rule)
|
||||||
|
|
||||||
|
state.output = list(filter(None, state.output))
|
||||||
|
|
||||||
|
return state.output
|
@ -72,7 +72,7 @@ $ ls -al /usr/bin | jc --ls -p
|
|||||||
...
|
...
|
||||||
]
|
]
|
||||||
|
|
||||||
$ $ ls -l /usr/bin | jc --ls | jq .[] | jq 'select(.bytes > 50000000)'
|
$ $ ls -l /usr/bin | jc --ls | jq '.[] | 'select(.bytes > 50000000)'
|
||||||
{
|
{
|
||||||
"filename": "emacs",
|
"filename": "emacs",
|
||||||
"flags": "-r-xr-xr-x",
|
"flags": "-r-xr-xr-x",
|
||||||
|
70
jc/parsers/lsblk.py
Normal file
70
jc/parsers/lsblk.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
"""jc - JSON CLI output utility lsblk Parser
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
specify --lsblk as the first argument if the piped input is coming from lsblk
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
$ lsblk | jc --lsblk -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"NAME": "loop0",
|
||||||
|
"MAJ:MIN": "7:0",
|
||||||
|
"RM": "0",
|
||||||
|
"SIZE": "54.5M",
|
||||||
|
"RO": "1",
|
||||||
|
"TYPE": "loop",
|
||||||
|
"MOUNTPOINT": "/snap/core18/1223"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"NAME": "sda",
|
||||||
|
"MAJ:MIN": "8:0",
|
||||||
|
"RM": "0",
|
||||||
|
"SIZE": "20G",
|
||||||
|
"RO": "0",
|
||||||
|
"TYPE": "disk"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"NAME": "sda1",
|
||||||
|
"MAJ:MIN": "8:1",
|
||||||
|
"RM": "0",
|
||||||
|
"SIZE": "1M",
|
||||||
|
"RO": "0",
|
||||||
|
"TYPE": "part"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"NAME": "sda2",
|
||||||
|
"MAJ:MIN": "8:2",
|
||||||
|
"RM": "0",
|
||||||
|
"SIZE": "20G",
|
||||||
|
"RO": "0",
|
||||||
|
"TYPE": "part",
|
||||||
|
"MOUNTPOINT": "/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"NAME": "sr0",
|
||||||
|
"MAJ:MIN": "11:0",
|
||||||
|
"RM": "1",
|
||||||
|
"SIZE": "64.8M",
|
||||||
|
"RO": "0",
|
||||||
|
"TYPE": "rom"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
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
|
75
jc/parsers/mount.py
Normal file
75
jc/parsers/mount.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
"""jc - JSON CLI output utility mount Parser
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
specify --mount as the first argument if the piped input is coming from mount
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
$ mount | jc --mount -p
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"filesystem": "sysfs",
|
||||||
|
"mount_point": "/sys",
|
||||||
|
"type": "sysfs",
|
||||||
|
"access": [
|
||||||
|
"rw",
|
||||||
|
"nosuid",
|
||||||
|
"nodev",
|
||||||
|
"noexec",
|
||||||
|
"relatime"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filesystem": "proc",
|
||||||
|
"mount_point": "/proc",
|
||||||
|
"type": "proc",
|
||||||
|
"access": [
|
||||||
|
"rw",
|
||||||
|
"nosuid",
|
||||||
|
"nodev",
|
||||||
|
"noexec",
|
||||||
|
"relatime"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filesystem": "udev",
|
||||||
|
"mount_point": "/dev",
|
||||||
|
"type": "devtmpfs",
|
||||||
|
"access": [
|
||||||
|
"rw",
|
||||||
|
"nosuid",
|
||||||
|
"relatime",
|
||||||
|
"size=977500k",
|
||||||
|
"nr_inodes=244375",
|
||||||
|
"mode=755"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def parse(data):
|
||||||
|
output = []
|
||||||
|
|
||||||
|
linedata = data.splitlines()
|
||||||
|
|
||||||
|
# Clear any blank lines
|
||||||
|
cleandata = list(filter(None, linedata))
|
||||||
|
|
||||||
|
if cleandata:
|
||||||
|
for entry in cleandata:
|
||||||
|
output_line = {}
|
||||||
|
parsed_line = entry.split()
|
||||||
|
|
||||||
|
output_line['filesystem'] = parsed_line[0]
|
||||||
|
output_line['mount_point'] = parsed_line[2]
|
||||||
|
output_line['type'] = parsed_line[4]
|
||||||
|
|
||||||
|
access = parsed_line[5].lstrip('(').rstrip(')').split(',')
|
||||||
|
|
||||||
|
output_line['access'] = access
|
||||||
|
|
||||||
|
output.append(output_line)
|
||||||
|
|
||||||
|
return output
|
42
jc/parsers/uname.py
Normal file
42
jc/parsers/uname.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
"""jc - JSON CLI output utility uname Parser
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
specify --uname as the first argument if the piped input is coming from uname
|
||||||
|
|
||||||
|
Limitations:
|
||||||
|
must use 'uname -a'
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
$ uname -a | jc --uname -p
|
||||||
|
{
|
||||||
|
"kernel_name": "Linux",
|
||||||
|
"node_name": "user-ubuntu",
|
||||||
|
"kernel_release": "4.15.0-65-generic",
|
||||||
|
"operating_system": "GNU/Linux",
|
||||||
|
"hardware_platform": "x86_64",
|
||||||
|
"processor": "x86_64",
|
||||||
|
"machine": "x86_64",
|
||||||
|
"kernel_version": "#74-Ubuntu SMP Tue Sep 17 17:06:04 UTC 2019"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def parse(data):
|
||||||
|
output = {}
|
||||||
|
parsed_line = data.split(maxsplit=3)
|
||||||
|
|
||||||
|
output['kernel_name'] = parsed_line.pop(0)
|
||||||
|
output['node_name'] = parsed_line.pop(0)
|
||||||
|
output['kernel_release'] = parsed_line.pop(0)
|
||||||
|
|
||||||
|
parsed_line = parsed_line[-1].rsplit(maxsplit=4)
|
||||||
|
|
||||||
|
output['operating_system'] = parsed_line.pop(-1)
|
||||||
|
output['hardware_platform'] = parsed_line.pop(-1)
|
||||||
|
output['processor'] = parsed_line.pop(-1)
|
||||||
|
output['machine'] = parsed_line.pop(-1)
|
||||||
|
|
||||||
|
output['kernel_version'] = parsed_line.pop(0)
|
||||||
|
|
||||||
|
return output
|
2
setup.py
2
setup.py
@ -5,7 +5,7 @@ with open('README.md', 'r') as f:
|
|||||||
|
|
||||||
setuptools.setup(
|
setuptools.setup(
|
||||||
name='jc',
|
name='jc',
|
||||||
version='0.6.4',
|
version='0.8.1',
|
||||||
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.',
|
||||||
|
Reference in New Issue
Block a user