mirror of
https://github.com/kellyjonbrazil/jc.git
synced 2025-06-19 00:17:51 +02:00
@ -1,5 +1,14 @@
|
||||
jc changelog
|
||||
|
||||
20210418 v1.15.2
|
||||
- Add systeminfo parser tested on Windows
|
||||
- Update dig parser to fix an issue with IPv6 addresses in the server field
|
||||
- Update dig parser to fix an issue when axfr entries contain a semicolon
|
||||
- Update dig parser to add support for Additional Section and Opt Pseudosection
|
||||
- Update dig parser to add query_size field
|
||||
- Use dig parser as the main example in readme, documentation, and man page
|
||||
- Standardize int, float, and boolean conversion rules with functions in jc.utils
|
||||
|
||||
20210413 v1.15.1
|
||||
- New feature to show parser documentation interactively with -h --parser_name
|
||||
for example: $ jc -h --arp
|
||||
|
123
EXAMPLES.md
123
EXAMPLES.md
@ -548,7 +548,7 @@ dig cnn.com www.cnn.com @205.251.194.64 | jc --dig -p # or: jc -p dig
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 52172,
|
||||
"id": 10267,
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
@ -560,6 +560,13 @@ dig cnn.com www.cnn.com @205.251.194.64 | jc --dig -p # or: jc -p dig
|
||||
"answer_num": 4,
|
||||
"authority_num": 0,
|
||||
"additional_num": 1,
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": 0,
|
||||
"flags": [],
|
||||
"udp": 4096
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
@ -570,40 +577,40 @@ dig cnn.com www.cnn.com @205.251.194.64 | jc --dig -p # or: jc -p dig
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"ttl": 17,
|
||||
"data": "151.101.65.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"ttl": 17,
|
||||
"data": "151.101.129.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"ttl": 17,
|
||||
"data": "151.101.1.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"ttl": 17,
|
||||
"data": "151.101.193.67"
|
||||
}
|
||||
],
|
||||
"query_time": 38,
|
||||
"server": "2600",
|
||||
"when": "Tue Mar 30 20:07:59 PDT 2021",
|
||||
"query_time": 51,
|
||||
"server": "2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)",
|
||||
"when": "Fri Apr 16 16:24:32 PDT 2021",
|
||||
"rcvd": 100,
|
||||
"when_epoch": 1617160079,
|
||||
"when_epoch": 1618615472,
|
||||
"when_epoch_utc": null
|
||||
},
|
||||
{
|
||||
"id": 36292,
|
||||
"id": 56207,
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
@ -615,6 +622,13 @@ dig cnn.com www.cnn.com @205.251.194.64 | jc --dig -p # or: jc -p dig
|
||||
"answer_num": 1,
|
||||
"authority_num": 4,
|
||||
"additional_num": 1,
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": 0,
|
||||
"flags": [],
|
||||
"udp": 4096
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "www.cnn.com.",
|
||||
"class": "IN",
|
||||
@ -659,11 +673,11 @@ dig cnn.com www.cnn.com @205.251.194.64 | jc --dig -p # or: jc -p dig
|
||||
"data": "ns-576.awsdns-08.net."
|
||||
}
|
||||
],
|
||||
"query_time": 27,
|
||||
"query_time": 22,
|
||||
"server": "205.251.194.64#53(205.251.194.64)",
|
||||
"when": "Tue Mar 30 20:07:59 PDT 2021",
|
||||
"when": "Fri Apr 16 16:24:32 PDT 2021",
|
||||
"rcvd": 212,
|
||||
"when_epoch": 1617160079,
|
||||
"when_epoch": 1618615472,
|
||||
"when_epoch_utc": null
|
||||
}
|
||||
]
|
||||
@ -674,7 +688,7 @@ dig -x 1.1.1.1 | jc --dig -p # or: jc -p dig -x 1.1.1.1
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 22191,
|
||||
"id": 20785,
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
@ -686,6 +700,13 @@ dig -x 1.1.1.1 | jc --dig -p # or: jc -p dig -x 1.1.1.1
|
||||
"answer_num": 1,
|
||||
"authority_num": 0,
|
||||
"additional_num": 1,
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": 0,
|
||||
"flags": [],
|
||||
"udp": 4096
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "1.1.1.1.in-addr.arpa.",
|
||||
"class": "IN",
|
||||
@ -700,11 +721,11 @@ dig -x 1.1.1.1 | jc --dig -p # or: jc -p dig -x 1.1.1.1
|
||||
"data": "one.one.one.one."
|
||||
}
|
||||
],
|
||||
"query_time": 44,
|
||||
"server": "2600",
|
||||
"when": "Tue Mar 30 20:10:34 PDT 2021",
|
||||
"query_time": 40,
|
||||
"server": "2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)",
|
||||
"when": "Sat Apr 17 14:50:50 PDT 2021",
|
||||
"rcvd": 78,
|
||||
"when_epoch": 1617160234,
|
||||
"when_epoch": 1618696250,
|
||||
"when_epoch_utc": null
|
||||
}
|
||||
]
|
||||
@ -2869,6 +2890,72 @@ systemctl list-unit-files | jc --systemctl-luf -p # or: jc -p systemct
|
||||
}
|
||||
]
|
||||
```
|
||||
### systeminfo
|
||||
```bash
|
||||
systeminfo | jc --systeminfo -p # or: jc -p systeminfo
|
||||
```
|
||||
```json
|
||||
{
|
||||
"host_name": "TESTLAPTOP",
|
||||
"os_name": "Microsoft Windows 10 Enterprise",
|
||||
"os_version": "10.0.17134 N/A Build 17134",
|
||||
"os_manufacturer": "Microsoft Corporation",
|
||||
"os_configuration": "Member Workstation",
|
||||
"os_build_type": "Multiprocessor Free",
|
||||
"registered_owner": "Test, Inc.",
|
||||
"registered_organization": "Test, Inc.",
|
||||
"product_id": "11111-11111-11111-AA111",
|
||||
"original_install_date": "3/26/2019, 3:51:30 PM",
|
||||
"system_boot_time": "3/30/2021, 6:13:59 AM",
|
||||
"system_manufacturer": "Dell Inc.",
|
||||
"system_model": "Precision 5530",
|
||||
"system_type": "x64-based PC",
|
||||
"processors": [
|
||||
"Intel64 Family 6 Model 158 Stepping 10 GenuineIntel ~2592 Mhz"
|
||||
],
|
||||
"bios_version": "Dell Inc. 1.16.2, 4/21/2020",
|
||||
"windows_directory": "C:\\WINDOWS",
|
||||
"system_directory": "C:\\WINDOWS\\system32",
|
||||
"boot_device": "\\Device\\HarddiskVolume2",
|
||||
"system_locale": "en-us;English (United States)",
|
||||
"input_locale": "en-us;English (United States)",
|
||||
"time_zone": "(UTC+00:00) UTC",
|
||||
"total_physical_memory_mb": 32503,
|
||||
"available_physical_memory_mb": 19743,
|
||||
"virtual_memory_max_size_mb": 37367,
|
||||
"virtual_memory_available_mb": 22266,
|
||||
"virtual_memory_in_use_mb": 15101,
|
||||
"page_file_locations": "C:\\pagefile.sys",
|
||||
"domain": "test.com",
|
||||
"logon_server": "\\\\TESTDC01",
|
||||
"hotfixs": [
|
||||
"KB2693643",
|
||||
"KB4601054"
|
||||
],
|
||||
"network_cards": [
|
||||
{
|
||||
"name": "Intel(R) Wireless-AC 9260 160MHz",
|
||||
"connection_name": "Wi-Fi",
|
||||
"status": null,
|
||||
"dhcp_enabled": true,
|
||||
"dhcp_server": "192.168.2.1",
|
||||
"ip_addresses": [
|
||||
"192.168.2.219"
|
||||
]
|
||||
}
|
||||
],
|
||||
"hyperv_requirements": {
|
||||
"vm_monitor_mode_extensions": true,
|
||||
"virtualization_enabled_in_firmware": true,
|
||||
"second_level_address_translation": false,
|
||||
"data_execution_prevention_available": true
|
||||
},
|
||||
"original_install_date_epoch": 1553640690,
|
||||
"original_install_date_epoch_utc": 1553615490,
|
||||
"system_boot_time_epoch": 1617110039,
|
||||
"system_boot_time_epoch_utc": 1617084839
|
||||
}
|
||||
```
|
||||
### /usr/bin/time
|
||||
```bash
|
||||
/usr/bin/time --verbose -o timefile.out sleep 2.5; cat timefile.out | jc --time -p
|
||||
|
127
README.md
127
README.md
@ -9,62 +9,56 @@
|
||||
JSON CLI output utility
|
||||
|
||||
`jc` JSONifies the output of many CLI tools and file-types for easier parsing in scripts. See the [**Parsers**](#parsers) section for supported commands and file-types.
|
||||
|
||||
This allows further command-line processing of output with tools like `jq` by piping commands:
|
||||
```bash
|
||||
ls -l /usr/bin | jc --ls | jq '.[] | select(.size > 50000000)'
|
||||
dig example.com | jc --dig
|
||||
```
|
||||
```json
|
||||
{
|
||||
"filename": "docker",
|
||||
"flags": "-rwxr-xr-x",
|
||||
"links": 1,
|
||||
"owner": "root",
|
||||
"group": "root",
|
||||
"size": 68677120,
|
||||
"date": "Aug 14 19:41"
|
||||
}
|
||||
[{"id":38052,"opcode":"QUERY","status":"NOERROR","flags":["qr","rd","ra"],"query_num":1,"answer_num":1,
|
||||
"authority_num":0,"additional_num":1,"opt_pseudosection":{"edns":{"version":0,"flags":[],"udp":4096}},"question":
|
||||
{"name":"example.com.","class":"IN","type":"A"},"answer":[{"name":"example.com.","class":"IN","type":"A","ttl":
|
||||
39049,"data":"93.184.216.34"}],"query_time":49,"server":"2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)","when":
|
||||
"Fri Apr 16 16:09:00 PDT 2021","rcvd":56,"when_epoch":1618614540,"when_epoch_utc":null}]
|
||||
```
|
||||
This allows further command-line processing of output with tools like `jq` by piping commands:
|
||||
```bash
|
||||
$ dig example.com | jc --dig | jq -r '.[].answer[].data'
|
||||
93.184.216.34
|
||||
```
|
||||
or using the alternative "magic" syntax:
|
||||
```bash
|
||||
jc ls -l /usr/bin | jq '.[] | select(.size > 50000000)'
|
||||
```
|
||||
```json
|
||||
{
|
||||
"filename": "docker",
|
||||
"flags": "-rwxr-xr-x",
|
||||
"links": 1,
|
||||
"owner": "root",
|
||||
"group": "root",
|
||||
"size": 68677120,
|
||||
"date": "Aug 14 19:41"
|
||||
}
|
||||
$ jc dig example.com | jq -r '.[].answer[].data'
|
||||
93.184.216.34
|
||||
```
|
||||
The `jc` parsers can also be used as python modules. In this case the output will be a python dictionary, or list of dictionaries, instead of JSON:
|
||||
```python
|
||||
>>> import jc.parsers.ls
|
||||
>>> import jc.parsers.dig
|
||||
>>>
|
||||
>>> data='''-rwxr-xr-x 1 root wheel 23648 May 3 22:26 cat
|
||||
... -rwxr-xr-x 1 root wheel 30016 May 3 22:26 chmod
|
||||
... -rwxr-xr-x 1 root wheel 29024 May 3 22:26 cp
|
||||
... -rwxr-xr-x 1 root wheel 375824 May 3 22:26 csh
|
||||
... -rwxr-xr-x 1 root wheel 28608 May 3 22:26 date
|
||||
... -rwxr-xr-x 1 root wheel 32000 May 3 22:26 dd
|
||||
... -rwxr-xr-x 1 root wheel 23392 May 3 22:26 df
|
||||
... -rwxr-xr-x 1 root wheel 18128 May 3 22:26 echo'''
|
||||
>>> data = '''; <<>> DiG 9.10.6 <<>> example.com
|
||||
... ;; global options: +cmd
|
||||
... ;; Got answer:
|
||||
... ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64612
|
||||
... ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
|
||||
...
|
||||
... ;; OPT PSEUDOSECTION:
|
||||
... ; EDNS: version: 0, flags:; udp: 4096
|
||||
... ;; QUESTION SECTION:
|
||||
... ;example.com. IN A
|
||||
...
|
||||
... ;; ANSWER SECTION:
|
||||
... example.com. 29658 IN A 93.184.216.34
|
||||
...
|
||||
... ;; Query time: 52 msec
|
||||
... ;; SERVER: 2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)
|
||||
... ;; WHEN: Fri Apr 16 16:13:00 PDT 2021
|
||||
... ;; MSG SIZE rcvd: 56'''
|
||||
>>>
|
||||
>>> jc.parsers.ls.parse(data)
|
||||
[{'filename': 'cat', 'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 23648,
|
||||
'date': 'May 3 22:26'}, {'filename': 'chmod', 'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root',
|
||||
'group': 'wheel', 'size': 30016, 'date': 'May 3 22:26'}, {'filename': 'cp', 'flags': '-rwxr-xr-x',
|
||||
'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 29024, 'date': 'May 3 22:26'}, {'filename': 'csh',
|
||||
'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 375824, 'date': 'May 3
|
||||
22:26'}, {'filename': 'date', 'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel',
|
||||
'size': 28608, 'date': 'May 3 22:26'}, {'filename': 'dd', 'flags': '-rwxr-xr-x', 'links': 1, 'owner':
|
||||
'root', 'group': 'wheel', 'size': 32000, 'date': 'May 3 22:26'}, {'filename': 'df', 'flags':
|
||||
'-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 23392, 'date': 'May 3 22:26'},
|
||||
{'filename': 'echo', 'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 18128,
|
||||
'date': 'May 3 22:26'}]
|
||||
>>> jc.parsers.dig.parse(data)
|
||||
[{'id': 64612, 'opcode': 'QUERY', 'status': 'NOERROR', 'flags': ['qr', 'rd', 'ra'], 'query_num': 1, 'answer_num':
|
||||
1, 'authority_num': 0, 'additional_num': 1, 'opt_pseudosection': {'edns': {'version': 0, 'flags': [], 'udp':
|
||||
4096}}, 'question': {'name': 'example.com.', 'class': 'IN', 'type': 'A'}, 'answer': [{'name': 'example.com.',
|
||||
'class': 'IN', 'type': 'A', 'ttl': 29658, 'data': '93.184.216.34'}], 'query_time': 52, 'server':
|
||||
'2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)', 'when': 'Fri Apr 16 16:13:00 PDT 2021', 'rcvd': 56,
|
||||
'when_epoch': 1618614780, 'when_epoch_utc': None}]
|
||||
```
|
||||
Two representations of the data are possible. The default representation uses a strict schema per parser and converts known numbers to int/float JSON values. Certain known values of `None` are converted to JSON `null`, known boolean values are converted, and, in some cases, additional semantic context fields are added.
|
||||
|
||||
@ -183,6 +177,7 @@ The JSON output can be compact (default) or pretty formatted with the `-p` optio
|
||||
- `--systemctl-lj` enables the `systemctl list-jobs` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_lj))
|
||||
- `--systemctl-ls` enables the `systemctl list-sockets` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_ls))
|
||||
- `--systemctl-luf` enables the `systemctl list-unit-files` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_luf))
|
||||
- `--systeminfo` enables the `systeminfo` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systeminfo))
|
||||
- `--time` enables the `/usr/bin/time` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/time))
|
||||
- `--timedatectl` enables the `timedatectl status` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/timedatectl))
|
||||
- `--tracepath` enables the `tracepath` and `tracepath6` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/tracepath))
|
||||
@ -352,48 +347,6 @@ cat homes.csv | jc --csv -p
|
||||
}
|
||||
]
|
||||
```
|
||||
### dig
|
||||
```bash
|
||||
dig cnn.com @205.251.194.64 | jc --dig -p # or: jc -p dig cnn.com @205.251.194.64
|
||||
```
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 52172,
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
"qr",
|
||||
"rd",
|
||||
"ra"
|
||||
],
|
||||
"query_num": 1,
|
||||
"answer_num": 1,
|
||||
"authority_num": 0,
|
||||
"additional_num": 1,
|
||||
"question": {
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A"
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"data": "151.101.65.67"
|
||||
}
|
||||
],
|
||||
"query_time": 38,
|
||||
"server": "2600",
|
||||
"when": "Tue Mar 30 20:07:59 PDT 2021",
|
||||
"rcvd": 100,
|
||||
"when_epoch": 1617160079,
|
||||
"when_epoch_utc": null
|
||||
}
|
||||
]
|
||||
```
|
||||
### /etc/hosts file
|
||||
```bash
|
||||
cat /etc/hosts | jc --hosts -p
|
||||
|
@ -252,4 +252,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -105,4 +105,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: darwin
|
||||
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -133,4 +133,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: darwin
|
||||
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -145,4 +145,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -79,4 +79,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -122,4 +122,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -24,64 +24,84 @@ Schema:
|
||||
|
||||
[
|
||||
{
|
||||
"id": integer,
|
||||
"opcode": string,
|
||||
"status": string,
|
||||
"id": integer,
|
||||
"opcode": string,
|
||||
"status": string,
|
||||
"flags": [
|
||||
string
|
||||
string
|
||||
],
|
||||
"query_num": integer,
|
||||
"answer_num": integer,
|
||||
"authority_num": integer,
|
||||
"additional_num": integer,
|
||||
"query_num": integer,
|
||||
"answer_num": integer,
|
||||
"authority_num": integer,
|
||||
"additional_num": integer,
|
||||
"axfr": [
|
||||
{
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
}
|
||||
],
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": integer,
|
||||
"flags": [
|
||||
string
|
||||
],
|
||||
"udp": integer
|
||||
},
|
||||
"cookie": string
|
||||
},
|
||||
"question": {
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
}
|
||||
],
|
||||
"additional": [
|
||||
{
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
}
|
||||
],
|
||||
"authority": [
|
||||
{
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
}
|
||||
],
|
||||
"query_time": integer, # in msec
|
||||
"server": string,
|
||||
"when": string,
|
||||
"when_epoch": integer, # naive timestamp if when field is parsable, else null
|
||||
"when_epoch_utc": integer, # timezone aware timestamp availabe for UTC, else null
|
||||
"rcvd": integer
|
||||
"size": string
|
||||
"query_size": integer,
|
||||
"query_time": integer, # in msec
|
||||
"server": string,
|
||||
"when": string,
|
||||
"when_epoch": integer, # naive timestamp if when field is parsable, else null
|
||||
"when_epoch_utc": integer, # timezone aware timestamp availabe for UTC, else null
|
||||
"rcvd": integer
|
||||
"size": string
|
||||
}
|
||||
]
|
||||
|
||||
Examples:
|
||||
|
||||
$ dig cnn.com www.cnn.com @205.251.194.64 | jc --dig -p
|
||||
$ dig example.com | jc --dig -p
|
||||
[
|
||||
{
|
||||
"id": 52172,
|
||||
"id": 2951,
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
@ -90,113 +110,35 @@ Examples:
|
||||
"ra"
|
||||
],
|
||||
"query_num": 1,
|
||||
"answer_num": 4,
|
||||
"answer_num": 1,
|
||||
"authority_num": 0,
|
||||
"additional_num": 1,
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": 0,
|
||||
"flags": [],
|
||||
"udp": 4096
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "cnn.com.",
|
||||
"name": "example.com.",
|
||||
"class": "IN",
|
||||
"type": "A"
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"name": "example.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"data": "151.101.65.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"data": "151.101.129.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"data": "151.101.1.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"data": "151.101.193.67"
|
||||
"ttl": 39302,
|
||||
"data": "93.184.216.34"
|
||||
}
|
||||
],
|
||||
"query_time": 38,
|
||||
"server": "2600",
|
||||
"when": "Tue Mar 30 20:07:59 PDT 2021",
|
||||
"rcvd": 100,
|
||||
"when_epoch": 1617160079,
|
||||
"when_epoch_utc": null
|
||||
},
|
||||
{
|
||||
"id": 36292,
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
"qr",
|
||||
"aa",
|
||||
"rd"
|
||||
],
|
||||
"query_num": 1,
|
||||
"answer_num": 1,
|
||||
"authority_num": 4,
|
||||
"additional_num": 1,
|
||||
"question": {
|
||||
"name": "www.cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A"
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": "www.cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "CNAME",
|
||||
"ttl": 300,
|
||||
"data": "turner-tls.map.fastly.net."
|
||||
}
|
||||
],
|
||||
"authority": [
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": 3600,
|
||||
"data": "ns-1086.awsdns-07.org."
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": 3600,
|
||||
"data": "ns-1630.awsdns-11.co.uk."
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": 3600,
|
||||
"data": "ns-47.awsdns-05.com."
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": 3600,
|
||||
"data": "ns-576.awsdns-08.net."
|
||||
}
|
||||
],
|
||||
"query_time": 27,
|
||||
"server": "205.251.194.64#53(205.251.194.64)",
|
||||
"when": "Tue Mar 30 20:07:59 PDT 2021",
|
||||
"rcvd": 212,
|
||||
"when_epoch": 1617160079,
|
||||
"query_time": 49,
|
||||
"server": "2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)",
|
||||
"when": "Fri Apr 16 16:05:10 PDT 2021",
|
||||
"rcvd": 56,
|
||||
"when_epoch": 1618614310,
|
||||
"when_epoch_utc": null
|
||||
}
|
||||
]
|
||||
@ -204,7 +146,7 @@ Examples:
|
||||
$ dig cnn.com www.cnn.com @205.251.194.64 | jc --dig -p -r
|
||||
[
|
||||
{
|
||||
"id": "23843",
|
||||
"id": "46052",
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
@ -213,117 +155,41 @@ Examples:
|
||||
"ra"
|
||||
],
|
||||
"query_num": "1",
|
||||
"answer_num": "4",
|
||||
"answer_num": "1",
|
||||
"authority_num": "0",
|
||||
"additional_num": "1",
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": "0",
|
||||
"flags": [],
|
||||
"udp": "4096"
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "cnn.com.",
|
||||
"name": "example.com.",
|
||||
"class": "IN",
|
||||
"type": "A"
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"name": "example.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": "30",
|
||||
"data": "151.101.193.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": "30",
|
||||
"data": "151.101.1.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": "30",
|
||||
"data": "151.101.65.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": "30",
|
||||
"data": "151.101.129.67"
|
||||
"ttl": "40426",
|
||||
"data": "93.184.216.34"
|
||||
}
|
||||
],
|
||||
"query_time": "24 msec",
|
||||
"server": "192.168.1.254#53(192.168.1.254)",
|
||||
"when": "Tue Nov 12 07:16:19 PST 2019",
|
||||
"rcvd": "100"
|
||||
},
|
||||
{
|
||||
"id": "8266",
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
"qr",
|
||||
"aa",
|
||||
"rd"
|
||||
],
|
||||
"query_num": "1",
|
||||
"answer_num": "1",
|
||||
"authority_num": "4",
|
||||
"additional_num": "1",
|
||||
"question": {
|
||||
"name": "www.cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A"
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": "www.cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "CNAME",
|
||||
"ttl": "300",
|
||||
"data": "turner-tls.map.fastly.net."
|
||||
}
|
||||
],
|
||||
"authority": [
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": "3600",
|
||||
"data": "ns-1086.awsdns-07.org."
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": "3600",
|
||||
"data": "ns-1630.awsdns-11.co.uk."
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": "3600",
|
||||
"data": "ns-47.awsdns-05.com."
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": "3600",
|
||||
"data": "ns-576.awsdns-08.net."
|
||||
}
|
||||
],
|
||||
"query_time": "26 msec",
|
||||
"server": "205.251.194.64#53(205.251.194.64)",
|
||||
"when": "Tue Nov 12 07:16:19 PST 2019",
|
||||
"rcvd": "212"
|
||||
"query_time": "48 msec",
|
||||
"server": "2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)",
|
||||
"when": "Fri Apr 16 16:06:12 PDT 2021",
|
||||
"rcvd": "56"
|
||||
}
|
||||
]
|
||||
|
||||
$ dig -x 1.1.1.1 | jc --dig -p
|
||||
[
|
||||
{
|
||||
"id": 22191,
|
||||
"id": 20785,
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
@ -335,6 +201,13 @@ Examples:
|
||||
"answer_num": 1,
|
||||
"authority_num": 0,
|
||||
"additional_num": 1,
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": 0,
|
||||
"flags": [],
|
||||
"udp": 4096
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "1.1.1.1.in-addr.arpa.",
|
||||
"class": "IN",
|
||||
@ -349,11 +222,11 @@ Examples:
|
||||
"data": "one.one.one.one."
|
||||
}
|
||||
],
|
||||
"query_time": 44,
|
||||
"server": "2600",
|
||||
"when": "Tue Mar 30 20:10:34 PDT 2021",
|
||||
"query_time": 40,
|
||||
"server": "2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)",
|
||||
"when": "Sat Apr 17 14:50:50 PDT 2021",
|
||||
"rcvd": 78,
|
||||
"when_epoch": 1617160234,
|
||||
"when_epoch": 1618696250,
|
||||
"when_epoch_utc": null
|
||||
}
|
||||
]
|
||||
@ -361,7 +234,7 @@ Examples:
|
||||
$ dig -x 1.1.1.1 | jc --dig -p -r
|
||||
[
|
||||
{
|
||||
"id": "50986",
|
||||
"id": "32644",
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
@ -373,6 +246,13 @@ Examples:
|
||||
"answer_num": "1",
|
||||
"authority_num": "0",
|
||||
"additional_num": "1",
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": "0",
|
||||
"flags": [],
|
||||
"udp": "4096"
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "1.1.1.1.in-addr.arpa.",
|
||||
"class": "IN",
|
||||
@ -387,9 +267,9 @@ Examples:
|
||||
"data": "one.one.one.one."
|
||||
}
|
||||
],
|
||||
"query_time": "38 msec",
|
||||
"server": "2600",
|
||||
"when": "Tue Nov 12 07:17:19 PST 2019",
|
||||
"query_time": "52 msec",
|
||||
"server": "2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)",
|
||||
"when": "Sat Apr 17 14:51:46 PDT 2021",
|
||||
"rcvd": "78"
|
||||
}
|
||||
]
|
||||
@ -421,4 +301,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, aix, freebsd, darwin
|
||||
|
||||
Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 2.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -145,4 +145,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: win32
|
||||
|
||||
Version 1.1 by Rasheed Elsaleh (rasheed@rebelliondefense.com)
|
||||
Version 1.2 by Rasheed Elsaleh (rasheed@rebelliondefense.com)
|
||||
|
@ -150,4 +150,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -112,4 +112,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, aix, freebsd
|
||||
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -97,4 +97,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -110,4 +110,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, freebsd
|
||||
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -134,4 +134,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, aix, freebsd
|
||||
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -62,4 +62,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -342,4 +342,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -83,4 +83,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -130,4 +130,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, aix, freebsd
|
||||
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -211,4 +211,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, aix, freebsd, darwin
|
||||
|
||||
Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.10 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -188,4 +188,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -119,4 +119,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -128,4 +128,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, aix, freebsd
|
||||
|
||||
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -6,7 +6,6 @@ jc - JSON CLI output utility `ls` and `vdir` command output parser
|
||||
Options supported:
|
||||
- `lbaR1`
|
||||
- `--time-style=full-iso`
|
||||
- `-h`: File sizes will be available in text form with `-r` but larger file sizes with human readable suffixes will be converted to `Null` in the default view since the parser attempts to convert this field to an integer.
|
||||
|
||||
Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly parse filenames that include newline characters. Since `ls` does not encode newlines in filenames when outputting to a pipe it will cause `jc` to see multiple files instead of a single file if `-1`, `-l`, or `-b` is not used. Alternatively, `vdir` can be used, which is the same as running `ls -lb`.
|
||||
|
||||
@ -132,4 +131,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -293,4 +293,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -150,4 +150,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -144,4 +144,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -379,4 +379,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.10 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -231,4 +231,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, freebsd
|
||||
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -119,4 +119,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, aix, freebsd
|
||||
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -170,4 +170,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -231,4 +231,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -135,4 +135,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.6 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -181,4 +181,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -126,4 +126,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, aix, freebsd
|
||||
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -303,4 +303,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -193,4 +193,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
Version 1.7 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -100,4 +100,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
232
docs/parsers/systeminfo.md
Normal file
232
docs/parsers/systeminfo.md
Normal file
@ -0,0 +1,232 @@
|
||||
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||
|
||||
# jc.parsers.systeminfo
|
||||
jc - JSON CLI output utility `systeminfo` command output parser
|
||||
|
||||
Blank or missing elements are set to `null`.
|
||||
|
||||
The `original_install_date_epoch` and `system_boot_time_epoch` calculated timestamp fields are naive (i.e. based on the local time of the system the parser is run on)
|
||||
|
||||
The `original_install_date_epoch_utc` and `system_boot_time_epoch_utc` calculated timestamp fields are timezone-aware and are only available if the timezone field is UTC.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ systeminfo | jc --systeminfo
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc.parsers.systeminfo
|
||||
result = jc.parsers.systeminfo.parse(systeminfo_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"host_name": string,
|
||||
"os_name": string,
|
||||
"os_version": string,
|
||||
"os_manufacturer": string,
|
||||
"os_configuration": string,
|
||||
"os_build_type": string,
|
||||
"registered_owner": string,
|
||||
"registered_organization": string,
|
||||
"product_id": string,
|
||||
"original_install_date": string,
|
||||
"original_install_date_epoch": integer, # naive timestamp
|
||||
"original_install_date_epoch_utc": integer, # timezone-aware timestamp
|
||||
"system_boot_time": string,
|
||||
"system_boot_time_epoch": integer, # naive timestamp
|
||||
"system_boot_time_epoch_utc": integer, # timezone-aware timestamp
|
||||
"system_manufacturer": string,
|
||||
"system_model": string,
|
||||
"system_type": string,
|
||||
"processors": [
|
||||
string
|
||||
],
|
||||
"bios_version": string,
|
||||
"windows_directory": string,
|
||||
"system_directory": string,
|
||||
"boot_device": string,
|
||||
"system_locale": string,
|
||||
"input_locale": string,
|
||||
"time_zone": string,
|
||||
"total_physical_memory_mb": string,
|
||||
"available_physical_memory_mb": integer,
|
||||
"virtual_memory_max_size_mb": integer,
|
||||
"virtual_memory_available_mb": integer,
|
||||
"virtual_memory_in_use_mb": integer,
|
||||
"page_file_locations": string,
|
||||
"domain": string,
|
||||
"logon_server": string,
|
||||
"hotfixs": [
|
||||
string
|
||||
],
|
||||
"network_cards": [
|
||||
{
|
||||
"name": string,
|
||||
"connection_name": string,
|
||||
"status": string,
|
||||
"dhcp_enabled": boolean,
|
||||
"dhcp_server": string,
|
||||
"ip_addresses": [
|
||||
string
|
||||
]
|
||||
}
|
||||
],
|
||||
"hyperv_requirements": {
|
||||
"vm_monitor_mode_extensions": boolean,
|
||||
"virtualization_enabled_in_firmware": boolean,
|
||||
"second_level_address_translation": boolean,
|
||||
"data_execution_prevention_available": boolean
|
||||
}
|
||||
}
|
||||
|
||||
Examples:
|
||||
|
||||
$ systeminfo | jc --systeminfo -p
|
||||
{
|
||||
"host_name": "TESTLAPTOP",
|
||||
"os_name": "Microsoft Windows 10 Enterprise",
|
||||
"os_version": "10.0.17134 N/A Build 17134",
|
||||
"os_manufacturer": "Microsoft Corporation",
|
||||
"os_configuration": "Member Workstation",
|
||||
"os_build_type": "Multiprocessor Free",
|
||||
"registered_owner": "Test, Inc.",
|
||||
"registered_organization": "Test, Inc.",
|
||||
"product_id": "11111-11111-11111-AA111",
|
||||
"original_install_date": "3/26/2019, 3:51:30 PM",
|
||||
"system_boot_time": "3/30/2021, 6:13:59 AM",
|
||||
"system_manufacturer": "Dell Inc.",
|
||||
"system_model": "Precision 5530",
|
||||
"system_type": "x64-based PC",
|
||||
"processors": [
|
||||
"Intel64 Family 6 Model 158 Stepping 10 GenuineIntel ~2592 Mhz"
|
||||
],
|
||||
"bios_version": "Dell Inc. 1.16.2, 4/21/2020",
|
||||
"windows_directory": "C:\WINDOWS",
|
||||
"system_directory": "C:\WINDOWS\system32",
|
||||
"boot_device": "\Device\HarddiskVolume2",
|
||||
"system_locale": "en-us;English (United States)",
|
||||
"input_locale": "en-us;English (United States)",
|
||||
"time_zone": "(UTC+00:00) UTC",
|
||||
"total_physical_memory_mb": 32503,
|
||||
"available_physical_memory_mb": 19743,
|
||||
"virtual_memory_max_size_mb": 37367,
|
||||
"virtual_memory_available_mb": 22266,
|
||||
"virtual_memory_in_use_mb": 15101,
|
||||
"page_file_locations": "C:\pagefile.sys",
|
||||
"domain": "test.com",
|
||||
"logon_server": "\\TESTDC01",
|
||||
"hotfixs": [
|
||||
"KB2693643",
|
||||
"KB4601054"
|
||||
],
|
||||
"network_cards": [
|
||||
{
|
||||
"name": "Intel(R) Wireless-AC 9260 160MHz",
|
||||
"connection_name": "Wi-Fi",
|
||||
"status": null,
|
||||
"dhcp_enabled": true,
|
||||
"dhcp_server": "192.168.2.1",
|
||||
"ip_addresses": [
|
||||
"192.168.2.219"
|
||||
]
|
||||
}
|
||||
],
|
||||
"hyperv_requirements": {
|
||||
"vm_monitor_mode_extensions": true,
|
||||
"virtualization_enabled_in_firmware": true,
|
||||
"second_level_address_translation": false,
|
||||
"data_execution_prevention_available": true
|
||||
},
|
||||
"original_install_date_epoch": 1553640690,
|
||||
"original_install_date_epoch_utc": 1553615490,
|
||||
"system_boot_time_epoch": 1617110039,
|
||||
"system_boot_time_epoch_utc": 1617084839
|
||||
}
|
||||
|
||||
$ systeminfo | jc --systeminfo -p -r
|
||||
{
|
||||
"host_name": "TESTLAPTOP",
|
||||
"os_name": "Microsoft Windows 10 Enterprise",
|
||||
"os_version": "10.0.17134 N/A Build 17134",
|
||||
"os_manufacturer": "Microsoft Corporation",
|
||||
"os_configuration": "Member Workstation",
|
||||
"os_build_type": "Multiprocessor Free",
|
||||
"registered_owner": "Test, Inc.",
|
||||
"registered_organization": "Test, Inc.",
|
||||
"product_id": "11111-11111-11111-AA111",
|
||||
"original_install_date": "3/26/2019, 3:51:30 PM",
|
||||
"system_boot_time": "3/30/2021, 6:13:59 AM",
|
||||
"system_manufacturer": "Dell Inc.",
|
||||
"system_model": "Precision 5530",
|
||||
"system_type": "x64-based PC",
|
||||
"processors": [
|
||||
"Intel64 Family 6 Model 158 Stepping 10 GenuineIntel ~2592 Mhz"
|
||||
],
|
||||
"bios_version": "Dell Inc. 1.16.2, 4/21/2020",
|
||||
"windows_directory": "C:\WINDOWS",
|
||||
"system_directory": "C:\WINDOWS\system32",
|
||||
"boot_device": "\Device\HarddiskVolume2",
|
||||
"system_locale": "en-us;English (United States)",
|
||||
"input_locale": "en-us;English (United States)",
|
||||
"time_zone": "(UTC+00:00) UTC",
|
||||
"total_physical_memory_mb": "32,503 MB",
|
||||
"available_physical_memory_mb": "19,743 MB",
|
||||
"virtual_memory_max_size_mb": "37,367 MB",
|
||||
"virtual_memory_available_mb": "22,266 MB",
|
||||
"virtual_memory_in_use_mb": "15,101 MB",
|
||||
"page_file_locations": "C:\pagefile.sys",
|
||||
"domain": "test.com",
|
||||
"logon_server": "\\TESTDC01",
|
||||
"hotfixs": [
|
||||
"KB2693643",
|
||||
"KB4601054"
|
||||
],
|
||||
"network_cards": [
|
||||
{
|
||||
"name": "Intel(R) Wireless-AC 9260 160MHz",
|
||||
"connection_name": "Wi-Fi",
|
||||
"status": "",
|
||||
"dhcp_enabled": "Yes",
|
||||
"dhcp_server": "192.168.2.1",
|
||||
"ip_addresses": [
|
||||
"192.168.2.219"
|
||||
]
|
||||
}
|
||||
],
|
||||
"hyperv_requirements": {
|
||||
"vm_monitor_mode_extensions": "Yes",
|
||||
"virtualization_enabled_in_firmware": "Yes",
|
||||
"second_level_address_translation": "No",
|
||||
"data_execution_prevention_available": "Yes"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
## info
|
||||
```python
|
||||
info()
|
||||
```
|
||||
Provides parser metadata (version, author, etc.)
|
||||
|
||||
## parse
|
||||
```python
|
||||
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:
|
||||
|
||||
List of Dictionaries. Raw or processed structured data.
|
||||
|
||||
## Parser Information
|
||||
Compatibility: win32
|
||||
|
||||
Version 1.0 by Jon Smith (jon@rebelliondefense.com)
|
@ -148,4 +148,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -88,4 +88,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -156,4 +156,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -142,4 +142,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -219,4 +219,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -90,4 +90,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.5 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -79,4 +79,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
@ -157,4 +157,4 @@ Returns:
|
||||
## Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
117
docs/readme.md
117
docs/readme.md
@ -10,62 +10,79 @@ For documentation on each parser, see the [documentation site](https://kellyjonb
|
||||
|
||||
CLI Example:
|
||||
|
||||
$ ls -l /usr/bin | jc --ls -p
|
||||
$ dig example.com | jc --dig -p
|
||||
[
|
||||
{
|
||||
"filename": "apropos",
|
||||
"link_to": "whatis",
|
||||
"flags": "lrwxrwxrwx.",
|
||||
"links": 1,
|
||||
"owner": "root",
|
||||
"group": "root",
|
||||
"size": 6,
|
||||
"date": "Aug 15 10:53"
|
||||
},
|
||||
{
|
||||
"filename": "ar",
|
||||
"flags": "-rwxr-xr-x.",
|
||||
"links": 1,
|
||||
"owner": "root",
|
||||
"group": "root",
|
||||
"size": 62744,
|
||||
"date": "Aug 8 16:14"
|
||||
},
|
||||
{
|
||||
"filename": "arch",
|
||||
"flags": "-rwxr-xr-x.",
|
||||
"links": 1,
|
||||
"owner": "root",
|
||||
"group": "root",
|
||||
"size": 33080,
|
||||
"date": "Aug 19 23:25"
|
||||
},
|
||||
...
|
||||
"id": 2951,
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
"qr",
|
||||
"rd",
|
||||
"ra"
|
||||
],
|
||||
"query_num": 1,
|
||||
"answer_num": 1,
|
||||
"authority_num": 0,
|
||||
"additional_num": 1,
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": 0,
|
||||
"flags": [],
|
||||
"udp": 4096
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "example.com.",
|
||||
"class": "IN",
|
||||
"type": "A"
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": "example.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 39302,
|
||||
"data": "93.184.216.34"
|
||||
}
|
||||
],
|
||||
"query_time": 49,
|
||||
"server": "2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)",
|
||||
"when": "Fri Apr 16 16:05:10 PDT 2021",
|
||||
"rcvd": 56,
|
||||
"when_epoch": 1618614310,
|
||||
"when_epoch_utc": null
|
||||
}
|
||||
]
|
||||
|
||||
Module Example:
|
||||
|
||||
>>> import jc.parsers.ls
|
||||
>>> import jc.parsers.dig
|
||||
>>>
|
||||
>>> data='''-rwxr-xr-x 1 root wheel 23648 May 3 22:26 cat
|
||||
... -rwxr-xr-x 1 root wheel 30016 May 3 22:26 chmod
|
||||
... -rwxr-xr-x 1 root wheel 29024 May 3 22:26 cp
|
||||
... -rwxr-xr-x 1 root wheel 375824 May 3 22:26 csh
|
||||
... -rwxr-xr-x 1 root wheel 28608 May 3 22:26 date
|
||||
... -rwxr-xr-x 1 root wheel 32000 May 3 22:26 dd
|
||||
... -rwxr-xr-x 1 root wheel 23392 May 3 22:26 df
|
||||
... -rwxr-xr-x 1 root wheel 18128 May 3 22:26 echo'''
|
||||
>>> data = '''; <<>> DiG 9.10.6 <<>> example.com
|
||||
... ;; global options: +cmd
|
||||
... ;; Got answer:
|
||||
... ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64612
|
||||
... ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
|
||||
...
|
||||
... ;; OPT PSEUDOSECTION:
|
||||
... ; EDNS: version: 0, flags:; udp: 4096
|
||||
... ;; QUESTION SECTION:
|
||||
... ;example.com. IN A
|
||||
...
|
||||
... ;; ANSWER SECTION:
|
||||
... example.com. 29658 IN A 93.184.216.34
|
||||
...
|
||||
... ;; Query time: 52 msec
|
||||
... ;; SERVER: 2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)
|
||||
... ;; WHEN: Fri Apr 16 16:13:00 PDT 2021
|
||||
... ;; MSG SIZE rcvd: 56'''
|
||||
>>>
|
||||
>>> jc.parsers.ls.parse(data)
|
||||
[{'filename': 'cat', 'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 23648,
|
||||
'date': 'May 3 22:26'}, {'filename': 'chmod', 'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root',
|
||||
'group': 'wheel', 'size': 30016, 'date': 'May 3 22:26'}, {'filename': 'cp', 'flags': '-rwxr-xr-x',
|
||||
'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 29024, 'date': 'May 3 22:26'}, {'filename': 'csh',
|
||||
'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 375824, 'date': 'May 3
|
||||
22:26'}, {'filename': 'date', 'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel',
|
||||
'size': 28608, 'date': 'May 3 22:26'}, {'filename': 'dd', 'flags': '-rwxr-xr-x', 'links': 1, 'owner':
|
||||
'root', 'group': 'wheel', 'size': 32000, 'date': 'May 3 22:26'}, {'filename': 'df', 'flags':
|
||||
'-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 23392, 'date': 'May 3 22:26'},
|
||||
{'filename': 'echo', 'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 18128,
|
||||
'date': 'May 3 22:26'}]
|
||||
>>> jc.parsers.dig.parse(data)
|
||||
[{'id': 64612, 'opcode': 'QUERY', 'status': 'NOERROR', 'flags': ['qr', 'rd', 'ra'], 'query_num': 1, 'answer_num':
|
||||
1, 'authority_num': 0, 'additional_num': 1, 'opt_pseudosection': {'edns': {'version': 0, 'flags': [], 'udp':
|
||||
4096}}, 'question': {'name': 'example.com.', 'class': 'IN', 'type': 'A'}, 'answer': [{'name': 'example.com.',
|
||||
'class': 'IN', 'type': 'A', 'ttl': 29658, 'data': '93.184.216.34'}], 'query_time': 52, 'server':
|
||||
'2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)', 'when': 'Fri Apr 16 16:13:00 PDT 2021', 'rcvd': 56,
|
||||
'when_epoch': 1618614780, 'when_epoch_utc': None}]
|
||||
|
||||
|
@ -69,6 +69,54 @@ Returns:
|
||||
Boolean True if input string (data) contains non-whitespace characters, otherwise False
|
||||
|
||||
|
||||
## convert_to_int
|
||||
```python
|
||||
convert_to_int(value)
|
||||
```
|
||||
|
||||
Converts string input to integer by stripping all non-numeric characters
|
||||
|
||||
Parameters:
|
||||
|
||||
value: (string/integer/float) Input value
|
||||
|
||||
Returns:
|
||||
|
||||
integer/None Integer if successful conversion, otherwise None
|
||||
|
||||
|
||||
## convert_to_float
|
||||
```python
|
||||
convert_to_float(value)
|
||||
```
|
||||
|
||||
Converts string input to float by stripping all non-numeric characters
|
||||
|
||||
Parameters:
|
||||
|
||||
value: (string) Input value
|
||||
|
||||
Returns:
|
||||
|
||||
float/None Float if successful conversion, otherwise None
|
||||
|
||||
|
||||
## convert_to_bool
|
||||
```python
|
||||
convert_to_bool(value)
|
||||
```
|
||||
|
||||
Converts string, integer, or float input to boolean by checking for 'truthy' values
|
||||
|
||||
Parameters:
|
||||
|
||||
value: (string/integer/float) Input value
|
||||
|
||||
Returns:
|
||||
|
||||
True/False False unless a 'truthy' number or string is found ('y', 'yes', 'true', '1', 1, -1, etc.)
|
||||
|
||||
|
||||
## timestamp
|
||||
```python
|
||||
timestamp(datetime_string)
|
||||
|
119
jc/__init__.py
119
jc/__init__.py
@ -8,65 +8,82 @@ For documentation on each parser, see the [documentation site](https://kellyjonb
|
||||
|
||||
CLI Example:
|
||||
|
||||
$ ls -l /usr/bin | jc --ls -p
|
||||
$ dig example.com | jc --dig -p
|
||||
[
|
||||
{
|
||||
"filename": "apropos",
|
||||
"link_to": "whatis",
|
||||
"flags": "lrwxrwxrwx.",
|
||||
"links": 1,
|
||||
"owner": "root",
|
||||
"group": "root",
|
||||
"size": 6,
|
||||
"date": "Aug 15 10:53"
|
||||
},
|
||||
{
|
||||
"filename": "ar",
|
||||
"flags": "-rwxr-xr-x.",
|
||||
"links": 1,
|
||||
"owner": "root",
|
||||
"group": "root",
|
||||
"size": 62744,
|
||||
"date": "Aug 8 16:14"
|
||||
},
|
||||
{
|
||||
"filename": "arch",
|
||||
"flags": "-rwxr-xr-x.",
|
||||
"links": 1,
|
||||
"owner": "root",
|
||||
"group": "root",
|
||||
"size": 33080,
|
||||
"date": "Aug 19 23:25"
|
||||
},
|
||||
...
|
||||
"id": 2951,
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
"qr",
|
||||
"rd",
|
||||
"ra"
|
||||
],
|
||||
"query_num": 1,
|
||||
"answer_num": 1,
|
||||
"authority_num": 0,
|
||||
"additional_num": 1,
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": 0,
|
||||
"flags": [],
|
||||
"udp": 4096
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "example.com.",
|
||||
"class": "IN",
|
||||
"type": "A"
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": "example.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 39302,
|
||||
"data": "93.184.216.34"
|
||||
}
|
||||
],
|
||||
"query_time": 49,
|
||||
"server": "2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)",
|
||||
"when": "Fri Apr 16 16:05:10 PDT 2021",
|
||||
"rcvd": 56,
|
||||
"when_epoch": 1618614310,
|
||||
"when_epoch_utc": null
|
||||
}
|
||||
]
|
||||
|
||||
Module Example:
|
||||
|
||||
>>> import jc.parsers.ls
|
||||
>>> import jc.parsers.dig
|
||||
>>>
|
||||
>>> data='''-rwxr-xr-x 1 root wheel 23648 May 3 22:26 cat
|
||||
... -rwxr-xr-x 1 root wheel 30016 May 3 22:26 chmod
|
||||
... -rwxr-xr-x 1 root wheel 29024 May 3 22:26 cp
|
||||
... -rwxr-xr-x 1 root wheel 375824 May 3 22:26 csh
|
||||
... -rwxr-xr-x 1 root wheel 28608 May 3 22:26 date
|
||||
... -rwxr-xr-x 1 root wheel 32000 May 3 22:26 dd
|
||||
... -rwxr-xr-x 1 root wheel 23392 May 3 22:26 df
|
||||
... -rwxr-xr-x 1 root wheel 18128 May 3 22:26 echo'''
|
||||
>>> data = '''; <<>> DiG 9.10.6 <<>> example.com
|
||||
... ;; global options: +cmd
|
||||
... ;; Got answer:
|
||||
... ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64612
|
||||
... ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
|
||||
...
|
||||
... ;; OPT PSEUDOSECTION:
|
||||
... ; EDNS: version: 0, flags:; udp: 4096
|
||||
... ;; QUESTION SECTION:
|
||||
... ;example.com. IN A
|
||||
...
|
||||
... ;; ANSWER SECTION:
|
||||
... example.com. 29658 IN A 93.184.216.34
|
||||
...
|
||||
... ;; Query time: 52 msec
|
||||
... ;; SERVER: 2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)
|
||||
... ;; WHEN: Fri Apr 16 16:13:00 PDT 2021
|
||||
... ;; MSG SIZE rcvd: 56'''
|
||||
>>>
|
||||
>>> jc.parsers.ls.parse(data)
|
||||
[{'filename': 'cat', 'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 23648,
|
||||
'date': 'May 3 22:26'}, {'filename': 'chmod', 'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root',
|
||||
'group': 'wheel', 'size': 30016, 'date': 'May 3 22:26'}, {'filename': 'cp', 'flags': '-rwxr-xr-x',
|
||||
'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 29024, 'date': 'May 3 22:26'}, {'filename': 'csh',
|
||||
'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 375824, 'date': 'May 3
|
||||
22:26'}, {'filename': 'date', 'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel',
|
||||
'size': 28608, 'date': 'May 3 22:26'}, {'filename': 'dd', 'flags': '-rwxr-xr-x', 'links': 1, 'owner':
|
||||
'root', 'group': 'wheel', 'size': 32000, 'date': 'May 3 22:26'}, {'filename': 'df', 'flags':
|
||||
'-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 23392, 'date': 'May 3 22:26'},
|
||||
{'filename': 'echo', 'flags': '-rwxr-xr-x', 'links': 1, 'owner': 'root', 'group': 'wheel', 'size': 18128,
|
||||
'date': 'May 3 22:26'}]
|
||||
>>> jc.parsers.dig.parse(data)
|
||||
[{'id': 64612, 'opcode': 'QUERY', 'status': 'NOERROR', 'flags': ['qr', 'rd', 'ra'], 'query_num': 1, 'answer_num':
|
||||
1, 'authority_num': 0, 'additional_num': 1, 'opt_pseudosection': {'edns': {'version': 0, 'flags': [], 'udp':
|
||||
4096}}, 'question': {'name': 'example.com.', 'class': 'IN', 'type': 'A'}, 'answer': [{'name': 'example.com.',
|
||||
'class': 'IN', 'type': 'A', 'ttl': 29658, 'data': '93.184.216.34'}], 'query_time': 52, 'server':
|
||||
'2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)', 'when': 'Fri Apr 16 16:13:00 PDT 2021', 'rcvd': 56,
|
||||
'when_epoch': 1618614780, 'when_epoch_utc': None}]
|
||||
"""
|
||||
|
||||
name = 'jc'
|
||||
__version__ = '1.15.1'
|
||||
__version__ = '1.15.2'
|
||||
|
22
jc/cli.py
22
jc/cli.py
@ -97,6 +97,7 @@ parsers = [
|
||||
'systemctl-lj',
|
||||
'systemctl-ls',
|
||||
'systemctl-luf',
|
||||
'systeminfo',
|
||||
'time',
|
||||
'timedatectl',
|
||||
'tracepath',
|
||||
@ -319,27 +320,27 @@ def helptext():
|
||||
{parsers_string}
|
||||
Options:
|
||||
-a about jc
|
||||
-d debug - show traceback (-dd for verbose traceback)
|
||||
-h help (use -h --parser_name for parser documentation)
|
||||
-d debug (-dd for verbose debug)
|
||||
-h help (-h --parser_name for parser documentation)
|
||||
-m monochrome output
|
||||
-p pretty print output
|
||||
-q quiet - suppress parser warnings
|
||||
-r raw JSON output
|
||||
-v version info
|
||||
|
||||
Example:
|
||||
ls -al | jc --ls -p
|
||||
Examples:
|
||||
Standard Syntax:
|
||||
$ dig www.google.com | jc --dig -p
|
||||
|
||||
or using the magic syntax:
|
||||
Magic Syntax:
|
||||
$ jc -p dig www.google.com
|
||||
|
||||
jc -p ls -al
|
||||
|
||||
For parser documentation:
|
||||
|
||||
jc -h --ls
|
||||
Parser Documentation:
|
||||
$ jc -h --dig
|
||||
'''
|
||||
return textwrap.dedent(helptext_string)
|
||||
|
||||
|
||||
def help_doc(options):
|
||||
"""
|
||||
Returns the parser documentation if a parser is found in the arguments, otherwise
|
||||
@ -362,6 +363,7 @@ Version {parser.info.version} by {parser.info.author} ({parser.info.author_email
|
||||
|
||||
return helptext()
|
||||
|
||||
|
||||
def versiontext():
|
||||
"""Return the version text"""
|
||||
versiontext_string = f'''\
|
||||
|
BIN
jc/man/jc.1.gz
BIN
jc/man/jc.1.gz
Binary file not shown.
@ -227,7 +227,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
version = '1.2'
|
||||
description = '`acpi` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -256,38 +256,19 @@ def _process(proc_data):
|
||||
float_list = ['temperature']
|
||||
|
||||
for entry in proc_data:
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = int(entry[key])
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
if key in float_list:
|
||||
entry[key] = jc.utils.convert_to_float(entry[key])
|
||||
|
||||
if 'trip_points' in entry:
|
||||
for tp in entry['trip_points']:
|
||||
for key in int_list:
|
||||
if key in tp:
|
||||
try:
|
||||
tp[key] = int(tp[key])
|
||||
except (ValueError):
|
||||
tp[key] = None
|
||||
|
||||
for entry in proc_data:
|
||||
for key in float_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = float(entry[key])
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
|
||||
if 'trip_points' in entry:
|
||||
for tp in entry['trip_points']:
|
||||
for key in float_list:
|
||||
if key in tp:
|
||||
try:
|
||||
tp[key] = float(tp[key])
|
||||
except (ValueError):
|
||||
tp[key] = None
|
||||
for key in tp:
|
||||
if key in int_list:
|
||||
tp[key] = jc.utils.convert_to_int(tp[key])
|
||||
if key in float_list:
|
||||
tp[key] = jc.utils.convert_to_float(tp[key])
|
||||
|
||||
for entry in proc_data:
|
||||
if 'until_charged' in entry:
|
||||
|
@ -80,7 +80,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.2'
|
||||
version = '1.3'
|
||||
description = '`airport -I` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -111,10 +111,7 @@ def _process(proc_data):
|
||||
'lasttxrate', 'maxrate', 'lastassocstatus', 'mcs']
|
||||
for key in proc_data:
|
||||
if key in int_list:
|
||||
try:
|
||||
proc_data[key] = int(proc_data[key])
|
||||
except (ValueError):
|
||||
proc_data[key] = None
|
||||
proc_data[key] = jc.utils.convert_to_int(proc_data[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -109,7 +109,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.3'
|
||||
version = '1.4'
|
||||
description = '`airport -s` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -137,23 +137,14 @@ def _process(proc_data):
|
||||
"""
|
||||
for entry in proc_data:
|
||||
|
||||
# integers
|
||||
# convert integers and booleans
|
||||
int_list = ['rssi']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = int(entry[key])
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
|
||||
# booleans
|
||||
bool_list = ['ht']
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
if key in bool_list:
|
||||
try:
|
||||
entry[key] = True if entry[key] == 'Y' else False
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
entry[key] = jc.utils.convert_to_bool(entry[key])
|
||||
|
||||
if 'security' in entry:
|
||||
entry['security'] = entry['security'].split()
|
||||
|
@ -150,12 +150,9 @@ def _process(proc_data):
|
||||
entry['name'] = None
|
||||
|
||||
int_list = ['expires']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = int(entry[key])
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -121,7 +121,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.3'
|
||||
version = '1.4'
|
||||
description = '`blkid` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -155,12 +155,9 @@ def _process(proc_data):
|
||||
'id_part_entry_offset', 'id_part_entry_size', 'minimum_io_size', 'physical_sector_size',
|
||||
'logical_sector_size', 'id_iolimit_minimum_io_size', 'id_iolimit_physical_sector_size',
|
||||
'id_iolimit_logical_sector_size']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = int(entry[key])
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -54,7 +54,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
version = '1.2'
|
||||
description = '`cksum` and `sum` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -82,12 +82,10 @@ def _process(proc_data):
|
||||
|
||||
for entry in proc_data:
|
||||
int_list = ['checksum', 'blocks']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = int(entry[key])
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
|
@ -98,7 +98,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.6'
|
||||
version = '1.7'
|
||||
description = '`df` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -144,11 +144,7 @@ def _process(proc_data):
|
||||
# change any entry for key with '_blocks' in the name to int
|
||||
for k in entry:
|
||||
if '_blocks' in str(k):
|
||||
try:
|
||||
blocks_int = int(entry[k])
|
||||
entry[k] = blocks_int
|
||||
except (ValueError):
|
||||
entry[k] = None
|
||||
entry[k] = jc.utils.convert_to_int(entry[k])
|
||||
|
||||
# remove percent sign from 'use_percent', 'capacity_percent', and 'iused_percent'
|
||||
if 'use_percent' in entry:
|
||||
@ -162,13 +158,9 @@ def _process(proc_data):
|
||||
|
||||
# change used, available, use_percent, capacity_percent, ifree, iused, iused_percent to int
|
||||
int_list = ['used', 'available', 'use_percent', 'capacity_percent', 'ifree', 'iused', 'iused_percent']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -21,64 +21,84 @@ Schema:
|
||||
|
||||
[
|
||||
{
|
||||
"id": integer,
|
||||
"opcode": string,
|
||||
"status": string,
|
||||
"id": integer,
|
||||
"opcode": string,
|
||||
"status": string,
|
||||
"flags": [
|
||||
string
|
||||
string
|
||||
],
|
||||
"query_num": integer,
|
||||
"answer_num": integer,
|
||||
"authority_num": integer,
|
||||
"additional_num": integer,
|
||||
"query_num": integer,
|
||||
"answer_num": integer,
|
||||
"authority_num": integer,
|
||||
"additional_num": integer,
|
||||
"axfr": [
|
||||
{
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
}
|
||||
],
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": integer,
|
||||
"flags": [
|
||||
string
|
||||
],
|
||||
"udp": integer
|
||||
},
|
||||
"cookie": string
|
||||
},
|
||||
"question": {
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
}
|
||||
],
|
||||
"additional": [
|
||||
{
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
}
|
||||
],
|
||||
"authority": [
|
||||
{
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
"name": string,
|
||||
"class": string,
|
||||
"type": string,
|
||||
"ttl": integer,
|
||||
"data": string
|
||||
}
|
||||
],
|
||||
"query_time": integer, # in msec
|
||||
"server": string,
|
||||
"when": string,
|
||||
"when_epoch": integer, # naive timestamp if when field is parsable, else null
|
||||
"when_epoch_utc": integer, # timezone aware timestamp availabe for UTC, else null
|
||||
"rcvd": integer
|
||||
"size": string
|
||||
"query_size": integer,
|
||||
"query_time": integer, # in msec
|
||||
"server": string,
|
||||
"when": string,
|
||||
"when_epoch": integer, # naive timestamp if when field is parsable, else null
|
||||
"when_epoch_utc": integer, # timezone aware timestamp availabe for UTC, else null
|
||||
"rcvd": integer
|
||||
"size": string
|
||||
}
|
||||
]
|
||||
|
||||
Examples:
|
||||
|
||||
$ dig cnn.com www.cnn.com @205.251.194.64 | jc --dig -p
|
||||
$ dig example.com | jc --dig -p
|
||||
[
|
||||
{
|
||||
"id": 52172,
|
||||
"id": 2951,
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
@ -87,113 +107,35 @@ Examples:
|
||||
"ra"
|
||||
],
|
||||
"query_num": 1,
|
||||
"answer_num": 4,
|
||||
"answer_num": 1,
|
||||
"authority_num": 0,
|
||||
"additional_num": 1,
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": 0,
|
||||
"flags": [],
|
||||
"udp": 4096
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "cnn.com.",
|
||||
"name": "example.com.",
|
||||
"class": "IN",
|
||||
"type": "A"
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"name": "example.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"data": "151.101.65.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"data": "151.101.129.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"data": "151.101.1.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": 27,
|
||||
"data": "151.101.193.67"
|
||||
"ttl": 39302,
|
||||
"data": "93.184.216.34"
|
||||
}
|
||||
],
|
||||
"query_time": 38,
|
||||
"server": "2600",
|
||||
"when": "Tue Mar 30 20:07:59 PDT 2021",
|
||||
"rcvd": 100,
|
||||
"when_epoch": 1617160079,
|
||||
"when_epoch_utc": null
|
||||
},
|
||||
{
|
||||
"id": 36292,
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
"qr",
|
||||
"aa",
|
||||
"rd"
|
||||
],
|
||||
"query_num": 1,
|
||||
"answer_num": 1,
|
||||
"authority_num": 4,
|
||||
"additional_num": 1,
|
||||
"question": {
|
||||
"name": "www.cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A"
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": "www.cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "CNAME",
|
||||
"ttl": 300,
|
||||
"data": "turner-tls.map.fastly.net."
|
||||
}
|
||||
],
|
||||
"authority": [
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": 3600,
|
||||
"data": "ns-1086.awsdns-07.org."
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": 3600,
|
||||
"data": "ns-1630.awsdns-11.co.uk."
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": 3600,
|
||||
"data": "ns-47.awsdns-05.com."
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": 3600,
|
||||
"data": "ns-576.awsdns-08.net."
|
||||
}
|
||||
],
|
||||
"query_time": 27,
|
||||
"server": "205.251.194.64#53(205.251.194.64)",
|
||||
"when": "Tue Mar 30 20:07:59 PDT 2021",
|
||||
"rcvd": 212,
|
||||
"when_epoch": 1617160079,
|
||||
"query_time": 49,
|
||||
"server": "2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)",
|
||||
"when": "Fri Apr 16 16:05:10 PDT 2021",
|
||||
"rcvd": 56,
|
||||
"when_epoch": 1618614310,
|
||||
"when_epoch_utc": null
|
||||
}
|
||||
]
|
||||
@ -201,7 +143,7 @@ Examples:
|
||||
$ dig cnn.com www.cnn.com @205.251.194.64 | jc --dig -p -r
|
||||
[
|
||||
{
|
||||
"id": "23843",
|
||||
"id": "46052",
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
@ -210,117 +152,41 @@ Examples:
|
||||
"ra"
|
||||
],
|
||||
"query_num": "1",
|
||||
"answer_num": "4",
|
||||
"answer_num": "1",
|
||||
"authority_num": "0",
|
||||
"additional_num": "1",
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": "0",
|
||||
"flags": [],
|
||||
"udp": "4096"
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "cnn.com.",
|
||||
"name": "example.com.",
|
||||
"class": "IN",
|
||||
"type": "A"
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"name": "example.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": "30",
|
||||
"data": "151.101.193.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": "30",
|
||||
"data": "151.101.1.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": "30",
|
||||
"data": "151.101.65.67"
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A",
|
||||
"ttl": "30",
|
||||
"data": "151.101.129.67"
|
||||
"ttl": "40426",
|
||||
"data": "93.184.216.34"
|
||||
}
|
||||
],
|
||||
"query_time": "24 msec",
|
||||
"server": "192.168.1.254#53(192.168.1.254)",
|
||||
"when": "Tue Nov 12 07:16:19 PST 2019",
|
||||
"rcvd": "100"
|
||||
},
|
||||
{
|
||||
"id": "8266",
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
"qr",
|
||||
"aa",
|
||||
"rd"
|
||||
],
|
||||
"query_num": "1",
|
||||
"answer_num": "1",
|
||||
"authority_num": "4",
|
||||
"additional_num": "1",
|
||||
"question": {
|
||||
"name": "www.cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "A"
|
||||
},
|
||||
"answer": [
|
||||
{
|
||||
"name": "www.cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "CNAME",
|
||||
"ttl": "300",
|
||||
"data": "turner-tls.map.fastly.net."
|
||||
}
|
||||
],
|
||||
"authority": [
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": "3600",
|
||||
"data": "ns-1086.awsdns-07.org."
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": "3600",
|
||||
"data": "ns-1630.awsdns-11.co.uk."
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": "3600",
|
||||
"data": "ns-47.awsdns-05.com."
|
||||
},
|
||||
{
|
||||
"name": "cnn.com.",
|
||||
"class": "IN",
|
||||
"type": "NS",
|
||||
"ttl": "3600",
|
||||
"data": "ns-576.awsdns-08.net."
|
||||
}
|
||||
],
|
||||
"query_time": "26 msec",
|
||||
"server": "205.251.194.64#53(205.251.194.64)",
|
||||
"when": "Tue Nov 12 07:16:19 PST 2019",
|
||||
"rcvd": "212"
|
||||
"query_time": "48 msec",
|
||||
"server": "2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)",
|
||||
"when": "Fri Apr 16 16:06:12 PDT 2021",
|
||||
"rcvd": "56"
|
||||
}
|
||||
]
|
||||
|
||||
$ dig -x 1.1.1.1 | jc --dig -p
|
||||
[
|
||||
{
|
||||
"id": 22191,
|
||||
"id": 20785,
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
@ -332,6 +198,13 @@ Examples:
|
||||
"answer_num": 1,
|
||||
"authority_num": 0,
|
||||
"additional_num": 1,
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": 0,
|
||||
"flags": [],
|
||||
"udp": 4096
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "1.1.1.1.in-addr.arpa.",
|
||||
"class": "IN",
|
||||
@ -346,11 +219,11 @@ Examples:
|
||||
"data": "one.one.one.one."
|
||||
}
|
||||
],
|
||||
"query_time": 44,
|
||||
"server": "2600",
|
||||
"when": "Tue Mar 30 20:10:34 PDT 2021",
|
||||
"query_time": 40,
|
||||
"server": "2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)",
|
||||
"when": "Sat Apr 17 14:50:50 PDT 2021",
|
||||
"rcvd": 78,
|
||||
"when_epoch": 1617160234,
|
||||
"when_epoch": 1618696250,
|
||||
"when_epoch_utc": null
|
||||
}
|
||||
]
|
||||
@ -358,7 +231,7 @@ Examples:
|
||||
$ dig -x 1.1.1.1 | jc --dig -p -r
|
||||
[
|
||||
{
|
||||
"id": "50986",
|
||||
"id": "32644",
|
||||
"opcode": "QUERY",
|
||||
"status": "NOERROR",
|
||||
"flags": [
|
||||
@ -370,6 +243,13 @@ Examples:
|
||||
"answer_num": "1",
|
||||
"authority_num": "0",
|
||||
"additional_num": "1",
|
||||
"opt_pseudosection": {
|
||||
"edns": {
|
||||
"version": "0",
|
||||
"flags": [],
|
||||
"udp": "4096"
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"name": "1.1.1.1.in-addr.arpa.",
|
||||
"class": "IN",
|
||||
@ -384,9 +264,9 @@ Examples:
|
||||
"data": "one.one.one.one."
|
||||
}
|
||||
],
|
||||
"query_time": "38 msec",
|
||||
"server": "2600",
|
||||
"when": "Tue Nov 12 07:17:19 PST 2019",
|
||||
"query_time": "52 msec",
|
||||
"server": "2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)",
|
||||
"when": "Sat Apr 17 14:51:46 PDT 2021",
|
||||
"rcvd": "78"
|
||||
}
|
||||
]
|
||||
@ -396,7 +276,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.7'
|
||||
version = '2.0'
|
||||
description = '`dig` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -421,47 +301,36 @@ def _process(proc_data):
|
||||
|
||||
List of Dictionaries. Structured data to conform to the schema.
|
||||
"""
|
||||
|
||||
for entry in proc_data:
|
||||
int_list = ['id', 'query_num', 'answer_num', 'authority_num', 'additional_num', 'rcvd']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
int_list = ['id', 'query_num', 'answer_num', 'authority_num', 'additional_num', 'rcvd',
|
||||
'query_size', 'query_time']
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
if 'axfr' in entry:
|
||||
for ax in entry['axfr']:
|
||||
try:
|
||||
ttl_int = int(ax['ttl'])
|
||||
ax['ttl'] = ttl_int
|
||||
except (ValueError):
|
||||
ax['ttl'] = None
|
||||
ax['ttl'] = jc.utils.convert_to_int(ax['ttl'])
|
||||
|
||||
if 'opt_pseudosection' in entry:
|
||||
if 'edns' in entry['opt_pseudosection']:
|
||||
if 'version' in entry['opt_pseudosection']['edns']:
|
||||
entry['opt_pseudosection']['edns']['version'] = jc.utils.convert_to_int(entry['opt_pseudosection']['edns']['version'])
|
||||
|
||||
if 'udp' in entry['opt_pseudosection']['edns']:
|
||||
entry['opt_pseudosection']['edns']['udp'] = jc.utils.convert_to_int(entry['opt_pseudosection']['edns']['udp'])
|
||||
|
||||
if 'answer' in entry:
|
||||
for ans in entry['answer']:
|
||||
try:
|
||||
ttl_int = int(ans['ttl'])
|
||||
ans['ttl'] = ttl_int
|
||||
except (ValueError):
|
||||
ans['ttl'] = None
|
||||
ans['ttl'] = jc.utils.convert_to_int(ans['ttl'])
|
||||
|
||||
if 'additional' in entry:
|
||||
for add in entry['additional']:
|
||||
add['ttl'] = jc.utils.convert_to_int(add['ttl'])
|
||||
|
||||
if 'authority' in entry:
|
||||
for auth in entry['authority']:
|
||||
try:
|
||||
ttl_int = int(auth['ttl'])
|
||||
auth['ttl'] = ttl_int
|
||||
except (ValueError):
|
||||
auth['ttl'] = None
|
||||
|
||||
if 'query_time' in entry:
|
||||
try:
|
||||
qt_int = int(entry['query_time'].split()[0])
|
||||
entry['query_time'] = qt_int
|
||||
except (ValueError):
|
||||
entry['query_time'] = None
|
||||
auth['ttl'] = jc.utils.convert_to_int(auth['ttl'])
|
||||
|
||||
if 'when' in entry:
|
||||
ts = jc.utils.timestamp(entry['when'])
|
||||
@ -507,6 +376,31 @@ def _parse_flags_line(flagsline):
|
||||
'additional_num': additional_num}
|
||||
|
||||
|
||||
def _parse_opt_pseudosection(optline):
|
||||
# ;; OPT PSEUDOSECTION:
|
||||
# ; EDNS: version: 0, flags:; udp: 4096
|
||||
# ; COOKIE: 1cbc06703eaef210
|
||||
if optline.startswith('; EDNS:'):
|
||||
optline_list = optline.replace(',', ' ').split(';')
|
||||
optline_first = optline_list[1]
|
||||
optline_rest = optline_list[2]
|
||||
_, _, ver, _, *flags = optline_first.split()
|
||||
udp = optline_rest.split()[-1]
|
||||
|
||||
return {
|
||||
'edns': {
|
||||
'version': ver,
|
||||
'flags': flags,
|
||||
'udp': udp
|
||||
}
|
||||
}
|
||||
|
||||
elif optline.startswith('; COOKIE:'):
|
||||
return {
|
||||
'cookie': optline.split()[2]
|
||||
}
|
||||
|
||||
|
||||
def _parse_question(question):
|
||||
# ;www.cnn.com. IN A
|
||||
question = question.split()
|
||||
@ -519,22 +413,6 @@ def _parse_question(question):
|
||||
'type': dns_type}
|
||||
|
||||
|
||||
def _parse_authority(authority):
|
||||
# cnn.com. 3600 IN NS ns-1086.awsdns-07.org.
|
||||
authority = authority.split()
|
||||
authority_name = authority[0]
|
||||
authority_class = authority[2]
|
||||
authority_type = authority[3]
|
||||
authority_ttl = authority[1]
|
||||
authority_data = authority[4]
|
||||
|
||||
return {'name': authority_name,
|
||||
'class': authority_class,
|
||||
'type': authority_type,
|
||||
'ttl': authority_ttl,
|
||||
'data': authority_data}
|
||||
|
||||
|
||||
def _parse_answer(answer):
|
||||
# www.cnn.com. 5 IN CNAME turner-tls.map.fastly.net.
|
||||
answer = answer.split(maxsplit=4)
|
||||
@ -574,6 +452,28 @@ def _parse_axfr(axfr):
|
||||
'data': axfr_data}
|
||||
|
||||
|
||||
def _parse_footer(footer):
|
||||
# footer consists of 4 lines
|
||||
# footer line 1
|
||||
if footer.startswith(';; Query time:'):
|
||||
return {'query_time': footer.split(':')[1].lstrip()}
|
||||
|
||||
# footer line 2
|
||||
if footer.startswith(';; SERVER:'):
|
||||
return {'server': footer.split(':', maxsplit=1)[1].lstrip()}
|
||||
|
||||
# footer line 3
|
||||
if footer.startswith(';; WHEN:'):
|
||||
return {'when': footer.split(':', maxsplit=1)[1].lstrip()}
|
||||
|
||||
# footer line 4 (last line)
|
||||
if footer.startswith(';; MSG SIZE rcvd:'):
|
||||
return {'rcvd': footer.split(':')[1].lstrip()}
|
||||
|
||||
elif footer.startswith(';; XFR size:'):
|
||||
return {'size': footer.split(':')[1].lstrip()}
|
||||
|
||||
|
||||
def parse(data, raw=False, quiet=False):
|
||||
"""
|
||||
Main text parsing function
|
||||
@ -597,106 +497,106 @@ def parse(data, raw=False, quiet=False):
|
||||
# remove blank lines
|
||||
cleandata = list(filter(None, cleandata))
|
||||
|
||||
question = False
|
||||
authority = False
|
||||
answer = False
|
||||
axfr = False
|
||||
|
||||
# section can be: header, flags, question, authority, answer, axfr, additional, opt_pseudosection, footer
|
||||
section = ''
|
||||
output_entry = {}
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
for line in cleandata:
|
||||
|
||||
# identify sections
|
||||
if line.startswith(';; Got answer:'):
|
||||
section = ''
|
||||
continue
|
||||
|
||||
if line.startswith('; <<>> ') and ' axfr ' in line.lower():
|
||||
question = False
|
||||
authority = False
|
||||
answer = False
|
||||
axfr = True
|
||||
section = 'axfr'
|
||||
axfr_list = []
|
||||
continue
|
||||
|
||||
if ';' not in line and axfr:
|
||||
axfr_list.append(_parse_axfr(line))
|
||||
output_entry.update({'axfr': axfr_list})
|
||||
continue
|
||||
|
||||
if line.startswith(';; ->>HEADER<<-'):
|
||||
section = 'header'
|
||||
if output_entry:
|
||||
raw_output.append(output_entry)
|
||||
output_entry = {}
|
||||
output_entry.update(_parse_header(line))
|
||||
continue
|
||||
|
||||
if line.startswith(';; flags:'):
|
||||
section = 'flags'
|
||||
output_entry.update(_parse_flags_line(line))
|
||||
continue
|
||||
|
||||
if line.startswith(';; QUESTION SECTION:'):
|
||||
question = True
|
||||
authority = False
|
||||
answer = False
|
||||
axfr = False
|
||||
if line.startswith(';; OPT PSEUDOSECTION:'):
|
||||
section = 'opt_pseudosection'
|
||||
continue
|
||||
|
||||
if question:
|
||||
output_entry['question'] = _parse_question(line)
|
||||
question = False
|
||||
authority = False
|
||||
answer = False
|
||||
axfr = False
|
||||
if line.startswith(';; QUESTION SECTION:'):
|
||||
section = 'question'
|
||||
continue
|
||||
|
||||
if line.startswith(';; AUTHORITY SECTION:'):
|
||||
question = False
|
||||
authority = True
|
||||
answer = False
|
||||
axfr = False
|
||||
section = 'authority'
|
||||
authority_list = []
|
||||
continue
|
||||
|
||||
if ';' not in line and authority:
|
||||
authority_list.append(_parse_authority(line))
|
||||
output_entry.update({'authority': authority_list})
|
||||
continue
|
||||
|
||||
if line.startswith(';; ANSWER SECTION:'):
|
||||
question = False
|
||||
authority = False
|
||||
answer = True
|
||||
axfr = False
|
||||
section = 'answer'
|
||||
answer_list = []
|
||||
continue
|
||||
|
||||
if ';' not in line and answer:
|
||||
if line.startswith(';; ADDITIONAL SECTION:'):
|
||||
section = 'additional'
|
||||
additional_list = []
|
||||
continue
|
||||
|
||||
if line.startswith(';; Query time:'):
|
||||
section = 'footer'
|
||||
output_entry.update(_parse_footer(line))
|
||||
continue
|
||||
|
||||
# parse sections
|
||||
|
||||
if line.startswith(';; QUERY SIZE:'):
|
||||
output_entry.update({'query_size': line.split(': ', maxsplit=1)[1]})
|
||||
continue
|
||||
|
||||
if not line.startswith(';') and section == 'axfr':
|
||||
axfr_list.append(_parse_axfr(line))
|
||||
output_entry.update({'axfr': axfr_list})
|
||||
continue
|
||||
|
||||
if section == 'opt_pseudosection':
|
||||
if 'opt_pseudosection' not in output_entry:
|
||||
output_entry['opt_pseudosection'] = {}
|
||||
output_entry['opt_pseudosection'].update(_parse_opt_pseudosection(line))
|
||||
continue
|
||||
|
||||
if section == 'question':
|
||||
output_entry['question'] = _parse_question(line)
|
||||
continue
|
||||
|
||||
if not line.startswith(';') and section == 'authority':
|
||||
authority_list.append(_parse_answer(line))
|
||||
output_entry.update({'authority': authority_list})
|
||||
continue
|
||||
|
||||
if not line.startswith(';') and section == 'answer':
|
||||
answer_list.append(_parse_answer(line))
|
||||
output_entry.update({'answer': answer_list})
|
||||
continue
|
||||
|
||||
# footer consists of 4 lines
|
||||
# footer line 1
|
||||
if line.startswith(';; Query time:'):
|
||||
output_entry.update({'query_time': line.split(':')[1].lstrip()})
|
||||
if not line.startswith(';') and section == 'additional':
|
||||
additional_list.append(_parse_answer(line))
|
||||
output_entry.update({'additional': additional_list})
|
||||
continue
|
||||
|
||||
# footer line 2
|
||||
if line.startswith(';; SERVER:'):
|
||||
output_entry.update({'server': line.split(':')[1].lstrip()})
|
||||
if section == 'footer':
|
||||
output_entry.update(_parse_footer(line))
|
||||
continue
|
||||
|
||||
# footer line 3
|
||||
if line.startswith(';; WHEN:'):
|
||||
output_entry.update({'when': line.split(':', maxsplit=1)[1].lstrip()})
|
||||
continue
|
||||
|
||||
# footer line 4 (last line)
|
||||
if line.startswith(';; MSG SIZE rcvd:'):
|
||||
output_entry.update({'rcvd': line.split(':')[1].lstrip()})
|
||||
|
||||
if output_entry:
|
||||
raw_output.append(output_entry)
|
||||
elif line.startswith(';; XFR size:'):
|
||||
output_entry.update({'size': line.split(':')[1].lstrip()})
|
||||
|
||||
if output_entry:
|
||||
raw_output.append(output_entry)
|
||||
if output_entry:
|
||||
raw_output.append(output_entry)
|
||||
|
||||
raw_output = list(filter(None, raw_output))
|
||||
|
||||
|
@ -121,7 +121,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
version = '1.2'
|
||||
description = '`dir` command parser'
|
||||
author = 'Rasheed Elsaleh'
|
||||
author_email = 'rasheed@rebelliondefense.com'
|
||||
@ -155,14 +155,9 @@ def _process(proc_data):
|
||||
|
||||
# add ints
|
||||
int_list = ["size"]
|
||||
for key in int_list:
|
||||
if entry.get(key):
|
||||
try:
|
||||
key_int = int(entry[key].replace(",", ""))
|
||||
except ValueError:
|
||||
entry[key] = None
|
||||
else:
|
||||
entry[key] = key_int
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -125,7 +125,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.2'
|
||||
version = '1.3'
|
||||
description = '`dmidecode` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -153,13 +153,9 @@ def _process(proc_data):
|
||||
"""
|
||||
for entry in proc_data:
|
||||
int_list = ['type', 'bytes']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
if not entry['values']:
|
||||
entry['values'] = None
|
||||
|
@ -88,7 +88,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.3'
|
||||
version = '1.4'
|
||||
description = '`du` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -116,13 +116,9 @@ def _process(proc_data):
|
||||
"""
|
||||
int_list = ['size']
|
||||
for entry in proc_data:
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -66,6 +66,8 @@ def _process(proc_data):
|
||||
"""
|
||||
|
||||
# rebuild output for added semantic information
|
||||
# use helper functions in jc.utils for int, float, bool conversions and timestamps
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
|
@ -73,7 +73,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.3'
|
||||
version = '1.4'
|
||||
description = '`free` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -101,13 +101,9 @@ def _process(proc_data):
|
||||
|
||||
for entry in proc_data:
|
||||
int_list = ['total', 'used', 'free', 'shared', 'buff_cache', 'available']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -85,7 +85,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.4'
|
||||
version = '1.5'
|
||||
description = '`/etc/fstab` file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -111,13 +111,9 @@ def _process(proc_data):
|
||||
"""
|
||||
for entry in proc_data:
|
||||
int_list = ['fs_freq', 'fs_passno']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -109,7 +109,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.2'
|
||||
version = '1.3'
|
||||
description = '`/etc/group` file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -136,13 +136,9 @@ def _process(proc_data):
|
||||
"""
|
||||
for entry in proc_data:
|
||||
int_list = ['gid']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
if entry['members'] == ['']:
|
||||
entry['members'] = []
|
||||
|
@ -38,7 +38,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
version = '1.2'
|
||||
description = '`hash` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -63,15 +63,10 @@ def _process(proc_data):
|
||||
List of Dictionaries. Structured data to conform to the schema.
|
||||
"""
|
||||
for entry in proc_data:
|
||||
# change to int
|
||||
int_list = ['hits']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -317,7 +317,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
version = '1.2'
|
||||
description = '`hciconfig` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -346,15 +346,11 @@ def _process(proc_data):
|
||||
|
||||
for entry in proc_data:
|
||||
|
||||
# integers
|
||||
int_list = ['acl_mtu', 'acl_mtu_packets', 'sco_mtu', 'sco_mtu_packets', 'rx_bytes', 'rx_acl', 'rx_sco',
|
||||
'rx_events', 'rx_errors', 'tx_bytes', 'tx_acl', 'tx_sco', 'tx_commands', 'tx_errors']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = int(entry[key])
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
if 'service_classes' in entry and len(entry['service_classes']) == 1 and 'Unspecified' in entry['service_classes']:
|
||||
entry['service_classes'] = None
|
||||
|
@ -57,7 +57,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.4'
|
||||
version = '1.5'
|
||||
description = '`history` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -82,12 +82,10 @@ def _process(proc_data):
|
||||
|
||||
List of Dictionaries. Structured data to conform to the schema.
|
||||
"""
|
||||
|
||||
# rebuild output for added semantic information
|
||||
processed = []
|
||||
for k, v in proc_data.items():
|
||||
proc_line = {
|
||||
'line': int(k) if k.isdigit() else None,
|
||||
'line': jc.utils.convert_to_int(k),
|
||||
'command': v,
|
||||
}
|
||||
processed.append(proc_line)
|
||||
|
@ -105,7 +105,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.2'
|
||||
version = '1.3'
|
||||
description = '`id` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -133,25 +133,16 @@ def _process(proc_data):
|
||||
"""
|
||||
if 'uid' in proc_data:
|
||||
if 'id' in proc_data['uid']:
|
||||
try:
|
||||
proc_data['uid']['id'] = int(proc_data['uid']['id'])
|
||||
except (ValueError):
|
||||
proc_data['uid']['id'] = None
|
||||
proc_data['uid']['id'] = jc.utils.convert_to_int(proc_data['uid']['id'])
|
||||
|
||||
if 'gid' in proc_data:
|
||||
if 'id' in proc_data['gid']:
|
||||
try:
|
||||
proc_data['gid']['id'] = int(proc_data['gid']['id'])
|
||||
except (ValueError):
|
||||
proc_data['gid']['id'] = None
|
||||
proc_data['gid']['id'] = jc.utils.convert_to_int(proc_data['gid']['id'])
|
||||
|
||||
if 'groups' in proc_data:
|
||||
for group in proc_data['groups']:
|
||||
if 'id' in group:
|
||||
try:
|
||||
group['id'] = int(group['id'])
|
||||
except (ValueError):
|
||||
group['id'] = None
|
||||
group['id'] = jc.utils.convert_to_int(group['id'])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -188,7 +188,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.9'
|
||||
version = '1.10'
|
||||
description = '`ifconfig` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -264,7 +264,7 @@ class _IfconfigParser(object):
|
||||
:return:
|
||||
"""
|
||||
for attr in kwargs.keys():
|
||||
if attr not in IfconfigParser.attributes:
|
||||
if attr not in _IfconfigParser.attributes:
|
||||
raise ValueError("Attribute [{}] not supported.".format(attr))
|
||||
|
||||
filtered_interfaces = []
|
||||
@ -398,7 +398,8 @@ class _IfconfigParser(object):
|
||||
if match:
|
||||
details = match.groupdict()
|
||||
for k, v in details.items():
|
||||
if isinstance(v, str): details[k] = v.strip()
|
||||
if isinstance(v, str):
|
||||
details[k] = v.strip()
|
||||
_interface.update(details)
|
||||
if _interface is not None:
|
||||
available_interfaces[_interface['name']] = self.update_interface_details(_interface)
|
||||
@ -433,13 +434,9 @@ def _process(proc_data):
|
||||
int_list = ['flags', 'mtu', 'ipv6_mask', 'rx_packets', 'rx_bytes', 'rx_errors', 'rx_dropped', 'rx_overruns',
|
||||
'rx_frame', 'tx_packets', 'tx_bytes', 'tx_errors', 'tx_dropped', 'tx_overruns', 'tx_carrier',
|
||||
'tx_collisions', 'metric']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError, TypeError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
# convert OSX-style subnet mask to dotted quad
|
||||
if 'ipv4_mask' in entry:
|
||||
|
@ -163,7 +163,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.5'
|
||||
version = '1.6'
|
||||
description = '`iptables` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -191,13 +191,9 @@ def _process(proc_data):
|
||||
for entry in proc_data:
|
||||
for rule in entry['rules']:
|
||||
int_list = ['num', 'pkts']
|
||||
for key in int_list:
|
||||
if key in rule:
|
||||
try:
|
||||
key_int = int(rule[key])
|
||||
rule[key] = key_int
|
||||
except (ValueError):
|
||||
rule[key] = None
|
||||
for key in rule:
|
||||
if key in int_list:
|
||||
rule[key] = jc.utils.convert_to_int(rule[key])
|
||||
|
||||
if 'bytes' in rule:
|
||||
multiplier = 1
|
||||
@ -218,7 +214,7 @@ def _process(proc_data):
|
||||
rule['bytes'] = rule['bytes'].rstrip('P')
|
||||
|
||||
try:
|
||||
bytes_int = int(rule['bytes'])
|
||||
bytes_int = jc.utils.convert_to_int(rule['bytes'])
|
||||
rule['bytes'] = bytes_int * multiplier
|
||||
except (ValueError):
|
||||
rule['bytes'] = None
|
||||
|
@ -95,7 +95,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.3'
|
||||
version = '1.4'
|
||||
description = '`jobs` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -122,13 +122,9 @@ def _process(proc_data):
|
||||
"""
|
||||
for entry in proc_data:
|
||||
int_list = ['job_number', 'pid']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -104,7 +104,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.6'
|
||||
version = '1.7'
|
||||
description = '`last` and `lastb` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -161,7 +161,7 @@ def _process(proc_data):
|
||||
entry['logout_epoch'] = timestamp.naive
|
||||
|
||||
if 'login_epoch' in entry and 'logout_epoch' in entry:
|
||||
entry['duration_seconds'] = int(entry['logout_epoch']) - int(entry['login_epoch'])
|
||||
entry['duration_seconds'] = entry['logout_epoch'] - entry['login_epoch']
|
||||
|
||||
if 'duration' in entry and re.match(r'^\d+\+', entry['duration']):
|
||||
m = re.match(r'^(?P<days>\d+)\+(?P<hours>\d\d):(?P<minutes>\d\d)', entry['duration'])
|
||||
|
@ -3,7 +3,6 @@
|
||||
Options supported:
|
||||
- `lbaR1`
|
||||
- `--time-style=full-iso`
|
||||
- `-h`: File sizes will be available in text form with `-r` but larger file sizes with human readable suffixes will be converted to `Null` in the default view since the parser attempts to convert this field to an integer.
|
||||
|
||||
Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly parse filenames that include newline characters. Since `ls` does not encode newlines in filenames when outputting to a pipe it will cause `jc` to see multiple files instead of a single file if `-1`, `-l`, or `-b` is not used. Alternatively, `vdir` can be used, which is the same as running `ls -lb`.
|
||||
|
||||
@ -108,7 +107,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.8'
|
||||
version = '1.9'
|
||||
description = '`ls` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -135,13 +134,9 @@ def _process(proc_data):
|
||||
"""
|
||||
for entry in proc_data:
|
||||
int_list = ['links', 'size']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
if 'date' in entry:
|
||||
# to speed up processing only try to convert the date if it's not the default format
|
||||
|
@ -269,7 +269,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.6'
|
||||
version = '1.7'
|
||||
description = '`lsblk` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -295,25 +295,14 @@ def _process(proc_data):
|
||||
List of Dictionaries. Structured data to conform to the schema.
|
||||
"""
|
||||
for entry in proc_data:
|
||||
# boolean changes
|
||||
# boolean and integer changes
|
||||
bool_list = ['rm', 'ro', 'rota', 'disc_zero', 'rand']
|
||||
for key in bool_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_bool = bool(int(entry[key]))
|
||||
entry[key] = key_bool
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
|
||||
# integer changes
|
||||
int_list = ['ra', 'alignment', 'min_io', 'opt_io', 'phy_sec', 'log_sec', 'rq_size', 'disc_aln']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in bool_list:
|
||||
entry[key] = jc.utils.convert_to_bool(entry[key])
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -126,7 +126,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.4'
|
||||
version = '1.5'
|
||||
description = '`lsmod` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -152,15 +152,10 @@ def _process(proc_data):
|
||||
List of Dictionaries. Structured data to conform to the schema.
|
||||
"""
|
||||
for entry in proc_data:
|
||||
# integer changes
|
||||
int_list = ['size', 'used']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -120,7 +120,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.3'
|
||||
version = '1.4'
|
||||
description = '`lsof` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -146,15 +146,11 @@ def _process(proc_data):
|
||||
List of Dictionaries. Structured data to conform to the schema.
|
||||
"""
|
||||
for entry in proc_data:
|
||||
# integer changes
|
||||
int_list = ['pid', 'tid', 'size_off', 'node']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError, TypeError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
|
@ -349,11 +349,12 @@ Examples:
|
||||
}
|
||||
]
|
||||
"""
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.9'
|
||||
version = '1.10'
|
||||
description = '`netstat` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -379,7 +380,7 @@ def _process(proc_data):
|
||||
List of Dictionaries. Structured data to conform to the schema.
|
||||
"""
|
||||
for entry in proc_data:
|
||||
# integer changes
|
||||
# integer and float conversions
|
||||
int_list = ['recv_q', 'send_q', 'pid', 'refcnt', 'inode', 'unit', 'vendor', 'class',
|
||||
'osx_flags', 'subcla', 'pcbcount', 'rcvbuf', 'sndbuf', 'rxbytes', 'txbytes',
|
||||
'route_refs', 'use', 'mtu', 'mss', 'window', 'irtt', 'metric', 'ipkts',
|
||||
@ -387,35 +388,23 @@ def _process(proc_data):
|
||||
'tx_ok', 'tx_err', 'tx_drp', 'tx_ovr', 'idrop', 'ibytes', 'obytes', 'r_mbuf',
|
||||
's_mbuf', 'r_clus', 's_clus', 'r_hiwa', 's_hiwa', 'r_lowa', 's_lowa', 'r_bcnt',
|
||||
's_bcnt', 'r_bmax', 's_bmax', 'rexmit', 'ooorcv', '0_win']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
|
||||
# float changes
|
||||
float_list = ['rexmt', 'persist', 'keep', '2msl', 'delack', 'rcvtime']
|
||||
for key in float_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_float = float(entry[key])
|
||||
entry[key] = key_float
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
if key in float_list:
|
||||
entry[key] = jc.utils.convert_to_float(entry[key])
|
||||
|
||||
# add number keys
|
||||
if 'local_port' in entry:
|
||||
try:
|
||||
entry['local_port_num'] = int(entry['local_port'])
|
||||
except (ValueError):
|
||||
pass
|
||||
local_num = jc.utils.convert_to_int(entry['local_port'])
|
||||
if local_num:
|
||||
entry['local_port_num'] = local_num
|
||||
|
||||
if 'foreign_port' in entry:
|
||||
try:
|
||||
entry['foreign_port_num'] = int(entry['foreign_port'])
|
||||
except (ValueError):
|
||||
pass
|
||||
foreign_num = jc.utils.convert_to_int(entry['foreign_port'])
|
||||
if foreign_num:
|
||||
entry['foreign_port_num'] = foreign_num
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -207,7 +207,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.4'
|
||||
version = '1.5'
|
||||
description = '`ntpq -p` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -240,20 +240,12 @@ def _process(proc_data):
|
||||
entry['state'] = entry.pop('s')
|
||||
|
||||
int_list = ['st', 'when', 'poll', 'reach']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = int(entry[key])
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
|
||||
float_list = ['delay', 'offset', 'jitter']
|
||||
for key in float_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = float(entry[key])
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
if key in float_list:
|
||||
entry[key] = jc.utils.convert_to_float(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -94,7 +94,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.2'
|
||||
version = '1.3'
|
||||
description = '`/etc/passwd` file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -121,13 +121,9 @@ def _process(proc_data):
|
||||
"""
|
||||
for entry in proc_data:
|
||||
int_list = ['uid', 'gid']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -146,7 +146,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.3'
|
||||
version = '1.4'
|
||||
description = '`ping` and `ping6` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -175,34 +175,20 @@ def _process(proc_data):
|
||||
float_list = ['packet_loss_percent', 'round_trip_ms_min', 'round_trip_ms_avg', 'round_trip_ms_max',
|
||||
'round_trip_ms_stddev', 'timestamp', 'time_ms']
|
||||
|
||||
for key in proc_data.keys():
|
||||
for item in int_list:
|
||||
if item == key:
|
||||
try:
|
||||
proc_data[key] = int(proc_data[key])
|
||||
except (ValueError, TypeError):
|
||||
proc_data[key] = None
|
||||
for key in proc_data:
|
||||
if key in int_list:
|
||||
proc_data[key] = jc.utils.convert_to_int(proc_data[key])
|
||||
|
||||
for item in float_list:
|
||||
if item == key:
|
||||
try:
|
||||
proc_data[key] = float(proc_data[key])
|
||||
except (ValueError, TypeError):
|
||||
proc_data[key] = None
|
||||
if key in float_list:
|
||||
proc_data[key] = jc.utils.convert_to_float(proc_data[key])
|
||||
|
||||
if key == 'responses':
|
||||
for entry in proc_data['responses']:
|
||||
for k in entry.keys():
|
||||
for k in entry:
|
||||
if k in int_list:
|
||||
try:
|
||||
entry[k] = int(entry[k])
|
||||
except (ValueError, TypeError):
|
||||
entry[k] = None
|
||||
entry[k] = jc.utils.convert_to_int(entry[k])
|
||||
if k in float_list:
|
||||
try:
|
||||
entry[k] = float(entry[k])
|
||||
except (ValueError, TypeError):
|
||||
entry[k] = None
|
||||
entry[k] = jc.utils.convert_to_float(entry[k])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -207,7 +207,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.4'
|
||||
version = '1.5'
|
||||
description = '`ps` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -241,26 +241,16 @@ def _process(proc_data):
|
||||
if '%mem' in entry:
|
||||
entry['mem_percent'] = entry.pop('%mem')
|
||||
|
||||
# change to int
|
||||
# convert ints and floats
|
||||
int_list = ['pid', 'ppid', 'c', 'vsz', 'rss']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
|
||||
# change to float
|
||||
float_list = ['cpu_percent', 'mem_percent']
|
||||
for key in float_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_float = float(entry[key])
|
||||
entry[key] = key_float
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
if key in float_list:
|
||||
entry[key] = jc.utils.convert_to_float(entry[key])
|
||||
|
||||
# clean up other fields
|
||||
if 'tty' in entry:
|
||||
if entry['tty'] == '?' or entry['tty'] == '??':
|
||||
entry['tty'] = None
|
||||
|
@ -111,7 +111,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.5'
|
||||
version = '1.6'
|
||||
description = '`route` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -138,13 +138,9 @@ def _process(proc_data):
|
||||
"""
|
||||
for entry in proc_data:
|
||||
int_list = ['metric', 'ref', 'use', 'mss', 'window', 'irtt']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
# add flags_pretty
|
||||
# Flag mapping from https://www.man7.org/linux/man-pages/man8/route.8.html
|
||||
|
@ -156,7 +156,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.2'
|
||||
version = '1.3'
|
||||
description = '`rpm -qi` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -183,14 +183,11 @@ def _process(proc_data):
|
||||
List of Dictionaries. Structured data to conform to the schema.
|
||||
"""
|
||||
for entry in proc_data:
|
||||
|
||||
|
||||
int_list = ['epoch', 'size']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = int(entry[key])
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
if 'build_date' in entry:
|
||||
timestamp = jc.utils.timestamp(entry['build_date'])
|
||||
|
@ -101,7 +101,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.2'
|
||||
version = '1.3'
|
||||
description = '`/etc/shadow` file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -128,13 +128,9 @@ def _process(proc_data):
|
||||
"""
|
||||
for entry in proc_data:
|
||||
int_list = ['last_changed', 'minimum', 'maximum', 'warn', 'inactive', 'expire']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -279,7 +279,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.3'
|
||||
version = '1.4'
|
||||
description = '`ss` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -306,25 +306,19 @@ def _process(proc_data):
|
||||
"""
|
||||
for entry in proc_data:
|
||||
int_list = ['recv_q', 'send_q', 'pid']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
if 'local_port' in entry:
|
||||
try:
|
||||
entry['local_port_num'] = int(entry['local_port'])
|
||||
except (ValueError):
|
||||
pass
|
||||
local_num = jc.utils.convert_to_int(entry['local_port'])
|
||||
if local_num is not None and local_num >= 0:
|
||||
entry['local_port_num'] = local_num
|
||||
|
||||
if 'peer_port' in entry:
|
||||
try:
|
||||
entry['peer_port_num'] = int(entry['peer_port'])
|
||||
except (ValueError):
|
||||
pass
|
||||
peer_num = jc.utils.convert_to_int(entry['peer_port'])
|
||||
if peer_num is not None and peer_num >= 0:
|
||||
entry['peer_port_num'] = peer_num
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -169,7 +169,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.7'
|
||||
version = '1.8'
|
||||
description = '`stat` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -195,14 +195,11 @@ def _process(proc_data):
|
||||
List of Dictionaries. Structured data to conform to the schema.
|
||||
"""
|
||||
for entry in proc_data:
|
||||
int_list = ['size', 'blocks', 'io_blocks', 'inode', 'links', 'uid', 'gid', 'unix_device', 'rdev', 'block_size']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
int_list = ['size', 'blocks', 'io_blocks', 'inode', 'links', 'uid', 'gid', 'unix_device',
|
||||
'rdev', 'block_size']
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
# turn - into null for time fields and add calculated timestamp fields
|
||||
for entry in proc_data:
|
||||
|
@ -75,7 +75,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.4'
|
||||
version = '1.5'
|
||||
description = '`systemctl list-jobs` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -102,13 +102,10 @@ def _process(proc_data):
|
||||
"""
|
||||
for entry in proc_data:
|
||||
int_list = ['job']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
|
528
jc/parsers/systeminfo.py
Normal file
528
jc/parsers/systeminfo.py
Normal file
@ -0,0 +1,528 @@
|
||||
"""jc - JSON CLI output utility `systeminfo` command output parser
|
||||
|
||||
Blank or missing elements are set to `null`.
|
||||
|
||||
The `original_install_date_epoch` and `system_boot_time_epoch` calculated timestamp fields are naive (i.e. based on the local time of the system the parser is run on)
|
||||
|
||||
The `original_install_date_epoch_utc` and `system_boot_time_epoch_utc` calculated timestamp fields are timezone-aware and are only available if the timezone field is UTC.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ systeminfo | jc --systeminfo
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc.parsers.systeminfo
|
||||
result = jc.parsers.systeminfo.parse(systeminfo_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"host_name": string,
|
||||
"os_name": string,
|
||||
"os_version": string,
|
||||
"os_manufacturer": string,
|
||||
"os_configuration": string,
|
||||
"os_build_type": string,
|
||||
"registered_owner": string,
|
||||
"registered_organization": string,
|
||||
"product_id": string,
|
||||
"original_install_date": string,
|
||||
"original_install_date_epoch": integer, # naive timestamp
|
||||
"original_install_date_epoch_utc": integer, # timezone-aware timestamp
|
||||
"system_boot_time": string,
|
||||
"system_boot_time_epoch": integer, # naive timestamp
|
||||
"system_boot_time_epoch_utc": integer, # timezone-aware timestamp
|
||||
"system_manufacturer": string,
|
||||
"system_model": string,
|
||||
"system_type": string,
|
||||
"processors": [
|
||||
string
|
||||
],
|
||||
"bios_version": string,
|
||||
"windows_directory": string,
|
||||
"system_directory": string,
|
||||
"boot_device": string,
|
||||
"system_locale": string,
|
||||
"input_locale": string,
|
||||
"time_zone": string,
|
||||
"total_physical_memory_mb": string,
|
||||
"available_physical_memory_mb": integer,
|
||||
"virtual_memory_max_size_mb": integer,
|
||||
"virtual_memory_available_mb": integer,
|
||||
"virtual_memory_in_use_mb": integer,
|
||||
"page_file_locations": string,
|
||||
"domain": string,
|
||||
"logon_server": string,
|
||||
"hotfixs": [
|
||||
string
|
||||
],
|
||||
"network_cards": [
|
||||
{
|
||||
"name": string,
|
||||
"connection_name": string,
|
||||
"status": string,
|
||||
"dhcp_enabled": boolean,
|
||||
"dhcp_server": string,
|
||||
"ip_addresses": [
|
||||
string
|
||||
]
|
||||
}
|
||||
],
|
||||
"hyperv_requirements": {
|
||||
"vm_monitor_mode_extensions": boolean,
|
||||
"virtualization_enabled_in_firmware": boolean,
|
||||
"second_level_address_translation": boolean,
|
||||
"data_execution_prevention_available": boolean
|
||||
}
|
||||
}
|
||||
|
||||
Examples:
|
||||
|
||||
$ systeminfo | jc --systeminfo -p
|
||||
{
|
||||
"host_name": "TESTLAPTOP",
|
||||
"os_name": "Microsoft Windows 10 Enterprise",
|
||||
"os_version": "10.0.17134 N/A Build 17134",
|
||||
"os_manufacturer": "Microsoft Corporation",
|
||||
"os_configuration": "Member Workstation",
|
||||
"os_build_type": "Multiprocessor Free",
|
||||
"registered_owner": "Test, Inc.",
|
||||
"registered_organization": "Test, Inc.",
|
||||
"product_id": "11111-11111-11111-AA111",
|
||||
"original_install_date": "3/26/2019, 3:51:30 PM",
|
||||
"system_boot_time": "3/30/2021, 6:13:59 AM",
|
||||
"system_manufacturer": "Dell Inc.",
|
||||
"system_model": "Precision 5530",
|
||||
"system_type": "x64-based PC",
|
||||
"processors": [
|
||||
"Intel64 Family 6 Model 158 Stepping 10 GenuineIntel ~2592 Mhz"
|
||||
],
|
||||
"bios_version": "Dell Inc. 1.16.2, 4/21/2020",
|
||||
"windows_directory": "C:\\WINDOWS",
|
||||
"system_directory": "C:\\WINDOWS\\system32",
|
||||
"boot_device": "\\Device\\HarddiskVolume2",
|
||||
"system_locale": "en-us;English (United States)",
|
||||
"input_locale": "en-us;English (United States)",
|
||||
"time_zone": "(UTC+00:00) UTC",
|
||||
"total_physical_memory_mb": 32503,
|
||||
"available_physical_memory_mb": 19743,
|
||||
"virtual_memory_max_size_mb": 37367,
|
||||
"virtual_memory_available_mb": 22266,
|
||||
"virtual_memory_in_use_mb": 15101,
|
||||
"page_file_locations": "C:\\pagefile.sys",
|
||||
"domain": "test.com",
|
||||
"logon_server": "\\\\TESTDC01",
|
||||
"hotfixs": [
|
||||
"KB2693643",
|
||||
"KB4601054"
|
||||
],
|
||||
"network_cards": [
|
||||
{
|
||||
"name": "Intel(R) Wireless-AC 9260 160MHz",
|
||||
"connection_name": "Wi-Fi",
|
||||
"status": null,
|
||||
"dhcp_enabled": true,
|
||||
"dhcp_server": "192.168.2.1",
|
||||
"ip_addresses": [
|
||||
"192.168.2.219"
|
||||
]
|
||||
}
|
||||
],
|
||||
"hyperv_requirements": {
|
||||
"vm_monitor_mode_extensions": true,
|
||||
"virtualization_enabled_in_firmware": true,
|
||||
"second_level_address_translation": false,
|
||||
"data_execution_prevention_available": true
|
||||
},
|
||||
"original_install_date_epoch": 1553640690,
|
||||
"original_install_date_epoch_utc": 1553615490,
|
||||
"system_boot_time_epoch": 1617110039,
|
||||
"system_boot_time_epoch_utc": 1617084839
|
||||
}
|
||||
|
||||
$ systeminfo | jc --systeminfo -p -r
|
||||
{
|
||||
"host_name": "TESTLAPTOP",
|
||||
"os_name": "Microsoft Windows 10 Enterprise",
|
||||
"os_version": "10.0.17134 N/A Build 17134",
|
||||
"os_manufacturer": "Microsoft Corporation",
|
||||
"os_configuration": "Member Workstation",
|
||||
"os_build_type": "Multiprocessor Free",
|
||||
"registered_owner": "Test, Inc.",
|
||||
"registered_organization": "Test, Inc.",
|
||||
"product_id": "11111-11111-11111-AA111",
|
||||
"original_install_date": "3/26/2019, 3:51:30 PM",
|
||||
"system_boot_time": "3/30/2021, 6:13:59 AM",
|
||||
"system_manufacturer": "Dell Inc.",
|
||||
"system_model": "Precision 5530",
|
||||
"system_type": "x64-based PC",
|
||||
"processors": [
|
||||
"Intel64 Family 6 Model 158 Stepping 10 GenuineIntel ~2592 Mhz"
|
||||
],
|
||||
"bios_version": "Dell Inc. 1.16.2, 4/21/2020",
|
||||
"windows_directory": "C:\\WINDOWS",
|
||||
"system_directory": "C:\\WINDOWS\\system32",
|
||||
"boot_device": "\\Device\\HarddiskVolume2",
|
||||
"system_locale": "en-us;English (United States)",
|
||||
"input_locale": "en-us;English (United States)",
|
||||
"time_zone": "(UTC+00:00) UTC",
|
||||
"total_physical_memory_mb": "32,503 MB",
|
||||
"available_physical_memory_mb": "19,743 MB",
|
||||
"virtual_memory_max_size_mb": "37,367 MB",
|
||||
"virtual_memory_available_mb": "22,266 MB",
|
||||
"virtual_memory_in_use_mb": "15,101 MB",
|
||||
"page_file_locations": "C:\\pagefile.sys",
|
||||
"domain": "test.com",
|
||||
"logon_server": "\\\\TESTDC01",
|
||||
"hotfixs": [
|
||||
"KB2693643",
|
||||
"KB4601054"
|
||||
],
|
||||
"network_cards": [
|
||||
{
|
||||
"name": "Intel(R) Wireless-AC 9260 160MHz",
|
||||
"connection_name": "Wi-Fi",
|
||||
"status": "",
|
||||
"dhcp_enabled": "Yes",
|
||||
"dhcp_server": "192.168.2.1",
|
||||
"ip_addresses": [
|
||||
"192.168.2.219"
|
||||
]
|
||||
}
|
||||
],
|
||||
"hyperv_requirements": {
|
||||
"vm_monitor_mode_extensions": "Yes",
|
||||
"virtualization_enabled_in_firmware": "Yes",
|
||||
"second_level_address_translation": "No",
|
||||
"data_execution_prevention_available": "Yes"
|
||||
}
|
||||
}
|
||||
"""
|
||||
import re
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info:
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = "1.0"
|
||||
description = "`systeminfo` command parser"
|
||||
author = "Jon Smith"
|
||||
author_email = "jon@rebelliondefense.com"
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ["win32"]
|
||||
magic_commands = ["systeminfo"]
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _process(proc_data):
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (Dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Some keys are optional. Example: a system without hyper-v capabilities
|
||||
will not have a 'hyperv_requirements' key, and a system already running hyper-v
|
||||
will have an empty "hyperv_requirements" object.
|
||||
|
||||
Structured data to conform to the schema.
|
||||
"""
|
||||
# convert empty strings to None/null
|
||||
for item in proc_data:
|
||||
if isinstance(proc_data[item], str) and not proc_data[item]:
|
||||
proc_data[item] = None
|
||||
|
||||
for i, nic in enumerate(proc_data["network_cards"]):
|
||||
proc_data["network_cards"][i]["dhcp_enabled"] = jc.utils.convert_to_bool(
|
||||
nic["dhcp_enabled"]
|
||||
)
|
||||
|
||||
# convert empty strings to None/null
|
||||
for item in nic:
|
||||
if isinstance(nic[item], str) and not nic[item]:
|
||||
proc_data["network_cards"][i][item] = None
|
||||
|
||||
int_list = [
|
||||
"total_physical_memory_mb",
|
||||
"available_physical_memory_mb",
|
||||
"virtual_memory_max_size_mb",
|
||||
"virtual_memory_available_mb",
|
||||
"virtual_memory_in_use_mb",
|
||||
]
|
||||
for key in int_list:
|
||||
proc_data[key] = jc.utils.convert_to_int(proc_data[key])
|
||||
|
||||
dt_list = ["original_install_date", "system_boot_time"]
|
||||
for key in dt_list:
|
||||
tz = proc_data.get("time_zone", "")
|
||||
if tz:
|
||||
# convert
|
||||
# from: (UTC-08:00) Pacific Time (US & Canada)
|
||||
# to: (UTC-0800)
|
||||
tz_fields = tz.split()
|
||||
tz = " " + tz_fields[0].replace(":", "")
|
||||
proc_data[key + '_epoch'] = jc.utils.timestamp(f"{proc_data.get(key)}{tz}").naive
|
||||
proc_data[key + '_epoch_utc'] = jc.utils.timestamp(f"{proc_data.get(key)}{tz}").utc
|
||||
|
||||
hyperv_key = "hyperv_requirements"
|
||||
hyperv_subkey_list = [
|
||||
"vm_monitor_mode_extensions",
|
||||
"virtualization_enabled_in_firmware",
|
||||
"second_level_address_translation",
|
||||
"data_execution_prevention_available",
|
||||
]
|
||||
if hyperv_key in proc_data:
|
||||
for key in hyperv_subkey_list:
|
||||
if key in proc_data[hyperv_key]:
|
||||
proc_data[hyperv_key][key] = jc.utils.convert_to_bool(
|
||||
proc_data[hyperv_key][key]
|
||||
)
|
||||
|
||||
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:
|
||||
|
||||
List of Dictionaries. Raw or processed structured data.
|
||||
"""
|
||||
if not quiet:
|
||||
jc.utils.compatibility(__name__, info.compatible)
|
||||
|
||||
delim = ":" # k/v delimiter
|
||||
raw_data = {} # intermediary output
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
# keepends = True, so that multiline data retains return chars
|
||||
lines = [line for line in data.splitlines(keepends=True) if line.strip() != ""]
|
||||
|
||||
# find the character position of the value in the k/v pair of the first line
|
||||
# all subsequent lines of data use the same character position
|
||||
start_value_pos = _get_value_pos(lines[0], delim)
|
||||
|
||||
last_key = None
|
||||
for line in lines:
|
||||
key = line[0:start_value_pos]
|
||||
value = line[start_value_pos:]
|
||||
|
||||
# possible multiline data
|
||||
if last_key:
|
||||
# the value data doesn't start where it should
|
||||
# so this is multiline data
|
||||
if delim not in key:
|
||||
raw_data[last_key] += line
|
||||
continue
|
||||
|
||||
raw_data[key] = value
|
||||
last_key = key
|
||||
|
||||
# clean up keys; strip values
|
||||
raw_output = {}
|
||||
for k, v in raw_data.items():
|
||||
k = _transform_key(k)
|
||||
|
||||
# since we split on start_value_pos, the delimiter
|
||||
# is still in the key field. Remove it.
|
||||
k = k.rstrip(delim)
|
||||
|
||||
if k in ["hotfixs", "processors"]:
|
||||
raw_output[k] = _parse_hotfixs_or_processors(v)
|
||||
elif k in ["network_cards"]:
|
||||
raw_output[k] = _parse_network_cards(v)
|
||||
elif k in ["hyperv_requirements"]:
|
||||
raw_output[k] = _parse_hyperv_requirements(v)
|
||||
elif k in [
|
||||
"total_physical_memory",
|
||||
"available_physical_memory",
|
||||
"virtual_memory_max_size",
|
||||
"virtual_memory_available",
|
||||
"virtual_memory_in_use"
|
||||
]:
|
||||
raw_output[k + "_mb"] = v.strip()
|
||||
else:
|
||||
raw_output[k] = v.strip()
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return _process(raw_output)
|
||||
|
||||
|
||||
def _parse_hotfixs_or_processors(data):
|
||||
"""
|
||||
Turns a list of return-delimited hotfixes or processors
|
||||
with [x] as a prefix into an array of hotfixes
|
||||
|
||||
Note that if a high number of items exist, the list may cutoff
|
||||
and this list may not contain all items installed on the system
|
||||
|
||||
IRL, this likely applies to hotfixes more than processors
|
||||
|
||||
Parameters:
|
||||
data: (string) Input string
|
||||
"""
|
||||
arr_output = []
|
||||
for i, l in enumerate(data.splitlines()):
|
||||
# skip line that says how many are installed
|
||||
if i == 0:
|
||||
continue
|
||||
# we have to make sure this is a complete line
|
||||
# as data could cutoff. Make sure the delimiter
|
||||
# exists. Otherwise, skip it.
|
||||
if ":" in l:
|
||||
k, v = l.split(":")
|
||||
# discard the number sequence
|
||||
arr_output.append(v.strip())
|
||||
|
||||
return arr_output
|
||||
|
||||
|
||||
def _parse_hyperv_requirements(data):
|
||||
"""
|
||||
Turns a list of key/value settings for hyperv
|
||||
into an object
|
||||
|
||||
Parameters:
|
||||
data: (string) Input string
|
||||
"""
|
||||
output = {}
|
||||
for i, l in enumerate(data.splitlines()):
|
||||
if ":" in l:
|
||||
k, v = l.split(":")
|
||||
# discard the number sequence
|
||||
output[_transform_key(k)] = v.strip()
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def _parse_network_cards(data):
|
||||
"""
|
||||
Turns a list of network_cards into an array of objects
|
||||
|
||||
Parameters:
|
||||
data: (string) Input string
|
||||
"""
|
||||
delim = ":"
|
||||
arr_output = []
|
||||
cur_nic = None
|
||||
is_ip = False
|
||||
nic_value_pos = 0
|
||||
|
||||
for i, line in enumerate(data.splitlines()):
|
||||
# skip first line
|
||||
if i == 0:
|
||||
continue
|
||||
|
||||
if "IP address(es)" in line:
|
||||
is_ip = True
|
||||
continue
|
||||
|
||||
cur_value_pos = len(line) - len(line.lstrip())
|
||||
|
||||
line = line.strip()
|
||||
|
||||
m = re.match(r"\[(\d+)\]" + delim + "(.+)", line)
|
||||
if m and is_ip and cur_value_pos > nic_value_pos:
|
||||
cur_nic["ip_addresses"].append(m.group(2).strip())
|
||||
elif m:
|
||||
if cur_nic:
|
||||
arr_output.append(cur_nic)
|
||||
cur_nic = _default_nic()
|
||||
cur_nic["name"] = m.group(2).strip()
|
||||
nic_value_pos = cur_value_pos
|
||||
is_ip = False
|
||||
elif delim in line:
|
||||
k, v = line.split(delim)
|
||||
k = _transform_key(k)
|
||||
cur_nic[k] = v.strip()
|
||||
|
||||
if cur_nic:
|
||||
arr_output.append(cur_nic)
|
||||
|
||||
return arr_output
|
||||
|
||||
|
||||
def _convert_to_boolean(value):
|
||||
"""
|
||||
Converts string input to boolean assuming "Yes/No" inputs
|
||||
|
||||
Parameters:
|
||||
value: (string) Input value
|
||||
"""
|
||||
return value == "Yes"
|
||||
|
||||
|
||||
def _convert_to_int(value):
|
||||
"""
|
||||
Converts string input to integer by stripping all non-numeric characters
|
||||
|
||||
Parameters:
|
||||
value: (string) Input value
|
||||
"""
|
||||
try:
|
||||
value = int(re.sub("[^0-9]", "", value))
|
||||
except ValueError:
|
||||
pass
|
||||
return value
|
||||
|
||||
|
||||
def _default_nic():
|
||||
"""
|
||||
Returns a default network card object
|
||||
"""
|
||||
return {
|
||||
"name": "",
|
||||
"connection_name": "",
|
||||
"status": "",
|
||||
"dhcp_enabled": "No",
|
||||
"dhcp_server": "",
|
||||
"ip_addresses": [],
|
||||
}
|
||||
|
||||
|
||||
def _get_value_pos(line, delim):
|
||||
"""
|
||||
Finds the first non-whitespace character after the delimiter
|
||||
|
||||
Parameters:
|
||||
line: (string) Input string
|
||||
delim: (string) The data delimiter
|
||||
"""
|
||||
fields = line.split(delim, 1)
|
||||
if not len(fields) == 2:
|
||||
raise Exception(f"Expected a '{delim}' delimited field. Actual: {line}")
|
||||
|
||||
return len(line) - len(fields[1].lstrip())
|
||||
|
||||
|
||||
def _transform_key(key):
|
||||
"""
|
||||
Converts a given key to a valid json key that plays nice with jq
|
||||
|
||||
Parameters:
|
||||
key: (string) Input value
|
||||
"""
|
||||
# lowercase and replace spaces with underscores
|
||||
key = key.strip().lower().replace(" ", "_")
|
||||
|
||||
# remove invalid key characters
|
||||
for c in ";:!@#$%^&*()-":
|
||||
key = key.replace(c, "")
|
||||
return key
|
@ -123,7 +123,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
version = '1.2'
|
||||
description = '`/usr/bin/time` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -156,38 +156,30 @@ def _process(proc_data):
|
||||
*hours, minutes, seconds, centiseconds = proc_data['elapsed_time'].split(':')
|
||||
proc_data['elapsed_time'] = proc_data['elapsed_time'][::-1].replace(':', '.', 1)[::-1]
|
||||
if hours:
|
||||
proc_data['elapsed_time_hours'] = int(hours[0])
|
||||
proc_data['elapsed_time_hours'] = jc.utils.convert_to_int(hours[0])
|
||||
else:
|
||||
proc_data['elapsed_time_hours'] = 0
|
||||
proc_data['elapsed_time_minutes'] = int(minutes)
|
||||
proc_data['elapsed_time_seconds'] = int(seconds)
|
||||
proc_data['elapsed_time_centiseconds'] = int(centiseconds)
|
||||
proc_data['elapsed_time_minutes'] = jc.utils.convert_to_int(minutes)
|
||||
proc_data['elapsed_time_seconds'] = jc.utils.convert_to_int(seconds)
|
||||
proc_data['elapsed_time_centiseconds'] = jc.utils.convert_to_int(centiseconds)
|
||||
proc_data['elapsed_time_total_seconds'] = (proc_data['elapsed_time_hours'] * 3600) + \
|
||||
(proc_data['elapsed_time_minutes'] * 60) + \
|
||||
(proc_data['elapsed_time_seconds']) + \
|
||||
(proc_data['elapsed_time_centiseconds'] / 100)
|
||||
|
||||
int_list = ['elapsed_time_hours', 'elapsed_time_minutes', 'elapsed_time_seconds', 'elapsed_time_microseconds',
|
||||
'cpu_percent', 'average_shared_text_size', 'average_unshared_data_size', 'average_unshared_stack_size',
|
||||
# convert ints and floats
|
||||
int_list = ['cpu_percent', 'average_shared_text_size', 'average_unshared_data_size', 'average_unshared_stack_size',
|
||||
'average_shared_memory_size', 'maximum_resident_set_size', 'block_input_operations',
|
||||
'block_output_operations', 'major_pagefaults', 'minor_pagefaults', 'swaps', 'page_reclaims',
|
||||
'page_faults', 'messages_sent', 'messages_received', 'signals_received', 'voluntary_context_switches',
|
||||
'involuntary_context_switches', 'average_stack_size', 'average_total_size', 'average_resident_set_size',
|
||||
'signals_delivered', 'page_size', 'exit_status']
|
||||
for key in int_list:
|
||||
if key in proc_data:
|
||||
try:
|
||||
proc_data[key] = int(proc_data[key])
|
||||
except (ValueError, TypeError):
|
||||
proc_data[key] = None
|
||||
|
||||
float_list = ['real_time', 'user_time', 'system_time']
|
||||
for key in float_list:
|
||||
if key in proc_data:
|
||||
try:
|
||||
proc_data[key] = float(proc_data[key])
|
||||
except (ValueError):
|
||||
proc_data[key] = None
|
||||
for key in proc_data:
|
||||
if key in int_list:
|
||||
proc_data[key] = jc.utils.convert_to_int(proc_data[key])
|
||||
if key in float_list:
|
||||
proc_data[key] = jc.utils.convert_to_float(proc_data[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -63,7 +63,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.3'
|
||||
version = '1.4'
|
||||
description = '`timedatectl status` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -89,15 +89,11 @@ def _process(proc_data):
|
||||
|
||||
Dictionary. Structured data to conform to the schema.
|
||||
"""
|
||||
# boolean changes
|
||||
bool_list = ['ntp_enabled', 'ntp_synchronized', 'rtc_in_local_tz', 'dst_active',
|
||||
'system_clock_synchronized', 'systemd-timesyncd.service_active']
|
||||
for key in proc_data:
|
||||
if key in bool_list:
|
||||
try:
|
||||
proc_data[key] = True if proc_data[key] == 'yes' else False
|
||||
except (ValueError):
|
||||
proc_data[key] = None
|
||||
proc_data[key] = jc.utils.convert_to_bool(proc_data[key])
|
||||
|
||||
if 'universal_time' in proc_data:
|
||||
ts = jc.utils.timestamp(proc_data['universal_time'])
|
||||
|
@ -132,7 +132,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
version = '1.2'
|
||||
description = '`tracepath` and `tracepath6` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -157,39 +157,23 @@ def _process(proc_data):
|
||||
|
||||
Dictionary. Structured data to conform to the schema.
|
||||
"""
|
||||
# convert ints and floats
|
||||
int_list = ['pmtu', 'forward_hops', 'return_hops', 'ttl', 'asymmetric_difference']
|
||||
float_list = ['reply_ms']
|
||||
|
||||
for key, value in proc_data.items():
|
||||
for item in int_list:
|
||||
if key in int_list:
|
||||
try:
|
||||
proc_data[key] = int(proc_data[key])
|
||||
except (ValueError, TypeError):
|
||||
proc_data[key] = None
|
||||
|
||||
for item in int_list:
|
||||
if key in float_list:
|
||||
try:
|
||||
proc_data[key] = float(proc_data[key])
|
||||
except (ValueError, TypeError):
|
||||
proc_data[key] = None
|
||||
for key in proc_data:
|
||||
if key in int_list:
|
||||
proc_data[key] = jc.utils.convert_to_int(proc_data[key])
|
||||
if key in float_list:
|
||||
proc_data[key] = jc.utils.convert_to_float(proc_data[key])
|
||||
|
||||
if 'hops' in proc_data:
|
||||
for entry in proc_data['hops']:
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = int(entry[key])
|
||||
except (ValueError, TypeError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
for key in float_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = float(entry[key])
|
||||
except (ValueError, TypeError):
|
||||
entry[key] = None
|
||||
if key in float_list:
|
||||
entry[key] = jc.utils.convert_to_float(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -119,7 +119,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.2'
|
||||
version = '1.3'
|
||||
description = '`traceroute` and `traceroute6` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -335,35 +335,21 @@ def _process(proc_data):
|
||||
|
||||
if 'hops' in proc_data:
|
||||
for entry in proc_data['hops']:
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = int(entry[key])
|
||||
except (ValueError, TypeError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
for key in float_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = float(entry[key])
|
||||
except (ValueError, TypeError):
|
||||
entry[key] = None
|
||||
if key in float_list:
|
||||
entry[key] = jc.utils.convert_to_float(entry[key])
|
||||
|
||||
if 'probes' in entry:
|
||||
for item in entry['probes']:
|
||||
for key in int_list:
|
||||
if key in item:
|
||||
try:
|
||||
item[key] = int(item[key])
|
||||
except (ValueError, TypeError):
|
||||
item[key] = None
|
||||
for key in item:
|
||||
if key in int_list:
|
||||
item[key] = jc.utils.convert_to_int(item[key])
|
||||
|
||||
for key in float_list:
|
||||
if key in item:
|
||||
try:
|
||||
item[key] = float(item[key])
|
||||
except (ValueError, TypeError):
|
||||
item[key] = None
|
||||
if key in float_list:
|
||||
item[key] = jc.utils.convert_to_float(item[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -194,7 +194,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
version = '1.2'
|
||||
description = '`upower` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -225,7 +225,7 @@ def _process(proc_data):
|
||||
if 'updated' in entry:
|
||||
updated_list = entry['updated'].replace('(', '').replace(')', '').split()
|
||||
entry['updated'] = ' '.join(updated_list[:-3])
|
||||
entry['updated_seconds_ago'] = int(updated_list[-3])
|
||||
entry['updated_seconds_ago'] = jc.utils.convert_to_int(updated_list[-3])
|
||||
|
||||
if entry['updated']:
|
||||
ts = jc.utils.timestamp(entry['updated'])
|
||||
@ -236,20 +236,14 @@ def _process(proc_data):
|
||||
bool_list = ['power_supply', 'has_history', 'has_statistics', 'on_battery', 'lid_is_closed', 'lid_is_present']
|
||||
for key in entry:
|
||||
if key in bool_list:
|
||||
if entry[key].lower() == 'yes':
|
||||
entry[key] = True
|
||||
else:
|
||||
entry[key] = False
|
||||
entry[key] = jc.utils.convert_to_bool(entry[key])
|
||||
|
||||
# detail level boolean conversions
|
||||
bool_list = ['online', 'present', 'rechargeable']
|
||||
if 'detail' in entry:
|
||||
for key in entry['detail']:
|
||||
if key in bool_list:
|
||||
if entry['detail'][key].lower() == 'yes':
|
||||
entry['detail'][key] = True
|
||||
else:
|
||||
entry['detail'][key] = False
|
||||
entry['detail'][key] = jc.utils.convert_to_bool(entry['detail'][key])
|
||||
|
||||
# detail level convert warning to null if value is none
|
||||
if 'detail' in entry:
|
||||
@ -262,8 +256,8 @@ def _process(proc_data):
|
||||
add_items = []
|
||||
for key, value in entry['detail'].items():
|
||||
if value and isinstance(value, str):
|
||||
if len(value.split()) == 2 and value.split()[0].replace('.', '').isnumeric():
|
||||
entry['detail'][key] = float(value.split()[0])
|
||||
if len(value.split()) == 2:
|
||||
entry['detail'][key] = jc.utils.convert_to_float(value.split()[0])
|
||||
add_items.append({
|
||||
key + '_unit': value.split()[1]
|
||||
})
|
||||
@ -278,7 +272,7 @@ def _process(proc_data):
|
||||
for key, value in entry['detail'].items():
|
||||
if value and isinstance(value, str):
|
||||
if value[-1] == '%':
|
||||
entry['detail'][key] = float(value[:-1])
|
||||
entry['detail'][key] = jc.utils.convert_to_float(value)
|
||||
|
||||
# detail level fix quoted values
|
||||
if 'detail' in entry:
|
||||
@ -302,9 +296,9 @@ def _process(proc_data):
|
||||
new_history_obj = {}
|
||||
for key, value in history_obj.items():
|
||||
if key == 'time':
|
||||
new_history_obj[key] = int(value)
|
||||
new_history_obj[key] = jc.utils.convert_to_int(value)
|
||||
elif key == 'percent_charged':
|
||||
new_history_obj[key] = float(value)
|
||||
new_history_obj[key] = jc.utils.convert_to_float(value)
|
||||
else:
|
||||
new_history_obj[key] = value
|
||||
|
||||
|
@ -65,7 +65,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.4'
|
||||
version = '1.5'
|
||||
description = '`uptime` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -92,10 +92,10 @@ def _process(proc_data):
|
||||
"""
|
||||
if 'time' in proc_data:
|
||||
time_list = proc_data['time'].split(':')
|
||||
proc_data['time_hour'] = int(time_list[0])
|
||||
proc_data['time_minute'] = int(time_list[1])
|
||||
proc_data['time_hour'] = jc.utils.convert_to_int(time_list[0])
|
||||
proc_data['time_minute'] = jc.utils.convert_to_int(time_list[1])
|
||||
if len(time_list) == 3:
|
||||
proc_data['time_second'] = int(time_list[2])
|
||||
proc_data['time_second'] = jc.utils.convert_to_int(time_list[2])
|
||||
else:
|
||||
proc_data['time_second'] = None
|
||||
|
||||
@ -113,14 +113,14 @@ def _process(proc_data):
|
||||
uptime_total_seconds = 0
|
||||
|
||||
if 'min' in proc_data['uptime']:
|
||||
uptime_minutes = int(proc_data['uptime'].split()[-2])
|
||||
uptime_minutes = jc.utils.convert_to_int(proc_data['uptime'].split()[-2])
|
||||
|
||||
if ':' in proc_data['uptime']:
|
||||
uptime_hours = int(proc_data['uptime'].split()[-1].split(':')[-2])
|
||||
uptime_minutes = int(proc_data['uptime'].split(':')[-1])
|
||||
uptime_hours = jc.utils.convert_to_int(proc_data['uptime'].split()[-1].split(':')[-2])
|
||||
uptime_minutes = jc.utils.convert_to_int(proc_data['uptime'].split(':')[-1])
|
||||
|
||||
if 'day' in proc_data['uptime']:
|
||||
uptime_days = int(proc_data['uptime'].split()[0])
|
||||
uptime_days = jc.utils.convert_to_int(proc_data['uptime'].split()[0])
|
||||
|
||||
proc_data['uptime_days'] = uptime_days
|
||||
proc_data['uptime_hours'] = uptime_hours
|
||||
@ -129,25 +129,14 @@ def _process(proc_data):
|
||||
uptime_total_seconds = (uptime_days * 86400) + (uptime_hours * 3600) + (uptime_minutes * 60)
|
||||
proc_data['uptime_total_seconds'] = uptime_total_seconds
|
||||
|
||||
# integer conversions
|
||||
# integer and float conversions
|
||||
int_list = ['users']
|
||||
for key in int_list:
|
||||
if key in proc_data:
|
||||
try:
|
||||
key_int = int(proc_data[key])
|
||||
proc_data[key] = key_int
|
||||
except (ValueError):
|
||||
proc_data[key] = None
|
||||
|
||||
# float conversions
|
||||
float_list = ['load_1m', 'load_5m', 'load_15m']
|
||||
for key in float_list:
|
||||
if key in proc_data:
|
||||
try:
|
||||
key_float = float(proc_data[key])
|
||||
proc_data[key] = key_float
|
||||
except (ValueError):
|
||||
proc_data[key] = None
|
||||
for key in proc_data:
|
||||
if key in int_list:
|
||||
proc_data[key] = jc.utils.convert_to_int(proc_data[key])
|
||||
if key in float_list:
|
||||
proc_data[key] = jc.utils.convert_to_float(proc_data[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
@ -131,8 +131,8 @@ def _process(proc_data):
|
||||
"""
|
||||
for entry in proc_data:
|
||||
null_list = ['user', 'tty', 'from', 'login_at', 'idle', 'what']
|
||||
for key in null_list:
|
||||
if key in entry:
|
||||
for key in entry:
|
||||
if key in null_list:
|
||||
if entry[key] == '-':
|
||||
entry[key] = None
|
||||
|
||||
|
@ -54,7 +54,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
version = '1.2'
|
||||
description = '`wc` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@ -82,12 +82,10 @@ def _process(proc_data):
|
||||
|
||||
for entry in proc_data:
|
||||
int_list = ['lines', 'words', 'characters']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
entry[key] = int(entry[key])
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
for key in entry:
|
||||
if key in int_list:
|
||||
entry[key] = jc.utils.convert_to_int(entry[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user