mirror of
https://github.com/kellyjonbrazil/jc.git
synced 2026-04-05 17:50:11 +02:00
Compare commits
184 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4989445ef4 | ||
|
|
6770892acd | ||
|
|
d4eba8740f | ||
|
|
9f60760560 | ||
|
|
0a8f8ac934 | ||
|
|
6ae24c8244 | ||
|
|
d3679082a8 | ||
|
|
fb08b42dca | ||
|
|
4aeaa9f42a | ||
|
|
5f5693da04 | ||
|
|
5eb0f61727 | ||
|
|
958e998991 | ||
|
|
b78c1509f6 | ||
|
|
ce184d4d57 | ||
|
|
b4c3714ced | ||
|
|
5b7dfa0438 | ||
|
|
391a388476 | ||
|
|
d9c4e2ed4c | ||
|
|
0c42db38b1 | ||
|
|
2f9be8bf33 | ||
|
|
e8c00155e8 | ||
|
|
cc88fdd9ee | ||
|
|
d9de11ef1d | ||
|
|
0ceda97d09 | ||
|
|
d0dec92ba8 | ||
|
|
d420c008d8 | ||
|
|
f0b32db433 | ||
|
|
bc838eda59 | ||
|
|
afe55b6af0 | ||
|
|
dd3a3ac302 | ||
|
|
f9982a7947 | ||
|
|
07c1be9e9a | ||
|
|
f832b88755 | ||
|
|
0fac757efc | ||
|
|
fc15742065 | ||
|
|
6f2466a131 | ||
|
|
4b90e22f0a | ||
|
|
c493568785 | ||
|
|
1cdf004b77 | ||
|
|
a4ea504261 | ||
|
|
4c2c234c3b | ||
|
|
3d4c0f3e89 | ||
|
|
52fad02903 | ||
|
|
9dcabc057c | ||
|
|
db8c1079dd | ||
|
|
8f954673ab | ||
|
|
79522d1c7d | ||
|
|
a18bf03079 | ||
|
|
c02b6b5d82 | ||
|
|
f99b423284 | ||
|
|
d7d9d45d4f | ||
|
|
90065ec0cd | ||
|
|
51157ebb86 | ||
|
|
96d95c79ca | ||
|
|
e5da34c233 | ||
|
|
f09d657f77 | ||
|
|
0f4b0189f5 | ||
|
|
4666042abb | ||
|
|
027d544c2b | ||
|
|
f1967d0138 | ||
|
|
c1d896027d | ||
|
|
5c2d2a6618 | ||
|
|
997b269b0b | ||
|
|
61257e7525 | ||
|
|
53ee2c3631 | ||
|
|
8bfa0bddec | ||
|
|
ad61e6bc81 | ||
|
|
873b5ba8ac | ||
|
|
6ae50054e2 | ||
|
|
22a35f41bf | ||
|
|
961696c963 | ||
|
|
c7b7f1a5dc | ||
|
|
b5a0d650b1 | ||
|
|
573b279464 | ||
|
|
116e07f161 | ||
|
|
964868c8af | ||
|
|
c8dac32df8 | ||
|
|
72a0016bd8 | ||
|
|
2ad3167434 | ||
|
|
ddabfaa05c | ||
|
|
f857523ca7 | ||
|
|
00d53858e8 | ||
|
|
c008167e66 | ||
|
|
102344a041 | ||
|
|
c865298ef3 | ||
|
|
6ac03faf93 | ||
|
|
49c2701743 | ||
|
|
d1a271b08e | ||
|
|
7388ad19b9 | ||
|
|
2e63cb5fad | ||
|
|
e7f14d02b1 | ||
|
|
873771d05a | ||
|
|
d7de122e36 | ||
|
|
4ef0434f53 | ||
|
|
1aa2c99259 | ||
|
|
c2450b27b0 | ||
|
|
14d6d8b84f | ||
|
|
f0e3846c03 | ||
|
|
6ba64f1128 | ||
|
|
13bcdbc6c9 | ||
|
|
cfba62db20 | ||
|
|
18fb69e36e | ||
|
|
474eb0f3fd | ||
|
|
7f47b53370 | ||
|
|
dc2907d3ce | ||
|
|
1af85811e0 | ||
|
|
1c1b19a478 | ||
|
|
66942d64ba | ||
|
|
2fb6ae08d7 | ||
|
|
bf8811e03e | ||
|
|
c8b502c571 | ||
|
|
81c11a975c | ||
|
|
0d370eb403 | ||
|
|
7492c3f1e3 | ||
|
|
515a8a84b7 | ||
|
|
dd6680efb2 | ||
|
|
a7158373cd | ||
|
|
6d50ec7199 | ||
|
|
95dbf98e8e | ||
|
|
d49323e4eb | ||
|
|
08c1e2aec9 | ||
|
|
a2c137df2e | ||
|
|
fe27dcdb8f | ||
|
|
028e136161 | ||
|
|
9a85a0a4d5 | ||
|
|
3a1cbc4d50 | ||
|
|
77d334f7f3 | ||
|
|
53cdf863ac | ||
|
|
7b7e7fe0fe | ||
|
|
0c03132847 | ||
|
|
3b81f7e2a1 | ||
|
|
3d76437b43 | ||
|
|
4bc54c78ce | ||
|
|
3d303a96b9 | ||
|
|
33c99d031d | ||
|
|
caf7e9f69a | ||
|
|
9449f1f5d5 | ||
|
|
6bad164b5e | ||
|
|
bb5ba7ddb1 | ||
|
|
8b2e01d540 | ||
|
|
ff1159b1de | ||
|
|
a2fd3202a0 | ||
|
|
7b53715b91 | ||
|
|
e05fc0a510 | ||
|
|
43604c33f6 | ||
|
|
eb67c484ff | ||
|
|
a7b7bdd467 | ||
|
|
ab06989a18 | ||
|
|
657b722f94 | ||
|
|
dd2aecad27 | ||
|
|
c82c5c5c64 | ||
|
|
a1761cd68f | ||
|
|
d618a7f583 | ||
|
|
831a42f660 | ||
|
|
3b36022e5a | ||
|
|
d01dfa25f1 | ||
|
|
395a99037b | ||
|
|
025986c51d | ||
|
|
c56b83093f | ||
|
|
7c712a4133 | ||
|
|
9a0cfe6dfa | ||
|
|
a116cdbcec | ||
|
|
f2d616c98e | ||
|
|
42cbd1777d | ||
|
|
ebf375aac0 | ||
|
|
1f9050267e | ||
|
|
d7f9707a15 | ||
|
|
ab589ee3ed | ||
|
|
c84ec0361f | ||
|
|
47d2f8968a | ||
|
|
019c480bcc | ||
|
|
547c6d3d59 | ||
|
|
b5ebf8b76a | ||
|
|
c690e328f2 | ||
|
|
cbb92c1a95 | ||
|
|
beb41997c9 | ||
|
|
755a6faf11 | ||
|
|
021f8350a3 | ||
|
|
76583dcd2f | ||
|
|
bf033239a7 | ||
|
|
eb37fccd37 | ||
|
|
d04ad45331 | ||
|
|
db157b8ca7 | ||
|
|
68f277bb20 |
1
MANIFEST.in
Normal file
1
MANIFEST.in
Normal file
@@ -0,0 +1 @@
|
||||
graft tests/fixtures
|
||||
@@ -1,5 +1,41 @@
|
||||
jc changelog
|
||||
|
||||
20200303 v1.8.0
|
||||
- Added blkid command parser
|
||||
- Added last and lastb command parser
|
||||
- Added who command parser
|
||||
- Added CSV file parser
|
||||
- Added /etc/passwd file parser
|
||||
- Added /etc/shadow file parser
|
||||
- Added /etc/group file parser
|
||||
- Added /etc/gshadow file parser
|
||||
|
||||
20200227 v1.7.5
|
||||
- Updated ls parser to support filenames with newline characters
|
||||
|
||||
20200219 v1.7.4
|
||||
- Updated ls parser to support multiple directories, globbing, and -R (recursive)
|
||||
|
||||
20200211 v1.7.3
|
||||
- Add alternative 'magic' syntax: e.g. `jc ls -al`
|
||||
- Options can now be condensed (e.g. -prq is equivalant to -p -r -q)
|
||||
|
||||
20200208 v1.7.2
|
||||
- Include test fixtures in wheel and sdist
|
||||
|
||||
20200205 v1.7.1
|
||||
- Add YAML file parser
|
||||
- Add INI file parser
|
||||
- Add XML file parser
|
||||
- Add id parser (tested on linux and OSX)
|
||||
- Add crontab file parser with user support (tested on linux)
|
||||
- Add __version__ variable to parser modules
|
||||
- Add exit code on error
|
||||
- Updated history parser to output "line" as an integer
|
||||
- Updated compatibility list for some parsers
|
||||
- Bugfix in crontab file parser: header insertion was clobbering first row
|
||||
- Just-in-time loading of parser modules instead of loading all at start
|
||||
|
||||
20191217 v1.6.1
|
||||
- Add du parser (tested on linux and OSX)
|
||||
- Add crontab parser (tested on linux and OSX)
|
||||
|
||||
13
docgen.sh
13
docgen.sh
@@ -5,28 +5,38 @@ cd jc
|
||||
pydocmd simple jc+ > ../docs/readme.md
|
||||
pydocmd simple utils+ > ../docs/utils.md
|
||||
pydocmd simple jc.parsers.arp+ > ../docs/parsers/arp.md
|
||||
pydocmd simple jc.parsers.blkid+ > ../docs/parsers/blkid.md
|
||||
pydocmd simple jc.parsers.crontab+ > ../docs/parsers/crontab.md
|
||||
pydocmd simple jc.parsers.crontab_u+ > ../docs/parsers/crontab_u.md
|
||||
pydocmd simple jc.parsers.csv+ > ../docs/parsers/csv.md
|
||||
pydocmd simple jc.parsers.df+ > ../docs/parsers/df.md
|
||||
pydocmd simple jc.parsers.dig+ > ../docs/parsers/dig.md
|
||||
pydocmd simple jc.parsers.du+ > ../docs/parsers/du.md
|
||||
pydocmd simple jc.parsers.env+ > ../docs/parsers/env.md
|
||||
pydocmd simple jc.parsers.free+ > ../docs/parsers/free.md
|
||||
pydocmd simple jc.parsers.fstab+ > ../docs/parsers/fstab.md
|
||||
pydocmd simple jc.parsers.group+ > ../docs/parsers/group.md
|
||||
pydocmd simple jc.parsers.gshadow+ > ../docs/parsers/gshadow.md
|
||||
pydocmd simple jc.parsers.history+ > ../docs/parsers/history.md
|
||||
pydocmd simple jc.parsers.hosts+ > ../docs/parsers/hosts.md
|
||||
pydocmd simple jc.parsers.id+ > ../docs/parsers/id.md
|
||||
pydocmd simple jc.parsers.ifconfig+ > ../docs/parsers/ifconfig.md
|
||||
pydocmd simple jc.parsers.ini+ > ../docs/parsers/ini.md
|
||||
pydocmd simple jc.parsers.iptables+ > ../docs/parsers/iptables.md
|
||||
pydocmd simple jc.parsers.jobs+ > ../docs/parsers/jobs.md
|
||||
pydocmd simple jc.parsers.last+ > ../docs/parsers/last.md
|
||||
pydocmd simple jc.parsers.ls+ > ../docs/parsers/ls.md
|
||||
pydocmd simple jc.parsers.lsblk+ > ../docs/parsers/lsblk.md
|
||||
pydocmd simple jc.parsers.lsmod+ > ../docs/parsers/lsmod.md
|
||||
pydocmd simple jc.parsers.lsof+ > ../docs/parsers/lsof.md
|
||||
pydocmd simple jc.parsers.mount+ > ../docs/parsers/mount.md
|
||||
pydocmd simple jc.parsers.netstat+ > ../docs/parsers/netstat.md
|
||||
pydocmd simple jc.parsers.passwd+ > ../docs/parsers/passwd.md
|
||||
pydocmd simple jc.parsers.pip_list+ > ../docs/parsers/pip_list.md
|
||||
pydocmd simple jc.parsers.pip_show+ > ../docs/parsers/pip_show.md
|
||||
pydocmd simple jc.parsers.ps+ > ../docs/parsers/ps.md
|
||||
pydocmd simple jc.parsers.route+ > ../docs/parsers/route.md
|
||||
pydocmd simple jc.parsers.shadow+ > ../docs/parsers/shadow.md
|
||||
pydocmd simple jc.parsers.ss+ > ../docs/parsers/ss.md
|
||||
pydocmd simple jc.parsers.stat+ > ../docs/parsers/stat.md
|
||||
pydocmd simple jc.parsers.systemctl+ > ../docs/parsers/systemctl.md
|
||||
@@ -36,3 +46,6 @@ pydocmd simple jc.parsers.systemctl_luf+ > ../docs/parsers/systemctl_luf.md
|
||||
pydocmd simple jc.parsers.uname+ > ../docs/parsers/uname.md
|
||||
pydocmd simple jc.parsers.uptime+ > ../docs/parsers/uptime.md
|
||||
pydocmd simple jc.parsers.w+ > ../docs/parsers/w.md
|
||||
pydocmd simple jc.parsers.who+ > ../docs/parsers/who.md
|
||||
pydocmd simple jc.parsers.xml+ > ../docs/parsers/xml.md
|
||||
pydocmd simple jc.parsers.yaml+ > ../docs/parsers/yaml.md
|
||||
|
||||
148
docs/parsers/blkid.md
Normal file
148
docs/parsers/blkid.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# jc.parsers.blkid
|
||||
jc - JSON CLI output utility blkid Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --blkid as the first argument if the piped input is coming from blkid
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux'
|
||||
|
||||
Examples:
|
||||
|
||||
$ blkid | jc --blkid -p
|
||||
[
|
||||
{
|
||||
"device": "/dev/sda1",
|
||||
"uuid": "05d927ab-5875-49e4-ada1-7f46cb32c932",
|
||||
"type": "xfs"
|
||||
},
|
||||
{
|
||||
"device": "/dev/sda2",
|
||||
"uuid": "3klkIj-w1kk-DkJi-0XBJ-y3i7-i2Ac-vHqWBM",
|
||||
"type": "LVM2_member"
|
||||
},
|
||||
{
|
||||
"device": "/dev/mapper/centos-root",
|
||||
"uuid": "07d718ff-950c-4e5b-98f0-42a1147c77d9",
|
||||
"type": "xfs"
|
||||
},
|
||||
{
|
||||
"device": "/dev/mapper/centos-swap",
|
||||
"uuid": "615eb89a-bcbf-46fd-80e3-c483ff5c931f",
|
||||
"type": "swap"
|
||||
}
|
||||
]
|
||||
|
||||
$ sudo blkid -o udev -ip /dev/sda2 | jc --blkid -p
|
||||
[
|
||||
{
|
||||
"id_fs_uuid": "3klkIj-w1kk-DkJi-0XBJ-y3i7-i2Ac-vHqWBM",
|
||||
"id_fs_uuid_enc": "3klkIj-w1kk-DkJi-0XBJ-y3i7-i2Ac-vHqWBM",
|
||||
"id_fs_version": "LVM2\x20001",
|
||||
"id_fs_type": "LVM2_member",
|
||||
"id_fs_usage": "raid",
|
||||
"id_iolimit_minimum_io_size": 512,
|
||||
"id_iolimit_physical_sector_size": 512,
|
||||
"id_iolimit_logical_sector_size": 512,
|
||||
"id_part_entry_scheme": "dos",
|
||||
"id_part_entry_type": "0x8e",
|
||||
"id_part_entry_number": 2,
|
||||
"id_part_entry_offset": 2099200,
|
||||
"id_part_entry_size": 39843840,
|
||||
"id_part_entry_disk": "8:0"
|
||||
}
|
||||
]
|
||||
|
||||
$ sudo blkid -ip /dev/sda1 | jc --blkid -p -r
|
||||
[
|
||||
{
|
||||
"devname": "/dev/sda1",
|
||||
"uuid": "05d927bb-5875-49e3-ada1-7f46cb31c932",
|
||||
"type": "xfs",
|
||||
"usage": "filesystem",
|
||||
"minimum_io_size": "512",
|
||||
"physical_sector_size": "512",
|
||||
"logical_sector_size": "512",
|
||||
"part_entry_scheme": "dos",
|
||||
"part_entry_type": "0x83",
|
||||
"part_entry_flags": "0x80",
|
||||
"part_entry_number": "1",
|
||||
"part_entry_offset": "2048",
|
||||
"part_entry_size": "2097152",
|
||||
"part_entry_disk": "8:0"
|
||||
}
|
||||
]
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"device": string,
|
||||
"uuid": string,
|
||||
"type": string,
|
||||
"usage": string,
|
||||
"part_entry_scheme": string,
|
||||
"part_entry_type": string,
|
||||
"part_entry_flags": string,
|
||||
"part_entry_number": integer,
|
||||
"part_entry_offset": integer,
|
||||
"part_entry_size": integer,
|
||||
"part_entry_disk": string,
|
||||
"id_fs_uuid": string,
|
||||
"id_fs_uuid_enc": string,
|
||||
"id_fs_version": string,
|
||||
"id_fs_type": string,
|
||||
"id_fs_usage": string,
|
||||
"id_part_entry_scheme": string,
|
||||
"id_part_entry_type": string,
|
||||
"id_part_entry_flags": string,
|
||||
"id_part_entry_number": integer,
|
||||
"id_part_entry_offset": integer,
|
||||
"id_part_entry_size": integer,
|
||||
"id_iolimit_minimum_io_size": integer,
|
||||
"id_iolimit_physical_sector_size": integer,
|
||||
"id_iolimit_logical_sector_size": integer,
|
||||
"id_part_entry_disk": string,
|
||||
"minimum_io_size": integer,
|
||||
"physical_sector_size": integer,
|
||||
"logical_sector_size": integer
|
||||
}
|
||||
]
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# jc.parsers.crontab
|
||||
jc - JSON CLI output utility crontab file Parser
|
||||
jc - JSON CLI output utility crontab command and file Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --crontab as the first argument if the piped input is coming from a crontab file
|
||||
specify --crontab as the first argument if the piped input is coming from crontab -l or a crontab file
|
||||
|
||||
Compatibility:
|
||||
|
||||
@@ -11,7 +11,7 @@ Compatibility:
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat /etc/crontab | jc --crontab -p
|
||||
$ crontab -l | jc --crontab -p
|
||||
{
|
||||
"variables": [
|
||||
{
|
||||
@@ -150,8 +150,8 @@ Returns:
|
||||
|
||||
{
|
||||
"variables": [
|
||||
"name": string,
|
||||
"value": string
|
||||
"name": string,
|
||||
"value": string
|
||||
],
|
||||
"schedule": [
|
||||
{
|
||||
|
||||
199
docs/parsers/crontab_u.md
Normal file
199
docs/parsers/crontab_u.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# jc.parsers.crontab_u
|
||||
jc - JSON CLI output utility crontab file Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --crontab-u as the first argument if the piped input is coming from a crontab file with User specified
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat /etc/crontab | jc --crontab-u -p
|
||||
{
|
||||
"variables": [
|
||||
{
|
||||
"name": "PATH",
|
||||
"value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
|
||||
},
|
||||
{
|
||||
"name": "SHELL",
|
||||
"value": "/bin/sh"
|
||||
}
|
||||
],
|
||||
"schedule": [
|
||||
{
|
||||
"minute": [
|
||||
"25"
|
||||
],
|
||||
"hour": [
|
||||
"6"
|
||||
],
|
||||
"day_of_month": [
|
||||
"*"
|
||||
],
|
||||
"month": [
|
||||
"*"
|
||||
],
|
||||
"day_of_week": [
|
||||
"*"
|
||||
],
|
||||
"user": "root",
|
||||
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )"
|
||||
},
|
||||
{
|
||||
"minute": [
|
||||
"47"
|
||||
],
|
||||
"hour": [
|
||||
"6"
|
||||
],
|
||||
"day_of_month": [
|
||||
"*"
|
||||
],
|
||||
"month": [
|
||||
"*"
|
||||
],
|
||||
"day_of_week": [
|
||||
"7"
|
||||
],
|
||||
"user": "root",
|
||||
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )"
|
||||
},
|
||||
{
|
||||
"minute": [
|
||||
"52"
|
||||
],
|
||||
"hour": [
|
||||
"6"
|
||||
],
|
||||
"day_of_month": [
|
||||
"1"
|
||||
],
|
||||
"month": [
|
||||
"*"
|
||||
],
|
||||
"day_of_week": [
|
||||
"*"
|
||||
],
|
||||
"user": "root",
|
||||
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
$ cat /etc/crontab | jc --crontab-u -p -r
|
||||
{
|
||||
"variables": [
|
||||
{
|
||||
"name": "PATH",
|
||||
"value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
|
||||
},
|
||||
{
|
||||
"name": "SHELL",
|
||||
"value": "/bin/sh"
|
||||
}
|
||||
],
|
||||
"schedule": [
|
||||
{
|
||||
"minute": "25",
|
||||
"hour": "6",
|
||||
"day_of_month": "*",
|
||||
"month": "*",
|
||||
"day_of_week": "*",
|
||||
"user": "root",
|
||||
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )"
|
||||
},
|
||||
{
|
||||
"minute": "47",
|
||||
"hour": "6",
|
||||
"day_of_month": "*",
|
||||
"month": "*",
|
||||
"day_of_week": "7",
|
||||
"user": "root",
|
||||
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )"
|
||||
},
|
||||
{
|
||||
"minute": "52",
|
||||
"hour": "6",
|
||||
"day_of_month": "1",
|
||||
"month": "*",
|
||||
"day_of_week": "*",
|
||||
"user": "root",
|
||||
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Structured data with the following schema:
|
||||
|
||||
{
|
||||
"variables": [
|
||||
"name": string,
|
||||
"value": string
|
||||
],
|
||||
"schedule": [
|
||||
{
|
||||
"occurrence" string,
|
||||
"minute": [
|
||||
string
|
||||
],
|
||||
"hour": [
|
||||
string
|
||||
],
|
||||
"day_of_month": [
|
||||
string
|
||||
],
|
||||
"month": [
|
||||
string
|
||||
],
|
||||
"day_of_week": [
|
||||
string
|
||||
],
|
||||
"occurrence": string,
|
||||
"user": string,
|
||||
"command": string
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
## 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:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
105
docs/parsers/csv.md
Normal file
105
docs/parsers/csv.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# jc.parsers.csv
|
||||
jc - JSON CLI output utility csv Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --csv as the first argument if the piped input is coming from a csv file.
|
||||
the csv parser will attempt to automatically detect the delimiter character.
|
||||
if the delimiter cannot be detected it will default to comma.
|
||||
the first row of the file must be a header row.
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat homes.csv
|
||||
"Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres", "Taxes"
|
||||
142, 160, 28, 10, 5, 3, 60, 0.28, 3167
|
||||
175, 180, 18, 8, 4, 1, 12, 0.43, 4033
|
||||
129, 132, 13, 6, 3, 1, 41, 0.33, 1471
|
||||
...
|
||||
|
||||
$ cat homes.csv | jc --csv -p
|
||||
[
|
||||
{
|
||||
"Sell": "142",
|
||||
"List": "160",
|
||||
"Living": "28",
|
||||
"Rooms": "10",
|
||||
"Beds": "5",
|
||||
"Baths": "3",
|
||||
"Age": "60",
|
||||
"Acres": "0.28",
|
||||
"Taxes": "3167"
|
||||
},
|
||||
{
|
||||
"Sell": "175",
|
||||
"List": "180",
|
||||
"Living": "18",
|
||||
"Rooms": "8",
|
||||
"Beds": "4",
|
||||
"Baths": "1",
|
||||
"Age": "12",
|
||||
"Acres": "0.43",
|
||||
"Taxes": "4033"
|
||||
},
|
||||
{
|
||||
"Sell": "129",
|
||||
"List": "132",
|
||||
"Living": "13",
|
||||
"Rooms": "6",
|
||||
"Beds": "3",
|
||||
"Baths": "1",
|
||||
"Age": "41",
|
||||
"Acres": "0.33",
|
||||
"Taxes": "1471"
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Each dictionary represents a row in the csv file:
|
||||
|
||||
[
|
||||
{
|
||||
csv file converted to a Dictionary
|
||||
https://docs.python.org/3/library/csv.html
|
||||
}
|
||||
]
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -7,7 +7,7 @@ Usage:
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
141
docs/parsers/group.md
Normal file
141
docs/parsers/group.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# jc.parsers.group
|
||||
jc - JSON CLI output utility /etc/group file Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --group as the first argument if the piped input is coming from /etc/group
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat /etc/group | jc --group -p
|
||||
[
|
||||
{
|
||||
"group_name": "nobody",
|
||||
"password": "*",
|
||||
"gid": -2,
|
||||
"members": []
|
||||
},
|
||||
{
|
||||
"group_name": "nogroup",
|
||||
"password": "*",
|
||||
"gid": -1,
|
||||
"members": []
|
||||
},
|
||||
{
|
||||
"group_name": "wheel",
|
||||
"password": "*",
|
||||
"gid": 0,
|
||||
"members": [
|
||||
"root"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_name": "certusers",
|
||||
"password": "*",
|
||||
"gid": 29,
|
||||
"members": [
|
||||
"root",
|
||||
"_jabber",
|
||||
"_postfix",
|
||||
"_cyrus",
|
||||
"_calendar",
|
||||
"_dovecot"
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
$ cat /etc/group | jc --group -p -r
|
||||
[
|
||||
{
|
||||
"group_name": "nobody",
|
||||
"password": "*",
|
||||
"gid": "-2",
|
||||
"members": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_name": "nogroup",
|
||||
"password": "*",
|
||||
"gid": "-1",
|
||||
"members": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_name": "wheel",
|
||||
"password": "*",
|
||||
"gid": "0",
|
||||
"members": [
|
||||
"root"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_name": "certusers",
|
||||
"password": "*",
|
||||
"gid": "29",
|
||||
"members": [
|
||||
"root",
|
||||
"_jabber",
|
||||
"_postfix",
|
||||
"_cyrus",
|
||||
"_calendar",
|
||||
"_dovecot"
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"group_name": string,
|
||||
"password": string,
|
||||
"gid": integer,
|
||||
"members": [
|
||||
string
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
## 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.
|
||||
|
||||
109
docs/parsers/gshadow.md
Normal file
109
docs/parsers/gshadow.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# jc.parsers.gshadow
|
||||
jc - JSON CLI output utility /etc/gshadow file Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --gshadow as the first argument if the piped input is coming from /etc/gshadow
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat /etc/gshadow | jc --gshadow -p
|
||||
[
|
||||
{
|
||||
"group_name": "root",
|
||||
"password": "*",
|
||||
"administrators": [],
|
||||
"members": []
|
||||
},
|
||||
{
|
||||
"group_name": "adm",
|
||||
"password": "*",
|
||||
"administrators": [],
|
||||
"members": [
|
||||
"syslog",
|
||||
"joeuser"
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
$ cat /etc/gshadow | jc --gshadow -p -r
|
||||
[
|
||||
{
|
||||
"group_name": "root",
|
||||
"password": "*",
|
||||
"administrators": [
|
||||
""
|
||||
],
|
||||
"members": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_name": "adm",
|
||||
"password": "*",
|
||||
"administrators": [
|
||||
""
|
||||
],
|
||||
"members": [
|
||||
"syslog",
|
||||
"joeuser"
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"group_name": string,
|
||||
"password": string,
|
||||
"administrators": [
|
||||
string
|
||||
],
|
||||
"members": [
|
||||
string
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -7,26 +7,26 @@ Usage:
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
|
||||
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ history | jc --history -p
|
||||
[
|
||||
{
|
||||
"line": "118",
|
||||
"line": 118,
|
||||
"command": "sleep 100"
|
||||
},
|
||||
{
|
||||
"line": "119",
|
||||
"line": 119,
|
||||
"command": "ls /bin"
|
||||
},
|
||||
{
|
||||
"line": "120",
|
||||
"line": 120,
|
||||
"command": "echo "hello""
|
||||
},
|
||||
{
|
||||
"line": "121",
|
||||
"line": 121,
|
||||
"command": "docker images"
|
||||
},
|
||||
...
|
||||
@@ -63,7 +63,7 @@ Returns:
|
||||
|
||||
[
|
||||
{
|
||||
"line": string,
|
||||
"line": integer,
|
||||
"command": string
|
||||
}
|
||||
]
|
||||
|
||||
133
docs/parsers/id.md
Normal file
133
docs/parsers/id.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# jc.parsers.id
|
||||
jc - JSON CLI output utility id Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --id as the first argument if the piped input is coming from id
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ id | jc --id -p
|
||||
{
|
||||
"uid": {
|
||||
"id": 1000,
|
||||
"name": "joeuser"
|
||||
},
|
||||
"gid": {
|
||||
"id": 1000,
|
||||
"name": "joeuser"
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"id": 1000,
|
||||
"name": "joeuser"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "wheel"
|
||||
}
|
||||
],
|
||||
"context": {
|
||||
"user": "unconfined_u",
|
||||
"role": "unconfined_r",
|
||||
"type": "unconfined_t",
|
||||
"level": "s0-s0:c0.c1023"
|
||||
}
|
||||
}
|
||||
|
||||
$ id | jc --id -p -r
|
||||
{
|
||||
"uid": {
|
||||
"id": "1000",
|
||||
"name": "joeuser"
|
||||
},
|
||||
"gid": {
|
||||
"id": "1000",
|
||||
"name": "joeuser"
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"id": "1000",
|
||||
"name": "joeuser"
|
||||
},
|
||||
{
|
||||
"id": "10",
|
||||
"name": "wheel"
|
||||
}
|
||||
],
|
||||
"context": {
|
||||
"user": "unconfined_u",
|
||||
"role": "unconfined_r",
|
||||
"type": "unconfined_t",
|
||||
"level": "s0-s0:c0.c1023"
|
||||
}
|
||||
}
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Structured data with the following schema:
|
||||
|
||||
{
|
||||
"uid": {
|
||||
"id": integer,
|
||||
"name": string
|
||||
},
|
||||
"gid": {
|
||||
"id": integer,
|
||||
"name": string
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"id": integer,
|
||||
"name": string
|
||||
},
|
||||
{
|
||||
"id": integer,
|
||||
"name": string
|
||||
}
|
||||
],
|
||||
"context": {
|
||||
"user": string,
|
||||
"role": string,
|
||||
"type": string,
|
||||
"level": string
|
||||
}
|
||||
}
|
||||
|
||||
## 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.
|
||||
|
||||
87
docs/parsers/ini.md
Normal file
87
docs/parsers/ini.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# jc.parsers.ini
|
||||
jc - JSON CLI output utility INI Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --ini as the first argument if the piped input is coming from an INI file
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat example.ini
|
||||
[DEFAULT]
|
||||
ServerAliveInterval = 45
|
||||
Compression = yes
|
||||
CompressionLevel = 9
|
||||
ForwardX11 = yes
|
||||
|
||||
[bitbucket.org]
|
||||
User = hg
|
||||
|
||||
[topsecret.server.com]
|
||||
Port = 50022
|
||||
ForwardX11 = no
|
||||
|
||||
$ cat example.ini | jc --ini -p
|
||||
{
|
||||
"bitbucket.org": {
|
||||
"serveraliveinterval": "45",
|
||||
"compression": "yes",
|
||||
"compressionlevel": "9",
|
||||
"forwardx11": "yes",
|
||||
"user": "hg"
|
||||
},
|
||||
"topsecret.server.com": {
|
||||
"serveraliveinterval": "45",
|
||||
"compression": "yes",
|
||||
"compressionlevel": "9",
|
||||
"forwardx11": "no",
|
||||
"port": "50022"
|
||||
}
|
||||
}
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary representing an ini document:
|
||||
|
||||
{
|
||||
ini document converted to a dictionary
|
||||
see configparser standard library documentation for more details
|
||||
}
|
||||
|
||||
## 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:
|
||||
|
||||
Dictionary representing the ini file
|
||||
|
||||
118
docs/parsers/last.md
Normal file
118
docs/parsers/last.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# jc.parsers.last
|
||||
jc - JSON CLI output utility last Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --last as the first argument if the piped input is coming from last or lastb
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ last | jc --last -p
|
||||
[
|
||||
{
|
||||
"user": "kbrazil",
|
||||
"tty": "ttys002",
|
||||
"hostname": null,
|
||||
"login": "Thu Feb 27 14:31",
|
||||
"logout": "still logged in"
|
||||
},
|
||||
{
|
||||
"user": "kbrazil",
|
||||
"tty": "ttys003",
|
||||
"hostname": null,
|
||||
"login": "Thu Feb 27 10:38",
|
||||
"logout": "10:38",
|
||||
"duration": "00:00"
|
||||
},
|
||||
{
|
||||
"user": "kbrazil",
|
||||
"tty": "ttys003",
|
||||
"hostname": null,
|
||||
"login": "Thu Feb 27 10:18",
|
||||
"logout": "10:18",
|
||||
"duration": "00:00"
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
$ last | jc --last -p -r
|
||||
[
|
||||
{
|
||||
"user": "kbrazil",
|
||||
"tty": "ttys002",
|
||||
"hostname": "-",
|
||||
"login": "Thu Feb 27 14:31",
|
||||
"logout": "still_logged_in"
|
||||
},
|
||||
{
|
||||
"user": "kbrazil",
|
||||
"tty": "ttys003",
|
||||
"hostname": "-",
|
||||
"login": "Thu Feb 27 10:38",
|
||||
"logout": "10:38",
|
||||
"duration": "00:00"
|
||||
},
|
||||
{
|
||||
"user": "kbrazil",
|
||||
"tty": "ttys003",
|
||||
"hostname": "-",
|
||||
"login": "Thu Feb 27 10:18",
|
||||
"logout": "10:18",
|
||||
"duration": "00:00"
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"user": string,
|
||||
"tty": string,
|
||||
"hostname": string,
|
||||
"login": string,
|
||||
"logout": string,
|
||||
"duration": string
|
||||
}
|
||||
]
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
# jc.parsers.ls
|
||||
jc - JSON CLI output utility ls Parser
|
||||
|
||||
Note: The -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 -l or -b is not used.
|
||||
|
||||
Usage:
|
||||
|
||||
specify --ls as the first argument if the piped input is coming from ls
|
||||
|
||||
ls options supported:
|
||||
- None
|
||||
- la
|
||||
- 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 default view
|
||||
since the parser attempts to convert this field to an integer.
|
||||
|
||||
-lbaR
|
||||
--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 default view
|
||||
since the parser attempts to convert this field to an integer.
|
||||
|
||||
Compatibility:
|
||||
|
||||
@@ -165,6 +170,7 @@ Returns:
|
||||
"filename": string,
|
||||
"flags": string,
|
||||
"links": integer,
|
||||
"parent": string,
|
||||
"owner": string,
|
||||
"group": string,
|
||||
"size": integer,
|
||||
|
||||
126
docs/parsers/passwd.md
Normal file
126
docs/parsers/passwd.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# jc.parsers.passwd
|
||||
jc - JSON CLI output utility /etc/passwd file Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --passwd as the first argument if the piped input is coming from /etc/passwd
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat /etc/passwd | jc --passwd -p
|
||||
[
|
||||
{
|
||||
"username": "nobody",
|
||||
"password": "*",
|
||||
"uid": -2,
|
||||
"gid": -2,
|
||||
"comment": "Unprivileged User",
|
||||
"home": "/var/empty",
|
||||
"shell": "/usr/bin/false"
|
||||
},
|
||||
{
|
||||
"username": "root",
|
||||
"password": "*",
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"comment": "System Administrator",
|
||||
"home": "/var/root",
|
||||
"shell": "/bin/sh"
|
||||
},
|
||||
{
|
||||
"username": "daemon",
|
||||
"password": "*",
|
||||
"uid": 1,
|
||||
"gid": 1,
|
||||
"comment": "System Services",
|
||||
"home": "/var/root",
|
||||
"shell": "/usr/bin/false"
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
$ cat /etc/passwd | jc --passwd -p -r
|
||||
[
|
||||
{
|
||||
"username": "nobody",
|
||||
"password": "*",
|
||||
"uid": "-2",
|
||||
"gid": "-2",
|
||||
"comment": "Unprivileged User",
|
||||
"home": "/var/empty",
|
||||
"shell": "/usr/bin/false"
|
||||
},
|
||||
{
|
||||
"username": "root",
|
||||
"password": "*",
|
||||
"uid": "0",
|
||||
"gid": "0",
|
||||
"comment": "System Administrator",
|
||||
"home": "/var/root",
|
||||
"shell": "/bin/sh"
|
||||
},
|
||||
{
|
||||
"username": "daemon",
|
||||
"password": "*",
|
||||
"uid": "1",
|
||||
"gid": "1",
|
||||
"comment": "System Services",
|
||||
"home": "/var/root",
|
||||
"shell": "/usr/bin/false"
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"username": string,
|
||||
"password": string,
|
||||
"uid": integer,
|
||||
"gid": integer,
|
||||
"comment": string,
|
||||
"home": string,
|
||||
"shell": string
|
||||
}
|
||||
]
|
||||
|
||||
## 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.
|
||||
|
||||
133
docs/parsers/shadow.md
Normal file
133
docs/parsers/shadow.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# jc.parsers.shadow
|
||||
jc - JSON CLI output utility /etc/shadow file Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --shadow as the first argument if the piped input is coming from /etc/shadow
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ sudo cat /etc/shadow | jc --shadow -p
|
||||
[
|
||||
{
|
||||
"username": "root",
|
||||
"password": "*",
|
||||
"last_changed": 18113,
|
||||
"minimum": 0,
|
||||
"maximum": 99999,
|
||||
"warn": 7,
|
||||
"inactive": null,
|
||||
"expire": null
|
||||
},
|
||||
{
|
||||
"username": "daemon",
|
||||
"password": "*",
|
||||
"last_changed": 18113,
|
||||
"minimum": 0,
|
||||
"maximum": 99999,
|
||||
"warn": 7,
|
||||
"inactive": null,
|
||||
"expire": null
|
||||
},
|
||||
{
|
||||
"username": "bin",
|
||||
"password": "*",
|
||||
"last_changed": 18113,
|
||||
"minimum": 0,
|
||||
"maximum": 99999,
|
||||
"warn": 7,
|
||||
"inactive": null,
|
||||
"expire": null
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
$ sudo cat /etc/shadow | jc --shadow -p -r
|
||||
[
|
||||
{
|
||||
"username": "root",
|
||||
"password": "*",
|
||||
"last_changed": "18113",
|
||||
"minimum": "0",
|
||||
"maximum": "99999",
|
||||
"warn": "7",
|
||||
"inactive": "",
|
||||
"expire": ""
|
||||
},
|
||||
{
|
||||
"username": "daemon",
|
||||
"password": "*",
|
||||
"last_changed": "18113",
|
||||
"minimum": "0",
|
||||
"maximum": "99999",
|
||||
"warn": "7",
|
||||
"inactive": "",
|
||||
"expire": ""
|
||||
},
|
||||
{
|
||||
"username": "bin",
|
||||
"password": "*",
|
||||
"last_changed": "18113",
|
||||
"minimum": "0",
|
||||
"maximum": "99999",
|
||||
"warn": "7",
|
||||
"inactive": "",
|
||||
"expire": ""
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"username": string,
|
||||
"password": string,
|
||||
"last_changed": integer,
|
||||
"minimum": integer,
|
||||
"maximum": integer,
|
||||
"warn": integer,
|
||||
"inactive": integer,
|
||||
"expire": integer
|
||||
}
|
||||
]
|
||||
|
||||
## 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.
|
||||
|
||||
152
docs/parsers/who.md
Normal file
152
docs/parsers/who.md
Normal file
@@ -0,0 +1,152 @@
|
||||
# jc.parsers.who
|
||||
jc - JSON CLI output utility who Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --who as the first argument if the piped input is coming from who
|
||||
|
||||
accepts any of the following who options (or no options): -aTH
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ who -a | jc --who -p
|
||||
[
|
||||
{
|
||||
"event": "reboot",
|
||||
"time": "Feb 7 23:31",
|
||||
"pid": 1
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "-",
|
||||
"tty": "console",
|
||||
"time": "Feb 7 23:32",
|
||||
"idle": "old",
|
||||
"pid": 105
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "+",
|
||||
"tty": "ttys000",
|
||||
"time": "Feb 13 16:44",
|
||||
"idle": ".",
|
||||
"pid": 51217,
|
||||
"comment": "term=0 exit=0"
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "?",
|
||||
"tty": "ttys003",
|
||||
"time": "Feb 28 08:59",
|
||||
"idle": "01:36",
|
||||
"pid": 41402
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "+",
|
||||
"tty": "ttys004",
|
||||
"time": "Mar 1 16:35",
|
||||
"idle": ".",
|
||||
"pid": 15679,
|
||||
"from": "192.168.1.5"
|
||||
}
|
||||
]
|
||||
|
||||
$ who -a | jc --who -p -r
|
||||
[
|
||||
{
|
||||
"event": "reboot",
|
||||
"time": "Feb 7 23:31",
|
||||
"pid": "1"
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "-",
|
||||
"tty": "console",
|
||||
"time": "Feb 7 23:32",
|
||||
"idle": "old",
|
||||
"pid": "105"
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "+",
|
||||
"tty": "ttys000",
|
||||
"time": "Feb 13 16:44",
|
||||
"idle": ".",
|
||||
"pid": "51217",
|
||||
"comment": "term=0 exit=0"
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "?",
|
||||
"tty": "ttys003",
|
||||
"time": "Feb 28 08:59",
|
||||
"idle": "01:36",
|
||||
"pid": "41402"
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "+",
|
||||
"tty": "ttys004",
|
||||
"time": "Mar 1 16:35",
|
||||
"idle": ".",
|
||||
"pid": "15679",
|
||||
"from": "192.168.1.5"
|
||||
}
|
||||
]
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"user": string,
|
||||
"event": string,
|
||||
"writeable_tty": string,
|
||||
"tty": string,
|
||||
"time": string,
|
||||
"idle": string,
|
||||
"pid": integer,
|
||||
"from": string,
|
||||
"comment": string
|
||||
}
|
||||
]
|
||||
|
||||
## 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.
|
||||
|
||||
99
docs/parsers/xml.md
Normal file
99
docs/parsers/xml.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# jc.parsers.xml
|
||||
jc - JSON CLI output utility XML Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --xml as the first argument if the piped input is coming from an XML file
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat cd_catalog.xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CATALOG>
|
||||
<CD>
|
||||
<TITLE>Empire Burlesque</TITLE>
|
||||
<ARTIST>Bob Dylan</ARTIST>
|
||||
<COUNTRY>USA</COUNTRY>
|
||||
<COMPANY>Columbia</COMPANY>
|
||||
<PRICE>10.90</PRICE>
|
||||
<YEAR>1985</YEAR>
|
||||
</CD>
|
||||
<CD>
|
||||
<TITLE>Hide your heart</TITLE>
|
||||
<ARTIST>Bonnie Tyler</ARTIST>
|
||||
<COUNTRY>UK</COUNTRY>
|
||||
<COMPANY>CBS Records</COMPANY>
|
||||
<PRICE>9.90</PRICE>
|
||||
<YEAR>1988</YEAR>
|
||||
</CD>
|
||||
...
|
||||
|
||||
$ cat cd_catalog.xml | jc --xml -p
|
||||
{
|
||||
"CATALOG": {
|
||||
"CD": [
|
||||
{
|
||||
"TITLE": "Empire Burlesque",
|
||||
"ARTIST": "Bob Dylan",
|
||||
"COUNTRY": "USA",
|
||||
"COMPANY": "Columbia",
|
||||
"PRICE": "10.90",
|
||||
"YEAR": "1985"
|
||||
},
|
||||
{
|
||||
"TITLE": "Hide your heart",
|
||||
"ARTIST": "Bonnie Tyler",
|
||||
"COUNTRY": "UK",
|
||||
"COMPANY": "CBS Records",
|
||||
"PRICE": "9.90",
|
||||
"YEAR": "1988"
|
||||
},
|
||||
...
|
||||
}
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary representing an XML document:
|
||||
|
||||
{
|
||||
XML Document converted to a Dictionary
|
||||
See https://github.com/martinblech/xmltodict for details
|
||||
}
|
||||
|
||||
## 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:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
113
docs/parsers/yaml.md
Normal file
113
docs/parsers/yaml.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# jc.parsers.yaml
|
||||
jc - JSON CLI output utility YAML Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --yaml as the first argument if the piped input is coming from a YAML file
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat istio-mtls-permissive.yaml
|
||||
apiVersion: "authentication.istio.io/v1alpha1"
|
||||
kind: "Policy"
|
||||
metadata:
|
||||
name: "default"
|
||||
namespace: "default"
|
||||
spec:
|
||||
peers:
|
||||
- mtls: {}
|
||||
---
|
||||
apiVersion: "networking.istio.io/v1alpha3"
|
||||
kind: "DestinationRule"
|
||||
metadata:
|
||||
name: "default"
|
||||
namespace: "default"
|
||||
spec:
|
||||
host: "*.default.svc.cluster.local"
|
||||
trafficPolicy:
|
||||
tls:
|
||||
mode: ISTIO_MUTUAL
|
||||
|
||||
$ cat istio-mtls-permissive.yaml | jc --yaml -p
|
||||
[
|
||||
{
|
||||
"apiVersion": "authentication.istio.io/v1alpha1",
|
||||
"kind": "Policy",
|
||||
"metadata": {
|
||||
"name": "default",
|
||||
"namespace": "default"
|
||||
},
|
||||
"spec": {
|
||||
"peers": [
|
||||
{
|
||||
"mtls": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "networking.istio.io/v1alpha3",
|
||||
"kind": "DestinationRule",
|
||||
"metadata": {
|
||||
"name": "default",
|
||||
"namespace": "default"
|
||||
},
|
||||
"spec": {
|
||||
"host": "*.default.svc.cluster.local",
|
||||
"trafficPolicy": {
|
||||
"tls": {
|
||||
"mode": "ISTIO_MUTUAL"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
## info
|
||||
```python
|
||||
info(self, /, *args, **kwargs)
|
||||
```
|
||||
|
||||
## process
|
||||
```python
|
||||
process(proc_data)
|
||||
```
|
||||
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Each dictionary represents a YAML document:
|
||||
|
||||
[
|
||||
{
|
||||
YAML Document converted to a Dictionary
|
||||
See https://pypi.org/project/ruamel.yaml for details
|
||||
}
|
||||
]
|
||||
|
||||
## 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.
|
||||
|
||||
311
jc/cli.py
311
jc/cli.py
@@ -3,113 +3,134 @@
|
||||
JC cli module
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import shlex
|
||||
import importlib
|
||||
import textwrap
|
||||
import signal
|
||||
import json
|
||||
import jc.utils
|
||||
import jc.parsers.arp
|
||||
import jc.parsers.crontab
|
||||
import jc.parsers.df
|
||||
import jc.parsers.dig
|
||||
import jc.parsers.du
|
||||
import jc.parsers.env
|
||||
import jc.parsers.free
|
||||
import jc.parsers.fstab
|
||||
import jc.parsers.history
|
||||
import jc.parsers.hosts
|
||||
import jc.parsers.ifconfig
|
||||
import jc.parsers.iptables
|
||||
import jc.parsers.jobs
|
||||
import jc.parsers.ls
|
||||
import jc.parsers.lsblk
|
||||
import jc.parsers.lsmod
|
||||
import jc.parsers.lsof
|
||||
import jc.parsers.mount
|
||||
import jc.parsers.netstat
|
||||
import jc.parsers.pip_list
|
||||
import jc.parsers.pip_show
|
||||
import jc.parsers.ps
|
||||
import jc.parsers.route
|
||||
import jc.parsers.ss
|
||||
import jc.parsers.stat
|
||||
import jc.parsers.systemctl
|
||||
import jc.parsers.systemctl_lj
|
||||
import jc.parsers.systemctl_ls
|
||||
import jc.parsers.systemctl_luf
|
||||
import jc.parsers.uname
|
||||
import jc.parsers.uptime
|
||||
import jc.parsers.w
|
||||
|
||||
parser_map = {
|
||||
'--arp': jc.parsers.arp,
|
||||
'--crontab': jc.parsers.crontab,
|
||||
'--df': jc.parsers.df,
|
||||
'--dig': jc.parsers.dig,
|
||||
'--du': jc.parsers.du,
|
||||
'--env': jc.parsers.env,
|
||||
'--free': jc.parsers.free,
|
||||
'--fstab': jc.parsers.fstab,
|
||||
'--history': jc.parsers.history,
|
||||
'--hosts': jc.parsers.hosts,
|
||||
'--ifconfig': jc.parsers.ifconfig,
|
||||
'--iptables': jc.parsers.iptables,
|
||||
'--jobs': jc.parsers.jobs,
|
||||
'--ls': jc.parsers.ls,
|
||||
'--lsblk': jc.parsers.lsblk,
|
||||
'--lsmod': jc.parsers.lsmod,
|
||||
'--lsof': jc.parsers.lsof,
|
||||
'--mount': jc.parsers.mount,
|
||||
'--netstat': jc.parsers.netstat,
|
||||
'--pip-list': jc.parsers.pip_list,
|
||||
'--pip-show': jc.parsers.pip_show,
|
||||
'--ps': jc.parsers.ps,
|
||||
'--route': jc.parsers.route,
|
||||
'--ss': jc.parsers.ss,
|
||||
'--stat': jc.parsers.stat,
|
||||
'--systemctl': jc.parsers.systemctl,
|
||||
'--systemctl-lj': jc.parsers.systemctl_lj,
|
||||
'--systemctl-ls': jc.parsers.systemctl_ls,
|
||||
'--systemctl-luf': jc.parsers.systemctl_luf,
|
||||
'--uname': jc.parsers.uname,
|
||||
'--uptime': jc.parsers.uptime,
|
||||
'--w': jc.parsers.w
|
||||
}
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.6.1'
|
||||
version = '1.8.0'
|
||||
description = 'jc cli output JSON conversion tool'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
parsers = [
|
||||
'arp',
|
||||
'blkid',
|
||||
'crontab',
|
||||
'crontab-u',
|
||||
'csv',
|
||||
'df',
|
||||
'dig',
|
||||
'du',
|
||||
'env',
|
||||
'free',
|
||||
'fstab',
|
||||
'group',
|
||||
'gshadow',
|
||||
'history',
|
||||
'hosts',
|
||||
'id',
|
||||
'ifconfig',
|
||||
'ini',
|
||||
'iptables',
|
||||
'jobs',
|
||||
'last',
|
||||
'ls',
|
||||
'lsblk',
|
||||
'lsmod',
|
||||
'lsof',
|
||||
'mount',
|
||||
'netstat',
|
||||
'passwd',
|
||||
'pip-list',
|
||||
'pip-show',
|
||||
'ps',
|
||||
'route',
|
||||
'shadow',
|
||||
'ss',
|
||||
'stat',
|
||||
'systemctl',
|
||||
'systemctl-lj',
|
||||
'systemctl-ls',
|
||||
'systemctl-luf',
|
||||
'uname',
|
||||
'uptime',
|
||||
'w',
|
||||
'who',
|
||||
'xml',
|
||||
'yaml'
|
||||
]
|
||||
|
||||
|
||||
def ctrlc(signum, frame):
|
||||
exit()
|
||||
"""exit with error on SIGINT"""
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def parsers_text():
|
||||
def parser_shortname(parser_argument):
|
||||
"""short name of the parser with dashes and no -- prefix"""
|
||||
return parser_argument[2:]
|
||||
|
||||
|
||||
def parser_argument(parser):
|
||||
"""short name of the parser with dashes and with -- prefix"""
|
||||
return f'--{parser}'
|
||||
|
||||
|
||||
def parser_mod_shortname(parser):
|
||||
"""short name of the parser's module name (no -- prefix and dashes converted to underscores)"""
|
||||
return parser.replace('--', '').replace('-', '_')
|
||||
|
||||
|
||||
def parser_module(parser):
|
||||
"""import the module just in time and return the module object"""
|
||||
importlib.import_module('jc.parsers.' + parser_mod_shortname(parser))
|
||||
return getattr(jc.parsers, parser_mod_shortname(parser))
|
||||
|
||||
|
||||
def parsers_text(indent=0, pad=0):
|
||||
"""return the argument and description information from each parser"""
|
||||
ptext = ''
|
||||
for parser in parser_map:
|
||||
if hasattr(parser_map[parser], 'info'):
|
||||
padding = 16 - len(parser)
|
||||
for parser in parsers:
|
||||
parser_arg = parser_argument(parser)
|
||||
parser_mod = parser_module(parser)
|
||||
|
||||
if hasattr(parser_mod, 'info'):
|
||||
parser_desc = parser_mod.info.description
|
||||
padding = pad - len(parser_arg)
|
||||
padding_char = ' '
|
||||
indent_text = padding_char * indent
|
||||
padding_text = padding_char * padding
|
||||
ptext += ' ' + parser + padding_text + parser_map[parser].info.description + '\n'
|
||||
ptext += indent_text + parser_arg + padding_text + parser_desc + '\n'
|
||||
|
||||
return ptext
|
||||
|
||||
|
||||
def about_jc():
|
||||
"""return jc info and the contents of each parser.info as a dictionary"""
|
||||
parser_list = []
|
||||
for parser in parser_map:
|
||||
if hasattr(parser_map[parser], 'info'):
|
||||
|
||||
for parser in parsers:
|
||||
parser_mod = parser_module(parser)
|
||||
|
||||
if hasattr(parser_mod, 'info'):
|
||||
info_dict = {}
|
||||
info_dict['name'] = parser_map[parser].__name__.split('.')[-1]
|
||||
info_dict['argument'] = parser
|
||||
parser_entry = vars(parser_map[parser].info)
|
||||
info_dict['name'] = parser_mod.__name__.split('.')[-1]
|
||||
info_dict['argument'] = parser_argument(parser)
|
||||
parser_entry = vars(parser_mod.info)
|
||||
|
||||
for k, v in parser_entry.items():
|
||||
if not k.startswith('__'):
|
||||
info_dict[k] = v
|
||||
|
||||
parser_list.append(info_dict)
|
||||
|
||||
return {
|
||||
@@ -124,24 +145,33 @@ def about_jc():
|
||||
|
||||
|
||||
def helptext(message):
|
||||
parsers_string = parsers_text()
|
||||
"""return the help text with the list of parsers"""
|
||||
parsers_string = parsers_text(indent=12, pad=17)
|
||||
|
||||
helptext_string = f'''
|
||||
jc: {message}
|
||||
|
||||
Usage: jc PARSER [OPTIONS]
|
||||
Usage: COMMAND | jc PARSER [OPTIONS]
|
||||
|
||||
or magic syntax:
|
||||
|
||||
jc [OPTIONS] COMMAND
|
||||
|
||||
Parsers:
|
||||
{parsers_string}
|
||||
Options:
|
||||
-a about jc
|
||||
-d debug - show trace messages
|
||||
-p pretty print output
|
||||
-q quiet - suppress warnings
|
||||
-r raw JSON output
|
||||
-a about jc
|
||||
-d debug - show trace messages
|
||||
-p pretty print output
|
||||
-q quiet - suppress warnings
|
||||
-r raw JSON output
|
||||
|
||||
Example:
|
||||
ls -al | jc --ls -p
|
||||
|
||||
or using the magic syntax:
|
||||
|
||||
jc -p ls -al
|
||||
'''
|
||||
print(textwrap.dedent(helptext_string), file=sys.stderr)
|
||||
|
||||
@@ -153,34 +183,108 @@ def json_out(data, pretty=False):
|
||||
print(json.dumps(data))
|
||||
|
||||
|
||||
def magic():
|
||||
"""Parse with magic syntax: jc -p ls -al"""
|
||||
if len(sys.argv) > 1 and not sys.argv[1].startswith('--'):
|
||||
parser_info = about_jc()['parsers']
|
||||
# correctly parse escape characters and spaces with shlex
|
||||
args_given = " ".join(map(shlex.quote, sys.argv[1:])).split()
|
||||
options = []
|
||||
found_parser = None
|
||||
|
||||
# find the options
|
||||
if args_given[0].startswith('-'):
|
||||
p = 0
|
||||
for i, arg in list(enumerate(args_given)):
|
||||
# parser found - use standard syntax
|
||||
if arg.startswith('--'):
|
||||
return
|
||||
# option found - populate option list
|
||||
elif arg.startswith('-'):
|
||||
options.append(args_given.pop(i - p)[1:])
|
||||
p = p + 1
|
||||
# command found if iterator didn't already stop - stop iterating
|
||||
else:
|
||||
break
|
||||
|
||||
# find the command and parser
|
||||
for parser in parser_info:
|
||||
if 'magic_commands' in parser:
|
||||
# first pass for two word commands: e.g. 'pip list'
|
||||
for magic_command in parser['magic_commands']:
|
||||
try:
|
||||
if ' '.join(args_given[0:2]) == magic_command:
|
||||
found_parser = parser['argument']
|
||||
break
|
||||
# No command found - go to next loop (for cases like 'jc -a')
|
||||
except Exception:
|
||||
break
|
||||
|
||||
# second pass for one word commands: e.g. 'ls'
|
||||
if not found_parser:
|
||||
for magic_command in parser['magic_commands']:
|
||||
try:
|
||||
if args_given[0] == magic_command:
|
||||
found_parser = parser['argument']
|
||||
break
|
||||
# No command found - use standard syntax (for cases like 'jc -a')
|
||||
except Exception:
|
||||
return
|
||||
|
||||
# construct a new command line using the standard syntax: COMMAND | jc --PARSER -OPTIONS
|
||||
run_command = ' '.join(args_given)
|
||||
if found_parser:
|
||||
if options:
|
||||
cmd_options = '-' + ''.join(options)
|
||||
else:
|
||||
cmd_options = ''
|
||||
whole_command = ' '.join([run_command, '|', 'jc', found_parser, cmd_options])
|
||||
|
||||
os.system(whole_command)
|
||||
exit()
|
||||
else:
|
||||
helptext(f'parser not found for "{run_command}"')
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
# break on ctrl-c keyboard interrupt
|
||||
signal.signal(signal.SIGINT, ctrlc)
|
||||
|
||||
# try magic syntax first: e.g. jc -p ls -al
|
||||
magic()
|
||||
|
||||
options = []
|
||||
debug = False
|
||||
pretty = False
|
||||
quiet = False
|
||||
raw = False
|
||||
|
||||
# options
|
||||
if '-d' in sys.argv:
|
||||
for opt in sys.argv:
|
||||
if opt.startswith('-') and not opt.startswith('--'):
|
||||
for flag in opt[1:]:
|
||||
options.append(flag)
|
||||
|
||||
if 'd' in options:
|
||||
debug = True
|
||||
|
||||
if '-p' in sys.argv:
|
||||
if 'p' in options:
|
||||
pretty = True
|
||||
|
||||
if '-q' in sys.argv:
|
||||
if 'q' in options:
|
||||
quiet = True
|
||||
|
||||
if '-r' in sys.argv:
|
||||
if 'r' in options:
|
||||
raw = True
|
||||
|
||||
if '-a' in sys.argv:
|
||||
if 'a' in options:
|
||||
json_out(about_jc(), pretty=pretty)
|
||||
exit()
|
||||
|
||||
if sys.stdin.isatty():
|
||||
helptext('missing piped data')
|
||||
exit()
|
||||
sys.exit(1)
|
||||
|
||||
data = sys.stdin.read()
|
||||
|
||||
@@ -188,25 +292,32 @@ def main():
|
||||
|
||||
if debug:
|
||||
for arg in sys.argv:
|
||||
if arg in parser_map:
|
||||
result = parser_map[arg].parse(data, raw=raw, quiet=quiet)
|
||||
parser_name = parser_shortname(arg)
|
||||
|
||||
if parser_name in parsers:
|
||||
# load parser module just in time so we don't need to load all modules
|
||||
parser = parser_module(arg)
|
||||
result = parser.parse(data, raw=raw, quiet=quiet)
|
||||
found = True
|
||||
break
|
||||
else:
|
||||
for arg in sys.argv:
|
||||
if arg in parser_map:
|
||||
parser_name = parser_shortname(arg)
|
||||
|
||||
if parser_name in parsers:
|
||||
# load parser module just in time so we don't need to load all modules
|
||||
parser = parser_module(arg)
|
||||
try:
|
||||
result = parser_map[arg].parse(data, raw=raw, quiet=quiet)
|
||||
result = parser.parse(data, raw=raw, quiet=quiet)
|
||||
found = True
|
||||
break
|
||||
except:
|
||||
parser_name = parser_map[arg].__name__.split('.')[-1]
|
||||
except Exception:
|
||||
jc.utils.error_message(f'{parser_name} parser could not parse the input data. Did you use the correct parser?\n For details use the -d option.')
|
||||
exit(1)
|
||||
sys.exit(1)
|
||||
|
||||
if not found:
|
||||
helptext('missing or incorrect arguments')
|
||||
exit()
|
||||
sys.exit(1)
|
||||
|
||||
json_out(result, pretty=pretty)
|
||||
|
||||
|
||||
@@ -92,12 +92,16 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
version = '1.1'
|
||||
description = 'arp parser'
|
||||
description = 'arp command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'aix', 'freebsd', 'darwin']
|
||||
magic_commands = ['arp']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
219
jc/parsers/blkid.py
Normal file
219
jc/parsers/blkid.py
Normal file
@@ -0,0 +1,219 @@
|
||||
"""jc - JSON CLI output utility blkid Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --blkid as the first argument if the piped input is coming from blkid
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux'
|
||||
|
||||
Examples:
|
||||
|
||||
$ blkid | jc --blkid -p
|
||||
[
|
||||
{
|
||||
"device": "/dev/sda1",
|
||||
"uuid": "05d927ab-5875-49e4-ada1-7f46cb32c932",
|
||||
"type": "xfs"
|
||||
},
|
||||
{
|
||||
"device": "/dev/sda2",
|
||||
"uuid": "3klkIj-w1kk-DkJi-0XBJ-y3i7-i2Ac-vHqWBM",
|
||||
"type": "LVM2_member"
|
||||
},
|
||||
{
|
||||
"device": "/dev/mapper/centos-root",
|
||||
"uuid": "07d718ff-950c-4e5b-98f0-42a1147c77d9",
|
||||
"type": "xfs"
|
||||
},
|
||||
{
|
||||
"device": "/dev/mapper/centos-swap",
|
||||
"uuid": "615eb89a-bcbf-46fd-80e3-c483ff5c931f",
|
||||
"type": "swap"
|
||||
}
|
||||
]
|
||||
|
||||
$ sudo blkid -o udev -ip /dev/sda2 | jc --blkid -p
|
||||
[
|
||||
{
|
||||
"id_fs_uuid": "3klkIj-w1kk-DkJi-0XBJ-y3i7-i2Ac-vHqWBM",
|
||||
"id_fs_uuid_enc": "3klkIj-w1kk-DkJi-0XBJ-y3i7-i2Ac-vHqWBM",
|
||||
"id_fs_version": "LVM2\\x20001",
|
||||
"id_fs_type": "LVM2_member",
|
||||
"id_fs_usage": "raid",
|
||||
"id_iolimit_minimum_io_size": 512,
|
||||
"id_iolimit_physical_sector_size": 512,
|
||||
"id_iolimit_logical_sector_size": 512,
|
||||
"id_part_entry_scheme": "dos",
|
||||
"id_part_entry_type": "0x8e",
|
||||
"id_part_entry_number": 2,
|
||||
"id_part_entry_offset": 2099200,
|
||||
"id_part_entry_size": 39843840,
|
||||
"id_part_entry_disk": "8:0"
|
||||
}
|
||||
]
|
||||
|
||||
$ sudo blkid -ip /dev/sda1 | jc --blkid -p -r
|
||||
[
|
||||
{
|
||||
"devname": "/dev/sda1",
|
||||
"uuid": "05d927bb-5875-49e3-ada1-7f46cb31c932",
|
||||
"type": "xfs",
|
||||
"usage": "filesystem",
|
||||
"minimum_io_size": "512",
|
||||
"physical_sector_size": "512",
|
||||
"logical_sector_size": "512",
|
||||
"part_entry_scheme": "dos",
|
||||
"part_entry_type": "0x83",
|
||||
"part_entry_flags": "0x80",
|
||||
"part_entry_number": "1",
|
||||
"part_entry_offset": "2048",
|
||||
"part_entry_size": "2097152",
|
||||
"part_entry_disk": "8:0"
|
||||
}
|
||||
]
|
||||
"""
|
||||
import shlex
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'blkid command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['blkid']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"device": string,
|
||||
"uuid": string,
|
||||
"type": string,
|
||||
"usage": string,
|
||||
"part_entry_scheme": string,
|
||||
"part_entry_type": string,
|
||||
"part_entry_flags": string,
|
||||
"part_entry_number": integer,
|
||||
"part_entry_offset": integer,
|
||||
"part_entry_size": integer,
|
||||
"part_entry_disk": string,
|
||||
"id_fs_uuid": string,
|
||||
"id_fs_uuid_enc": string,
|
||||
"id_fs_version": string,
|
||||
"id_fs_type": string,
|
||||
"id_fs_usage": string,
|
||||
"id_part_entry_scheme": string,
|
||||
"id_part_entry_type": string,
|
||||
"id_part_entry_flags": string,
|
||||
"id_part_entry_number": integer,
|
||||
"id_part_entry_offset": integer,
|
||||
"id_part_entry_size": integer,
|
||||
"id_iolimit_minimum_io_size": integer,
|
||||
"id_iolimit_physical_sector_size": integer,
|
||||
"id_iolimit_logical_sector_size": integer,
|
||||
"id_part_entry_disk": string,
|
||||
"minimum_io_size": integer,
|
||||
"physical_sector_size": integer,
|
||||
"logical_sector_size": integer
|
||||
}
|
||||
]
|
||||
"""
|
||||
for entry in proc_data:
|
||||
if 'devname' in entry:
|
||||
entry['device'] = entry.pop('devname')
|
||||
|
||||
int_list = ['part_entry_number', 'part_entry_offset', 'part_entry_size', 'id_part_entry_number',
|
||||
'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:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
|
||||
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)
|
||||
|
||||
raw_output = []
|
||||
|
||||
if data:
|
||||
# if the first field is a device, use normal parsing:
|
||||
if data.split(maxsplit=1)[0][-1] == ':':
|
||||
linedata = data.splitlines()
|
||||
|
||||
for line in linedata:
|
||||
output_line = {}
|
||||
entries = shlex.split(line)
|
||||
output_line['device'] = entries.pop(0)[:-1]
|
||||
|
||||
for entry in entries:
|
||||
key = entry.split('=', maxsplit=1)[0].lower()
|
||||
value = entry.split('=', maxsplit=1)[1]
|
||||
output_line[key] = value
|
||||
|
||||
raw_output.append(output_line)
|
||||
|
||||
# else use key/value per line parsing
|
||||
else:
|
||||
linedata = data.splitlines()
|
||||
output_line = {}
|
||||
for line in linedata:
|
||||
if line == '':
|
||||
if output_line:
|
||||
raw_output.append(output_line)
|
||||
output_line = {}
|
||||
continue
|
||||
continue
|
||||
|
||||
key = line.split('=', maxsplit=1)[0].lower()
|
||||
value = line.split('=', maxsplit=1)[1]
|
||||
output_line[key] = value
|
||||
|
||||
if output_line:
|
||||
raw_output.append(output_line)
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
@@ -1,8 +1,8 @@
|
||||
"""jc - JSON CLI output utility crontab file Parser
|
||||
"""jc - JSON CLI output utility crontab command and file Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --crontab as the first argument if the piped input is coming from a crontab file
|
||||
specify --crontab as the first argument if the piped input is coming from crontab -l or a crontab file
|
||||
|
||||
Compatibility:
|
||||
|
||||
@@ -10,7 +10,7 @@ Compatibility:
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat /etc/crontab | jc --crontab -p
|
||||
$ crontab -l | jc --crontab -p
|
||||
{
|
||||
"variables": [
|
||||
{
|
||||
@@ -132,14 +132,18 @@ import jc.parsers.universal
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'crontab file parser'
|
||||
version = '1.1'
|
||||
description = 'crontab command and file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'aix', 'freebsd']
|
||||
magic_commands = ['crontab']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
@@ -156,8 +160,8 @@ def process(proc_data):
|
||||
|
||||
{
|
||||
"variables": [
|
||||
"name": string,
|
||||
"value": string
|
||||
"name": string,
|
||||
"value": string
|
||||
],
|
||||
"schedule": [
|
||||
{
|
||||
@@ -249,12 +253,12 @@ def parse(data, raw=False, quiet=False):
|
||||
'command': cmd})
|
||||
|
||||
# Add header row for parsing
|
||||
cleandata[0] = 'minute hour day_of_month month day_of_week command'
|
||||
cleandata[:0] = ['minute hour day_of_month month day_of_week command']
|
||||
|
||||
if len(cleandata) > 1:
|
||||
cron_list = jc.parsers.universal.simple_table_parse(cleandata)
|
||||
|
||||
raw_output['schedule'] = cron_list
|
||||
raw_output['schedule'] = cron_list
|
||||
|
||||
# Add shortcut entries back in
|
||||
for item in shortcut_list:
|
||||
|
||||
273
jc/parsers/crontab_u.py
Normal file
273
jc/parsers/crontab_u.py
Normal file
@@ -0,0 +1,273 @@
|
||||
"""jc - JSON CLI output utility crontab file Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --crontab-u as the first argument if the piped input is coming from a crontab file with User specified
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat /etc/crontab | jc --crontab-u -p
|
||||
{
|
||||
"variables": [
|
||||
{
|
||||
"name": "PATH",
|
||||
"value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
|
||||
},
|
||||
{
|
||||
"name": "SHELL",
|
||||
"value": "/bin/sh"
|
||||
}
|
||||
],
|
||||
"schedule": [
|
||||
{
|
||||
"minute": [
|
||||
"25"
|
||||
],
|
||||
"hour": [
|
||||
"6"
|
||||
],
|
||||
"day_of_month": [
|
||||
"*"
|
||||
],
|
||||
"month": [
|
||||
"*"
|
||||
],
|
||||
"day_of_week": [
|
||||
"*"
|
||||
],
|
||||
"user": "root",
|
||||
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )"
|
||||
},
|
||||
{
|
||||
"minute": [
|
||||
"47"
|
||||
],
|
||||
"hour": [
|
||||
"6"
|
||||
],
|
||||
"day_of_month": [
|
||||
"*"
|
||||
],
|
||||
"month": [
|
||||
"*"
|
||||
],
|
||||
"day_of_week": [
|
||||
"7"
|
||||
],
|
||||
"user": "root",
|
||||
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )"
|
||||
},
|
||||
{
|
||||
"minute": [
|
||||
"52"
|
||||
],
|
||||
"hour": [
|
||||
"6"
|
||||
],
|
||||
"day_of_month": [
|
||||
"1"
|
||||
],
|
||||
"month": [
|
||||
"*"
|
||||
],
|
||||
"day_of_week": [
|
||||
"*"
|
||||
],
|
||||
"user": "root",
|
||||
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
$ cat /etc/crontab | jc --crontab-u -p -r
|
||||
{
|
||||
"variables": [
|
||||
{
|
||||
"name": "PATH",
|
||||
"value": "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
|
||||
},
|
||||
{
|
||||
"name": "SHELL",
|
||||
"value": "/bin/sh"
|
||||
}
|
||||
],
|
||||
"schedule": [
|
||||
{
|
||||
"minute": "25",
|
||||
"hour": "6",
|
||||
"day_of_month": "*",
|
||||
"month": "*",
|
||||
"day_of_week": "*",
|
||||
"user": "root",
|
||||
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )"
|
||||
},
|
||||
{
|
||||
"minute": "47",
|
||||
"hour": "6",
|
||||
"day_of_month": "*",
|
||||
"month": "*",
|
||||
"day_of_week": "7",
|
||||
"user": "root",
|
||||
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )"
|
||||
},
|
||||
{
|
||||
"minute": "52",
|
||||
"hour": "6",
|
||||
"day_of_month": "1",
|
||||
"month": "*",
|
||||
"day_of_week": "*",
|
||||
"user": "root",
|
||||
"command": "test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
"""
|
||||
import jc.utils
|
||||
import jc.parsers.universal
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'crontab file parser with user support'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'aix', 'freebsd']
|
||||
|
||||
|
||||
__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. Structured data with the following schema:
|
||||
|
||||
{
|
||||
"variables": [
|
||||
"name": string,
|
||||
"value": string
|
||||
],
|
||||
"schedule": [
|
||||
{
|
||||
"occurrence" string,
|
||||
"minute": [
|
||||
string
|
||||
],
|
||||
"hour": [
|
||||
string
|
||||
],
|
||||
"day_of_month": [
|
||||
string
|
||||
],
|
||||
"month": [
|
||||
string
|
||||
],
|
||||
"day_of_week": [
|
||||
string
|
||||
],
|
||||
"occurrence": string,
|
||||
"user": string,
|
||||
"command": string
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
"""
|
||||
# put itmes in lists
|
||||
try:
|
||||
for entry in proc_data['schedule']:
|
||||
entry['minute'] = entry['minute'].split(',')
|
||||
entry['hour'] = entry['hour'].split(',')
|
||||
entry['day_of_month'] = entry['day_of_month'].split(',')
|
||||
entry['month'] = entry['month'].split(',')
|
||||
entry['day_of_week'] = entry['day_of_week'].split(',')
|
||||
except (KeyError):
|
||||
pass
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
def parse(data, raw=False, quiet=False):
|
||||
"""
|
||||
Main text parsing function
|
||||
|
||||
Parameters:
|
||||
|
||||
data: (string) text data to parse
|
||||
raw: (boolean) output preprocessed JSON if True
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
"""
|
||||
if not quiet:
|
||||
jc.utils.compatibility(__name__, info.compatible)
|
||||
|
||||
raw_output = {}
|
||||
cleandata = data.splitlines()
|
||||
|
||||
# Clear any blank lines
|
||||
cleandata = list(filter(None, cleandata))
|
||||
|
||||
# Clear any commented lines
|
||||
for i, line in reversed(list(enumerate(cleandata))):
|
||||
if line.strip().find('#') == 0:
|
||||
cleandata.pop(i)
|
||||
|
||||
# Pop any variable assignment lines
|
||||
cron_var = []
|
||||
for i, line in reversed(list(enumerate(cleandata))):
|
||||
if line.find('=') != -1:
|
||||
var_line = cleandata.pop(i)
|
||||
var_name = var_line.split('=', maxsplit=1)[0].strip()
|
||||
var_value = var_line.split('=', maxsplit=1)[1].strip()
|
||||
cron_var.append({'name': var_name,
|
||||
'value': var_value})
|
||||
|
||||
raw_output['variables'] = cron_var
|
||||
|
||||
# Pop any shortcut lines
|
||||
shortcut_list = []
|
||||
for i, line in reversed(list(enumerate(cleandata))):
|
||||
if line.strip().startswith('@'):
|
||||
shortcut_line = cleandata.pop(i)
|
||||
occurrence = shortcut_line.split(maxsplit=1)[0].strip().lstrip('@')
|
||||
usr = shortcut_line.split(maxsplit=2)[1].strip()
|
||||
cmd = shortcut_line.split(maxsplit=2)[2].strip()
|
||||
shortcut_list.append({'occurrence': occurrence,
|
||||
'user': usr,
|
||||
'command': cmd})
|
||||
|
||||
# Add header row for parsing
|
||||
cleandata[:0] = ['minute hour day_of_month month day_of_week user command']
|
||||
|
||||
if len(cleandata) > 1:
|
||||
cron_list = jc.parsers.universal.simple_table_parse(cleandata)
|
||||
|
||||
raw_output['schedule'] = cron_list
|
||||
|
||||
# Add shortcut entries back in
|
||||
for item in shortcut_list:
|
||||
raw_output['schedule'].append(item)
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
141
jc/parsers/csv.py
Normal file
141
jc/parsers/csv.py
Normal file
@@ -0,0 +1,141 @@
|
||||
"""jc - JSON CLI output utility csv Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --csv as the first argument if the piped input is coming from a csv file.
|
||||
the csv parser will attempt to automatically detect the delimiter character.
|
||||
if the delimiter cannot be detected it will default to comma.
|
||||
the first row of the file must be a header row.
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat homes.csv
|
||||
"Sell", "List", "Living", "Rooms", "Beds", "Baths", "Age", "Acres", "Taxes"
|
||||
142, 160, 28, 10, 5, 3, 60, 0.28, 3167
|
||||
175, 180, 18, 8, 4, 1, 12, 0.43, 4033
|
||||
129, 132, 13, 6, 3, 1, 41, 0.33, 1471
|
||||
...
|
||||
|
||||
$ cat homes.csv | jc --csv -p
|
||||
[
|
||||
{
|
||||
"Sell": "142",
|
||||
"List": "160",
|
||||
"Living": "28",
|
||||
"Rooms": "10",
|
||||
"Beds": "5",
|
||||
"Baths": "3",
|
||||
"Age": "60",
|
||||
"Acres": "0.28",
|
||||
"Taxes": "3167"
|
||||
},
|
||||
{
|
||||
"Sell": "175",
|
||||
"List": "180",
|
||||
"Living": "18",
|
||||
"Rooms": "8",
|
||||
"Beds": "4",
|
||||
"Baths": "1",
|
||||
"Age": "12",
|
||||
"Acres": "0.43",
|
||||
"Taxes": "4033"
|
||||
},
|
||||
{
|
||||
"Sell": "129",
|
||||
"List": "132",
|
||||
"Living": "13",
|
||||
"Rooms": "6",
|
||||
"Beds": "3",
|
||||
"Baths": "1",
|
||||
"Age": "41",
|
||||
"Acres": "0.33",
|
||||
"Taxes": "1471"
|
||||
},
|
||||
...
|
||||
]
|
||||
"""
|
||||
import jc.utils
|
||||
import csv
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'CSV file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
details = 'Using the python standard csv library'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Each dictionary represents a row in the csv file:
|
||||
|
||||
[
|
||||
{
|
||||
csv file converted to a Dictionary
|
||||
https://docs.python.org/3/library/csv.html
|
||||
}
|
||||
]
|
||||
"""
|
||||
|
||||
# No further processing
|
||||
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)
|
||||
|
||||
raw_output = []
|
||||
cleandata = data.splitlines()
|
||||
|
||||
# Clear any blank lines
|
||||
cleandata = list(filter(None, cleandata))
|
||||
|
||||
if cleandata:
|
||||
dialect = None
|
||||
try:
|
||||
dialect = csv.Sniffer().sniff(data[:1024])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
reader = csv.DictReader(cleandata, dialect=dialect)
|
||||
|
||||
for row in reader:
|
||||
raw_output.append(row)
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
@@ -74,12 +74,16 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
version = '1.1'
|
||||
description = 'df parser'
|
||||
description = 'df command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin']
|
||||
magic_commands = ['df']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -325,12 +325,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'dig parser'
|
||||
description = 'dig command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'aix', 'freebsd', 'darwin']
|
||||
magic_commands = ['dig']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -6,7 +6,7 @@ Usage:
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -73,14 +73,18 @@ import jc.parsers.universal
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'du parser'
|
||||
version = '1.1'
|
||||
description = 'du command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
compatible = ['linux', 'darwin', 'aix', 'freebsd']
|
||||
magic_commands = ['du']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -53,12 +53,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.1'
|
||||
description = 'env parser'
|
||||
description = 'env command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
magic_commands = ['env']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -21,13 +21,17 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'foo parser'
|
||||
description = 'foo command parser'
|
||||
author = 'John Doe'
|
||||
author_email = 'johndoe@gmail.com'
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
magic_commands = ['foo']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -54,12 +54,16 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'free parser'
|
||||
description = 'free command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['free']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -71,7 +71,7 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = '/etc/fstab file parser'
|
||||
description = 'fstab file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
@@ -79,6 +79,9 @@ class info():
|
||||
compatible = ['linux']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
190
jc/parsers/group.py
Normal file
190
jc/parsers/group.py
Normal file
@@ -0,0 +1,190 @@
|
||||
"""jc - JSON CLI output utility /etc/group file Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --group as the first argument if the piped input is coming from /etc/group
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat /etc/group | jc --group -p
|
||||
[
|
||||
{
|
||||
"group_name": "nobody",
|
||||
"password": "*",
|
||||
"gid": -2,
|
||||
"members": []
|
||||
},
|
||||
{
|
||||
"group_name": "nogroup",
|
||||
"password": "*",
|
||||
"gid": -1,
|
||||
"members": []
|
||||
},
|
||||
{
|
||||
"group_name": "wheel",
|
||||
"password": "*",
|
||||
"gid": 0,
|
||||
"members": [
|
||||
"root"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_name": "certusers",
|
||||
"password": "*",
|
||||
"gid": 29,
|
||||
"members": [
|
||||
"root",
|
||||
"_jabber",
|
||||
"_postfix",
|
||||
"_cyrus",
|
||||
"_calendar",
|
||||
"_dovecot"
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
$ cat /etc/group | jc --group -p -r
|
||||
[
|
||||
{
|
||||
"group_name": "nobody",
|
||||
"password": "*",
|
||||
"gid": "-2",
|
||||
"members": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_name": "nogroup",
|
||||
"password": "*",
|
||||
"gid": "-1",
|
||||
"members": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_name": "wheel",
|
||||
"password": "*",
|
||||
"gid": "0",
|
||||
"members": [
|
||||
"root"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_name": "certusers",
|
||||
"password": "*",
|
||||
"gid": "29",
|
||||
"members": [
|
||||
"root",
|
||||
"_jabber",
|
||||
"_postfix",
|
||||
"_cyrus",
|
||||
"_calendar",
|
||||
"_dovecot"
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
||||
"""
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = '/etc/group file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'aix', 'freebsd']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"group_name": string,
|
||||
"password": string,
|
||||
"gid": integer,
|
||||
"members": [
|
||||
string
|
||||
]
|
||||
}
|
||||
]
|
||||
"""
|
||||
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
|
||||
|
||||
if entry['members'] == ['']:
|
||||
entry['members'] = []
|
||||
|
||||
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)
|
||||
|
||||
raw_output = []
|
||||
cleandata = data.splitlines()
|
||||
|
||||
# Clear any blank lines
|
||||
cleandata = list(filter(None, cleandata))
|
||||
|
||||
if cleandata:
|
||||
for entry in cleandata:
|
||||
if entry.startswith('#'):
|
||||
continue
|
||||
|
||||
output_line = {}
|
||||
fields = entry.split(':')
|
||||
|
||||
output_line['group_name'] = fields[0]
|
||||
output_line['password'] = fields[1]
|
||||
output_line['gid'] = fields[2]
|
||||
output_line['members'] = fields[3].split(',')
|
||||
|
||||
raw_output.append(output_line)
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
152
jc/parsers/gshadow.py
Normal file
152
jc/parsers/gshadow.py
Normal file
@@ -0,0 +1,152 @@
|
||||
"""jc - JSON CLI output utility /etc/gshadow file Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --gshadow as the first argument if the piped input is coming from /etc/gshadow
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat /etc/gshadow | jc --gshadow -p
|
||||
[
|
||||
{
|
||||
"group_name": "root",
|
||||
"password": "*",
|
||||
"administrators": [],
|
||||
"members": []
|
||||
},
|
||||
{
|
||||
"group_name": "adm",
|
||||
"password": "*",
|
||||
"administrators": [],
|
||||
"members": [
|
||||
"syslog",
|
||||
"joeuser"
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
$ cat /etc/gshadow | jc --gshadow -p -r
|
||||
[
|
||||
{
|
||||
"group_name": "root",
|
||||
"password": "*",
|
||||
"administrators": [
|
||||
""
|
||||
],
|
||||
"members": [
|
||||
""
|
||||
]
|
||||
},
|
||||
{
|
||||
"group_name": "adm",
|
||||
"password": "*",
|
||||
"administrators": [
|
||||
""
|
||||
],
|
||||
"members": [
|
||||
"syslog",
|
||||
"joeuser"
|
||||
]
|
||||
},
|
||||
...
|
||||
]
|
||||
"""
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = '/etc/gshadow file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'aix', 'freebsd']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"group_name": string,
|
||||
"password": string,
|
||||
"administrators": [
|
||||
string
|
||||
],
|
||||
"members": [
|
||||
string
|
||||
]
|
||||
}
|
||||
]
|
||||
"""
|
||||
for entry in proc_data:
|
||||
if entry['administrators'] == ['']:
|
||||
entry['administrators'] = []
|
||||
|
||||
if entry['members'] == ['']:
|
||||
entry['members'] = []
|
||||
|
||||
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)
|
||||
|
||||
raw_output = []
|
||||
cleandata = data.splitlines()
|
||||
|
||||
# Clear any blank lines
|
||||
cleandata = list(filter(None, cleandata))
|
||||
|
||||
if cleandata:
|
||||
for entry in cleandata:
|
||||
if entry.startswith('#'):
|
||||
continue
|
||||
|
||||
output_line = {}
|
||||
fields = entry.split(':')
|
||||
|
||||
output_line['group_name'] = fields[0]
|
||||
output_line['password'] = fields[1]
|
||||
output_line['administrators'] = fields[2].split(',')
|
||||
output_line['members'] = fields[3].split(',')
|
||||
|
||||
raw_output.append(output_line)
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
@@ -6,26 +6,26 @@ Usage:
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
|
||||
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ history | jc --history -p
|
||||
[
|
||||
{
|
||||
"line": "118",
|
||||
"line": 118,
|
||||
"command": "sleep 100"
|
||||
},
|
||||
{
|
||||
"line": "119",
|
||||
"line": 119,
|
||||
"command": "ls /bin"
|
||||
},
|
||||
{
|
||||
"line": "120",
|
||||
"line": 120,
|
||||
"command": "echo \"hello\""
|
||||
},
|
||||
{
|
||||
"line": "121",
|
||||
"line": 121,
|
||||
"command": "docker images"
|
||||
},
|
||||
...
|
||||
@@ -45,12 +45,15 @@ import jc
|
||||
|
||||
class info():
|
||||
version = '1.1'
|
||||
description = 'history parser'
|
||||
description = 'history command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
@@ -67,7 +70,7 @@ def process(proc_data):
|
||||
|
||||
[
|
||||
{
|
||||
"line": string,
|
||||
"line": integer,
|
||||
"command": string
|
||||
}
|
||||
]
|
||||
@@ -81,6 +84,16 @@ def process(proc_data):
|
||||
proc_line['command'] = v
|
||||
processed.append(proc_line)
|
||||
|
||||
for entry in processed:
|
||||
int_list = ['line']
|
||||
for key in int_list:
|
||||
if key in entry:
|
||||
try:
|
||||
key_int = int(entry[key])
|
||||
entry[key] = key_int
|
||||
except (ValueError):
|
||||
entry[key] = None
|
||||
|
||||
return processed
|
||||
|
||||
|
||||
|
||||
@@ -70,6 +70,9 @@ class info():
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
215
jc/parsers/id.py
Normal file
215
jc/parsers/id.py
Normal file
@@ -0,0 +1,215 @@
|
||||
"""jc - JSON CLI output utility id Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --id as the first argument if the piped input is coming from id
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ id | jc --id -p
|
||||
{
|
||||
"uid": {
|
||||
"id": 1000,
|
||||
"name": "joeuser"
|
||||
},
|
||||
"gid": {
|
||||
"id": 1000,
|
||||
"name": "joeuser"
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"id": 1000,
|
||||
"name": "joeuser"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "wheel"
|
||||
}
|
||||
],
|
||||
"context": {
|
||||
"user": "unconfined_u",
|
||||
"role": "unconfined_r",
|
||||
"type": "unconfined_t",
|
||||
"level": "s0-s0:c0.c1023"
|
||||
}
|
||||
}
|
||||
|
||||
$ id | jc --id -p -r
|
||||
{
|
||||
"uid": {
|
||||
"id": "1000",
|
||||
"name": "joeuser"
|
||||
},
|
||||
"gid": {
|
||||
"id": "1000",
|
||||
"name": "joeuser"
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"id": "1000",
|
||||
"name": "joeuser"
|
||||
},
|
||||
{
|
||||
"id": "10",
|
||||
"name": "wheel"
|
||||
}
|
||||
],
|
||||
"context": {
|
||||
"user": "unconfined_u",
|
||||
"role": "unconfined_r",
|
||||
"type": "unconfined_t",
|
||||
"level": "s0-s0:c0.c1023"
|
||||
}
|
||||
}
|
||||
"""
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'id command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'aix', 'freebsd']
|
||||
magic_commands = ['id']
|
||||
|
||||
|
||||
__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. Structured data with the following schema:
|
||||
|
||||
{
|
||||
"uid": {
|
||||
"id": integer,
|
||||
"name": string
|
||||
},
|
||||
"gid": {
|
||||
"id": integer,
|
||||
"name": string
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"id": integer,
|
||||
"name": string
|
||||
},
|
||||
{
|
||||
"id": integer,
|
||||
"name": string
|
||||
}
|
||||
],
|
||||
"context": {
|
||||
"user": string,
|
||||
"role": string,
|
||||
"type": string,
|
||||
"level": string
|
||||
}
|
||||
}
|
||||
"""
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
raw_output = {}
|
||||
cleandata = data.split()
|
||||
|
||||
# Clear any blank lines
|
||||
cleandata = list(filter(None, cleandata))
|
||||
|
||||
if cleandata:
|
||||
for section in cleandata:
|
||||
if section.startswith('uid'):
|
||||
uid_parsed = section.replace('(', '=').replace(')', '=')
|
||||
uid_parsed = uid_parsed.split('=')
|
||||
raw_output['uid'] = {}
|
||||
raw_output['uid']['id'] = uid_parsed[1]
|
||||
raw_output['uid']['name'] = uid_parsed[2]
|
||||
|
||||
if section.startswith('gid'):
|
||||
gid_parsed = section.replace('(', '=').replace(')', '=')
|
||||
gid_parsed = gid_parsed.split('=')
|
||||
raw_output['gid'] = {}
|
||||
raw_output['gid']['id'] = gid_parsed[1]
|
||||
raw_output['gid']['name'] = gid_parsed[2]
|
||||
|
||||
if section.startswith('groups'):
|
||||
groups_parsed = section.replace('(', '=').replace(')', '=')
|
||||
groups_parsed = groups_parsed.replace('groups=', '')
|
||||
groups_parsed = groups_parsed.split(',')
|
||||
raw_output['groups'] = []
|
||||
|
||||
for group in groups_parsed:
|
||||
group_dict = {}
|
||||
grp_parsed = group.split('=')
|
||||
group_dict['id'] = grp_parsed[0]
|
||||
group_dict['name'] = grp_parsed[1]
|
||||
raw_output['groups'].append(group_dict)
|
||||
|
||||
if section.startswith('context'):
|
||||
context_parsed = section.replace('context=', '')
|
||||
context_parsed = context_parsed.split(':', maxsplit=3)
|
||||
raw_output['context'] = {}
|
||||
raw_output['context']['user'] = context_parsed[0]
|
||||
raw_output['context']['role'] = context_parsed[1]
|
||||
raw_output['context']['type'] = context_parsed[2]
|
||||
raw_output['context']['level'] = context_parsed[3]
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
@@ -147,13 +147,17 @@ from ifconfigparser import IfconfigParser
|
||||
|
||||
class info():
|
||||
version = '1.5'
|
||||
description = 'ifconfig parser'
|
||||
description = 'ifconfig command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
details = 'Using ifconfig-parser package from https://github.com/KnightWhoSayNi/ifconfig-parser'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'aix', 'freebsd', 'darwin']
|
||||
magic_commands = ['ifconfig']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
112
jc/parsers/ini.py
Normal file
112
jc/parsers/ini.py
Normal file
@@ -0,0 +1,112 @@
|
||||
"""jc - JSON CLI output utility INI Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --ini as the first argument if the piped input is coming from an INI file
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat example.ini
|
||||
[DEFAULT]
|
||||
ServerAliveInterval = 45
|
||||
Compression = yes
|
||||
CompressionLevel = 9
|
||||
ForwardX11 = yes
|
||||
|
||||
[bitbucket.org]
|
||||
User = hg
|
||||
|
||||
[topsecret.server.com]
|
||||
Port = 50022
|
||||
ForwardX11 = no
|
||||
|
||||
$ cat example.ini | jc --ini -p
|
||||
{
|
||||
"bitbucket.org": {
|
||||
"serveraliveinterval": "45",
|
||||
"compression": "yes",
|
||||
"compressionlevel": "9",
|
||||
"forwardx11": "yes",
|
||||
"user": "hg"
|
||||
},
|
||||
"topsecret.server.com": {
|
||||
"serveraliveinterval": "45",
|
||||
"compression": "yes",
|
||||
"compressionlevel": "9",
|
||||
"forwardx11": "no",
|
||||
"port": "50022"
|
||||
}
|
||||
}
|
||||
"""
|
||||
import jc.utils
|
||||
import configparser
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'INI file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
details = 'Using configparser from the standard library'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
|
||||
|
||||
__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 representing an ini document:
|
||||
|
||||
{
|
||||
ini document converted to a dictionary
|
||||
see configparser standard library documentation for more details
|
||||
}
|
||||
"""
|
||||
|
||||
# No further processing
|
||||
return proc_data
|
||||
|
||||
|
||||
def parse(data, raw=False, quiet=False):
|
||||
"""
|
||||
Main text parsing function
|
||||
|
||||
Parameters:
|
||||
|
||||
data: (string) text data to parse
|
||||
raw: (boolean) output preprocessed JSON if True
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary representing the ini file
|
||||
"""
|
||||
if not quiet:
|
||||
jc.utils.compatibility(__name__, info.compatible)
|
||||
|
||||
raw_output = {}
|
||||
|
||||
if data:
|
||||
ini = configparser.ConfigParser()
|
||||
ini.read_string(data)
|
||||
raw_output = {s: dict(ini.items(s)) for s in ini.sections()}
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
@@ -135,12 +135,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.1'
|
||||
description = 'iptables parser'
|
||||
description = 'iptables command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['iptables']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -78,12 +78,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'jobs parser'
|
||||
description = 'jobs command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
|
||||
magic_commands = ['jobs']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
181
jc/parsers/last.py
Normal file
181
jc/parsers/last.py
Normal file
@@ -0,0 +1,181 @@
|
||||
"""jc - JSON CLI output utility last Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --last as the first argument if the piped input is coming from last or lastb
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ last | jc --last -p
|
||||
[
|
||||
{
|
||||
"user": "kbrazil",
|
||||
"tty": "ttys002",
|
||||
"hostname": null,
|
||||
"login": "Thu Feb 27 14:31",
|
||||
"logout": "still logged in"
|
||||
},
|
||||
{
|
||||
"user": "kbrazil",
|
||||
"tty": "ttys003",
|
||||
"hostname": null,
|
||||
"login": "Thu Feb 27 10:38",
|
||||
"logout": "10:38",
|
||||
"duration": "00:00"
|
||||
},
|
||||
{
|
||||
"user": "kbrazil",
|
||||
"tty": "ttys003",
|
||||
"hostname": null,
|
||||
"login": "Thu Feb 27 10:18",
|
||||
"logout": "10:18",
|
||||
"duration": "00:00"
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
$ last | jc --last -p -r
|
||||
[
|
||||
{
|
||||
"user": "kbrazil",
|
||||
"tty": "ttys002",
|
||||
"hostname": "-",
|
||||
"login": "Thu Feb 27 14:31",
|
||||
"logout": "still_logged_in"
|
||||
},
|
||||
{
|
||||
"user": "kbrazil",
|
||||
"tty": "ttys003",
|
||||
"hostname": "-",
|
||||
"login": "Thu Feb 27 10:38",
|
||||
"logout": "10:38",
|
||||
"duration": "00:00"
|
||||
},
|
||||
{
|
||||
"user": "kbrazil",
|
||||
"tty": "ttys003",
|
||||
"hostname": "-",
|
||||
"login": "Thu Feb 27 10:18",
|
||||
"logout": "10:18",
|
||||
"duration": "00:00"
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
"""
|
||||
import re
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'last and lastb command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'aix', 'freebsd']
|
||||
magic_commands = ['last', 'lastb']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"user": string,
|
||||
"tty": string,
|
||||
"hostname": string,
|
||||
"login": string,
|
||||
"logout": string,
|
||||
"duration": string
|
||||
}
|
||||
]
|
||||
"""
|
||||
for entry in proc_data:
|
||||
if 'tty' in entry and entry['tty'] == '~':
|
||||
entry['tty'] = None
|
||||
|
||||
if 'tty' in entry and entry['tty'] == 'system_boot':
|
||||
entry['tty'] = 'system boot'
|
||||
|
||||
if 'hostname' in entry and entry['hostname'] == '-':
|
||||
entry['hostname'] = None
|
||||
|
||||
if 'logout' in entry and entry['logout'] == 'still_logged_in':
|
||||
entry['logout'] = 'still logged in'
|
||||
|
||||
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)
|
||||
|
||||
raw_output = []
|
||||
cleandata = data.splitlines()
|
||||
|
||||
# Clear any blank lines
|
||||
cleandata = list(filter(None, cleandata))
|
||||
|
||||
if cleandata:
|
||||
for entry in cleandata:
|
||||
output_line = {}
|
||||
|
||||
if entry.startswith('wtmp begins ') or entry.startswith('btmp begins '):
|
||||
continue
|
||||
|
||||
entry = entry.replace('system boot', 'system_boot')
|
||||
entry = entry.replace(' still logged in', '- still_logged_in')
|
||||
|
||||
linedata = entry.split()
|
||||
if re.match(r'[MTWFS][ouerha][nedritnu] [JFMASOND][aepuco][nbrynlgptvc]', ' '.join(linedata[2:4])):
|
||||
linedata.insert(2, '-')
|
||||
|
||||
output_line['user'] = linedata[0]
|
||||
output_line['tty'] = linedata[1]
|
||||
output_line['hostname'] = linedata[2]
|
||||
output_line['login'] = ' '.join(linedata[3:7])
|
||||
|
||||
if len(linedata) > 8:
|
||||
output_line['logout'] = linedata[8]
|
||||
|
||||
if len(linedata) > 9:
|
||||
output_line['duration'] = linedata[9].replace('(', '').replace(')', '')
|
||||
|
||||
raw_output.append(output_line)
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
@@ -1,15 +1,20 @@
|
||||
"""jc - JSON CLI output utility ls Parser
|
||||
|
||||
Note: The -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 -l or -b is not used.
|
||||
|
||||
Usage:
|
||||
|
||||
specify --ls as the first argument if the piped input is coming from ls
|
||||
|
||||
ls options supported:
|
||||
- None
|
||||
- la
|
||||
- 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 default view
|
||||
since the parser attempts to convert this field to an integer.
|
||||
|
||||
-lbaR
|
||||
--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 default view
|
||||
since the parser attempts to convert this field to an integer.
|
||||
|
||||
Compatibility:
|
||||
|
||||
@@ -144,13 +149,17 @@ import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'ls parser'
|
||||
version = '1.2'
|
||||
description = 'ls command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
|
||||
magic_commands = ['ls']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
@@ -170,6 +179,7 @@ def process(proc_data):
|
||||
"filename": string,
|
||||
"flags": string,
|
||||
"links": integer,
|
||||
"parent": string,
|
||||
"owner": string,
|
||||
"group": string,
|
||||
"size": integer,
|
||||
@@ -209,27 +219,58 @@ def parse(data, raw=False, quiet=False):
|
||||
jc.utils.compatibility(__name__, info.compatible)
|
||||
|
||||
raw_output = []
|
||||
warned = False
|
||||
parent = ''
|
||||
next_is_parent = False
|
||||
new_section = False
|
||||
|
||||
linedata = data.splitlines()
|
||||
|
||||
# Delete first line if it starts with 'total'
|
||||
# Delete first line if it starts with 'total 1234'
|
||||
if linedata:
|
||||
if linedata[0].find('total') == 0:
|
||||
if re.match(r'total [0-9]+', linedata[0]):
|
||||
linedata.pop(0)
|
||||
|
||||
# Clear any blank lines
|
||||
cleandata = list(filter(None, linedata))
|
||||
# Look for parent line if glob or -R is used
|
||||
if not re.match(r'[-dclpsbDCMnP?]([-r][-w][-xsS]){2}([-r][-w][-xtT])[+]?', linedata[0]) \
|
||||
and linedata[0].endswith(':'):
|
||||
parent = linedata.pop(0)[:-1]
|
||||
# Pop following total line
|
||||
linedata.pop(0)
|
||||
|
||||
if cleandata:
|
||||
if linedata:
|
||||
# Check if -l was used to parse extra data
|
||||
if re.match('^[-dclpsbDCMnP?]([-r][-w][-xsS]){2}([-r][-w][-xtT])[+]?', cleandata[0]):
|
||||
for entry in cleandata:
|
||||
if re.match(r'[-dclpsbDCMnP?]([-r][-w][-xsS]){2}([-r][-w][-xtT])[+]?', linedata[0]):
|
||||
for entry in linedata:
|
||||
output_line = {}
|
||||
|
||||
parsed_line = entry.split(maxsplit=8)
|
||||
|
||||
if not re.match(r'[-dclpsbDCMnP?]([-r][-w][-xsS]){2}([-r][-w][-xtT])[+]?', entry) \
|
||||
and entry.endswith(':'):
|
||||
parent = entry[:-1]
|
||||
new_section = True
|
||||
|
||||
# fixup to remove trailing \n in previous entry
|
||||
raw_output[-1]['filename'] = raw_output[-1]['filename'][:-1]
|
||||
continue
|
||||
|
||||
if re.match(r'total [0-9]+', entry):
|
||||
new_section = False
|
||||
continue
|
||||
|
||||
# fixup for filenames with newlines
|
||||
if not new_section \
|
||||
and not re.match(r'[-dclpsbDCMnP?]([-r][-w][-xsS]){2}([-r][-w][-xtT])[+]?', entry):
|
||||
raw_output[-1]['filename'] = raw_output[-1]['filename'] + '\n' + entry
|
||||
continue
|
||||
|
||||
# split filenames and links
|
||||
filename_field = parsed_line[8].split(' -> ')
|
||||
if len(parsed_line) == 9:
|
||||
filename_field = parsed_line[8].split(' -> ')
|
||||
else:
|
||||
# in case of filenames starting with a newline character
|
||||
filename_field = ['']
|
||||
|
||||
# create list of dictionaries
|
||||
output_line['filename'] = filename_field[0]
|
||||
@@ -237,6 +278,9 @@ def parse(data, raw=False, quiet=False):
|
||||
if len(filename_field) > 1:
|
||||
output_line['link_to'] = filename_field[1]
|
||||
|
||||
if parent:
|
||||
output_line['parent'] = parent
|
||||
|
||||
output_line['flags'] = parsed_line[0]
|
||||
output_line['links'] = parsed_line[1]
|
||||
output_line['owner'] = parsed_line[2]
|
||||
@@ -245,9 +289,27 @@ def parse(data, raw=False, quiet=False):
|
||||
output_line['date'] = ' '.join(parsed_line[5:8])
|
||||
raw_output.append(output_line)
|
||||
else:
|
||||
for entry in cleandata:
|
||||
for entry in linedata:
|
||||
output_line = {}
|
||||
|
||||
if entry == '':
|
||||
next_is_parent = True
|
||||
continue
|
||||
|
||||
if next_is_parent and entry.endswith(':'):
|
||||
parent = entry[:-1]
|
||||
next_is_parent = False
|
||||
continue
|
||||
|
||||
if not quiet and next_is_parent and not entry.endswith(':') and not warned:
|
||||
jc.utils.warning_message('Newline characters detected. Filenames probably corrupted. Use ls -l or -b instead.')
|
||||
warned = True
|
||||
|
||||
output_line['filename'] = entry
|
||||
|
||||
if parent:
|
||||
output_line['parent'] = parent
|
||||
|
||||
raw_output.append(output_line)
|
||||
|
||||
if raw:
|
||||
|
||||
@@ -217,12 +217,16 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
version = '1.3'
|
||||
description = 'lsblk parser'
|
||||
description = 'lsblk command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['lsblk']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -108,12 +108,16 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
version = '1.1'
|
||||
description = 'lsmod parser'
|
||||
description = 'lsmod command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['lsmod']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -98,12 +98,16 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'lsof parser'
|
||||
description = 'lsof command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['lsof']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -57,12 +57,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.1'
|
||||
description = 'mount parser'
|
||||
description = 'mount command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin']
|
||||
magic_commands = ['mount']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -314,12 +314,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.2'
|
||||
description = 'netstat parser'
|
||||
description = 'netstat command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['netstat']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
175
jc/parsers/passwd.py
Normal file
175
jc/parsers/passwd.py
Normal file
@@ -0,0 +1,175 @@
|
||||
"""jc - JSON CLI output utility /etc/passwd file Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --passwd as the first argument if the piped input is coming from /etc/passwd
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat /etc/passwd | jc --passwd -p
|
||||
[
|
||||
{
|
||||
"username": "nobody",
|
||||
"password": "*",
|
||||
"uid": -2,
|
||||
"gid": -2,
|
||||
"comment": "Unprivileged User",
|
||||
"home": "/var/empty",
|
||||
"shell": "/usr/bin/false"
|
||||
},
|
||||
{
|
||||
"username": "root",
|
||||
"password": "*",
|
||||
"uid": 0,
|
||||
"gid": 0,
|
||||
"comment": "System Administrator",
|
||||
"home": "/var/root",
|
||||
"shell": "/bin/sh"
|
||||
},
|
||||
{
|
||||
"username": "daemon",
|
||||
"password": "*",
|
||||
"uid": 1,
|
||||
"gid": 1,
|
||||
"comment": "System Services",
|
||||
"home": "/var/root",
|
||||
"shell": "/usr/bin/false"
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
$ cat /etc/passwd | jc --passwd -p -r
|
||||
[
|
||||
{
|
||||
"username": "nobody",
|
||||
"password": "*",
|
||||
"uid": "-2",
|
||||
"gid": "-2",
|
||||
"comment": "Unprivileged User",
|
||||
"home": "/var/empty",
|
||||
"shell": "/usr/bin/false"
|
||||
},
|
||||
{
|
||||
"username": "root",
|
||||
"password": "*",
|
||||
"uid": "0",
|
||||
"gid": "0",
|
||||
"comment": "System Administrator",
|
||||
"home": "/var/root",
|
||||
"shell": "/bin/sh"
|
||||
},
|
||||
{
|
||||
"username": "daemon",
|
||||
"password": "*",
|
||||
"uid": "1",
|
||||
"gid": "1",
|
||||
"comment": "System Services",
|
||||
"home": "/var/root",
|
||||
"shell": "/usr/bin/false"
|
||||
},
|
||||
...
|
||||
]
|
||||
"""
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = '/etc/passwd file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'aix', 'freebsd']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"username": string,
|
||||
"password": string,
|
||||
"uid": integer,
|
||||
"gid": integer,
|
||||
"comment": string,
|
||||
"home": string,
|
||||
"shell": string
|
||||
}
|
||||
]
|
||||
"""
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
raw_output = []
|
||||
cleandata = data.splitlines()
|
||||
|
||||
# Clear any blank lines
|
||||
cleandata = list(filter(None, cleandata))
|
||||
|
||||
if cleandata:
|
||||
for entry in cleandata:
|
||||
if entry.startswith('#'):
|
||||
continue
|
||||
|
||||
output_line = {}
|
||||
fields = entry.split(':')
|
||||
|
||||
output_line['username'] = fields[0]
|
||||
output_line['password'] = fields[1]
|
||||
output_line['uid'] = fields[2]
|
||||
output_line['gid'] = fields[3]
|
||||
output_line['comment'] = fields[4]
|
||||
output_line['home'] = fields[5]
|
||||
output_line['shell'] = fields[6]
|
||||
|
||||
raw_output.append(output_line)
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
@@ -33,12 +33,16 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'pip-list parser'
|
||||
description = 'pip list command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
magic_commands = ['pip list', 'pip3 list']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -43,12 +43,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'pip-show parser'
|
||||
description = 'pip show command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
magic_commands = ['pip show', 'pip3 show']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -178,12 +178,16 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
version = '1.1'
|
||||
description = 'ps parser'
|
||||
description = 'ps command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
|
||||
magic_commands = ['ps']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -102,12 +102,16 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'route parser'
|
||||
description = 'route command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['route']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
183
jc/parsers/shadow.py
Normal file
183
jc/parsers/shadow.py
Normal file
@@ -0,0 +1,183 @@
|
||||
"""jc - JSON CLI output utility /etc/shadow file Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --shadow as the first argument if the piped input is coming from /etc/shadow
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ sudo cat /etc/shadow | jc --shadow -p
|
||||
[
|
||||
{
|
||||
"username": "root",
|
||||
"password": "*",
|
||||
"last_changed": 18113,
|
||||
"minimum": 0,
|
||||
"maximum": 99999,
|
||||
"warn": 7,
|
||||
"inactive": null,
|
||||
"expire": null
|
||||
},
|
||||
{
|
||||
"username": "daemon",
|
||||
"password": "*",
|
||||
"last_changed": 18113,
|
||||
"minimum": 0,
|
||||
"maximum": 99999,
|
||||
"warn": 7,
|
||||
"inactive": null,
|
||||
"expire": null
|
||||
},
|
||||
{
|
||||
"username": "bin",
|
||||
"password": "*",
|
||||
"last_changed": 18113,
|
||||
"minimum": 0,
|
||||
"maximum": 99999,
|
||||
"warn": 7,
|
||||
"inactive": null,
|
||||
"expire": null
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
$ sudo cat /etc/shadow | jc --shadow -p -r
|
||||
[
|
||||
{
|
||||
"username": "root",
|
||||
"password": "*",
|
||||
"last_changed": "18113",
|
||||
"minimum": "0",
|
||||
"maximum": "99999",
|
||||
"warn": "7",
|
||||
"inactive": "",
|
||||
"expire": ""
|
||||
},
|
||||
{
|
||||
"username": "daemon",
|
||||
"password": "*",
|
||||
"last_changed": "18113",
|
||||
"minimum": "0",
|
||||
"maximum": "99999",
|
||||
"warn": "7",
|
||||
"inactive": "",
|
||||
"expire": ""
|
||||
},
|
||||
{
|
||||
"username": "bin",
|
||||
"password": "*",
|
||||
"last_changed": "18113",
|
||||
"minimum": "0",
|
||||
"maximum": "99999",
|
||||
"warn": "7",
|
||||
"inactive": "",
|
||||
"expire": ""
|
||||
},
|
||||
...
|
||||
]
|
||||
"""
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = '/etc/shadow file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'aix', 'freebsd']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"username": string,
|
||||
"password": string,
|
||||
"last_changed": integer,
|
||||
"minimum": integer,
|
||||
"maximum": integer,
|
||||
"warn": integer,
|
||||
"inactive": integer,
|
||||
"expire": integer
|
||||
}
|
||||
]
|
||||
"""
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
raw_output = []
|
||||
cleandata = data.splitlines()
|
||||
|
||||
# Clear any blank lines
|
||||
cleandata = list(filter(None, cleandata))
|
||||
|
||||
if cleandata:
|
||||
for entry in cleandata:
|
||||
if entry.startswith('#'):
|
||||
continue
|
||||
|
||||
output_line = {}
|
||||
fields = entry.split(':')
|
||||
|
||||
output_line['username'] = fields[0]
|
||||
output_line['password'] = fields[1]
|
||||
output_line['last_changed'] = fields[2]
|
||||
output_line['minimum'] = fields[3]
|
||||
output_line['maximum'] = fields[4]
|
||||
output_line['warn'] = fields[5]
|
||||
output_line['inactive'] = fields[6]
|
||||
output_line['expire'] = fields[7]
|
||||
|
||||
raw_output.append(output_line)
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
@@ -252,12 +252,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'ss parser'
|
||||
description = 'ss command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['ss']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -105,12 +105,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'stat parser'
|
||||
description = 'stat command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['stat']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -41,12 +41,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'systemctl parser'
|
||||
description = 'systemctl command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['systemctl']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -60,12 +60,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'systemctl list-jobs parser'
|
||||
description = 'systemctl list-jobs command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['systemctl list-jobs']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -35,12 +35,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'systemctl list-sockets parser'
|
||||
description = 'systemctl list-sockets command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['systemctl list-sockets']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -32,12 +32,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'systemctl list-unit-files parser'
|
||||
description = 'systemctl list-unit-files command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux']
|
||||
magic_commands = ['systemctl list-unit-files']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -31,12 +31,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.1'
|
||||
description = 'uname -a parser'
|
||||
description = 'uname -a command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin']
|
||||
magic_commands = ['uname']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -35,12 +35,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'uptime parser'
|
||||
description = 'uptime command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
|
||||
magic_commands = ['uptime']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
@@ -84,12 +84,16 @@ import jc.utils
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'w parser'
|
||||
description = 'w command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
|
||||
magic_commands = ['w']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
|
||||
284
jc/parsers/who.py
Normal file
284
jc/parsers/who.py
Normal file
@@ -0,0 +1,284 @@
|
||||
"""jc - JSON CLI output utility who Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --who as the first argument if the piped input is coming from who
|
||||
|
||||
accepts any of the following who options (or no options): -aTH
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ who -a | jc --who -p
|
||||
[
|
||||
{
|
||||
"event": "reboot",
|
||||
"time": "Feb 7 23:31",
|
||||
"pid": 1
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "-",
|
||||
"tty": "console",
|
||||
"time": "Feb 7 23:32",
|
||||
"idle": "old",
|
||||
"pid": 105
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "+",
|
||||
"tty": "ttys000",
|
||||
"time": "Feb 13 16:44",
|
||||
"idle": ".",
|
||||
"pid": 51217,
|
||||
"comment": "term=0 exit=0"
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "?",
|
||||
"tty": "ttys003",
|
||||
"time": "Feb 28 08:59",
|
||||
"idle": "01:36",
|
||||
"pid": 41402
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "+",
|
||||
"tty": "ttys004",
|
||||
"time": "Mar 1 16:35",
|
||||
"idle": ".",
|
||||
"pid": 15679,
|
||||
"from": "192.168.1.5"
|
||||
}
|
||||
]
|
||||
|
||||
$ who -a | jc --who -p -r
|
||||
[
|
||||
{
|
||||
"event": "reboot",
|
||||
"time": "Feb 7 23:31",
|
||||
"pid": "1"
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "-",
|
||||
"tty": "console",
|
||||
"time": "Feb 7 23:32",
|
||||
"idle": "old",
|
||||
"pid": "105"
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "+",
|
||||
"tty": "ttys000",
|
||||
"time": "Feb 13 16:44",
|
||||
"idle": ".",
|
||||
"pid": "51217",
|
||||
"comment": "term=0 exit=0"
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "?",
|
||||
"tty": "ttys003",
|
||||
"time": "Feb 28 08:59",
|
||||
"idle": "01:36",
|
||||
"pid": "41402"
|
||||
},
|
||||
{
|
||||
"user": "joeuser",
|
||||
"writeable_tty": "+",
|
||||
"tty": "ttys004",
|
||||
"time": "Mar 1 16:35",
|
||||
"idle": ".",
|
||||
"pid": "15679",
|
||||
"from": "192.168.1.5"
|
||||
}
|
||||
]
|
||||
"""
|
||||
import re
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'who command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
# details = 'enter any other details here'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'aix', 'freebsd']
|
||||
magic_commands = ['who']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Structured data with the following schema:
|
||||
|
||||
[
|
||||
{
|
||||
"user": string,
|
||||
"event": string,
|
||||
"writeable_tty": string,
|
||||
"tty": string,
|
||||
"time": string,
|
||||
"idle": string,
|
||||
"pid": integer,
|
||||
"from": string,
|
||||
"comment": string
|
||||
}
|
||||
]
|
||||
"""
|
||||
for entry in proc_data:
|
||||
int_list = ['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
|
||||
|
||||
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)
|
||||
|
||||
raw_output = []
|
||||
cleandata = data.splitlines()
|
||||
|
||||
# Clear any blank lines
|
||||
cleandata = list(filter(None, cleandata))
|
||||
|
||||
if cleandata:
|
||||
for line in cleandata:
|
||||
output_line = {}
|
||||
linedata = line.split()
|
||||
|
||||
# clear headers, if they exist
|
||||
if ''.join(linedata[0:3]) == 'NAMELINETIME' \
|
||||
or ''.join(linedata[0:3]) == 'USERLINEWHEN':
|
||||
linedata.pop(0)
|
||||
continue
|
||||
|
||||
# mac reboot line
|
||||
if linedata[0] == 'reboot':
|
||||
output_line['event'] = 'reboot'
|
||||
output_line['time'] = ' '.join(linedata[2:5])
|
||||
output_line['pid'] = linedata[6]
|
||||
raw_output.append(output_line)
|
||||
continue
|
||||
|
||||
# linux reboot line
|
||||
if ''.join(linedata[0:2]) == 'systemboot':
|
||||
output_line['event'] = 'reboot'
|
||||
output_line['time'] = ' '.join(linedata[2:4])
|
||||
raw_output.append(output_line)
|
||||
continue
|
||||
|
||||
# linux login line
|
||||
if linedata[0] == 'LOGIN':
|
||||
output_line['event'] = 'login'
|
||||
output_line['tty'] = linedata[1]
|
||||
output_line['time'] = ' '.join(linedata[2:4])
|
||||
output_line['pid'] = linedata[4]
|
||||
if len(linedata) > 5:
|
||||
output_line['comment'] = ' '.join(linedata[5:])
|
||||
raw_output.append(output_line)
|
||||
continue
|
||||
|
||||
# linux run-level
|
||||
if linedata[0] == 'run-level':
|
||||
output_line['event'] = ' '.join(linedata[0:2])
|
||||
output_line['time'] = ' '.join(linedata[2:4])
|
||||
raw_output.append(output_line)
|
||||
continue
|
||||
|
||||
# mac run-level (ignore because not enough useful info)
|
||||
if linedata[1] == 'run-level':
|
||||
continue
|
||||
|
||||
# pts lines with no user information
|
||||
if linedata[0].startswith('pts/'):
|
||||
output_line['tty'] = linedata[0]
|
||||
output_line['time'] = ' '.join(linedata[1:3])
|
||||
output_line['pid'] = linedata[3]
|
||||
output_line['comment'] = ' '.join(linedata[4:])
|
||||
raw_output.append(output_line)
|
||||
continue
|
||||
|
||||
# user logins
|
||||
output_line['user'] = linedata.pop(0)
|
||||
|
||||
if linedata[0] in '+-?':
|
||||
output_line['writeable_tty'] = linedata.pop(0)
|
||||
|
||||
output_line['tty'] = linedata.pop(0)
|
||||
|
||||
# mac
|
||||
if re.match(r'[JFMASOND][aepuco][nbrynlgptvc]', linedata[0]):
|
||||
output_line['time'] = ' '.join([linedata.pop(0),
|
||||
linedata.pop(0),
|
||||
linedata.pop(0)])
|
||||
# linux
|
||||
else:
|
||||
output_line['time'] = ' '.join([linedata.pop(0),
|
||||
linedata.pop(0)])
|
||||
|
||||
# if just one more field, then it's the remote IP
|
||||
if len(linedata) == 1:
|
||||
output_line['from'] = linedata[0].replace('(', '').replace(')', '')
|
||||
raw_output.append(output_line)
|
||||
continue
|
||||
|
||||
# extended info: idle
|
||||
if len(linedata) > 0:
|
||||
output_line['idle'] = linedata.pop(0)
|
||||
|
||||
# extended info: pid
|
||||
if len(linedata) > 0:
|
||||
output_line['pid'] = linedata.pop(0)
|
||||
|
||||
# extended info is from
|
||||
if len(linedata) > 0 and linedata[0].startswith('('):
|
||||
output_line['from'] = linedata[0].replace('(', '').replace(')', '')
|
||||
|
||||
# else, extended info is comment
|
||||
elif len(linedata) > 0:
|
||||
output_line['comment'] = ' '.join(linedata)
|
||||
|
||||
raw_output.append(output_line)
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
120
jc/parsers/xml.py
Normal file
120
jc/parsers/xml.py
Normal file
@@ -0,0 +1,120 @@
|
||||
"""jc - JSON CLI output utility XML Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --xml as the first argument if the piped input is coming from an XML file
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat cd_catalog.xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CATALOG>
|
||||
<CD>
|
||||
<TITLE>Empire Burlesque</TITLE>
|
||||
<ARTIST>Bob Dylan</ARTIST>
|
||||
<COUNTRY>USA</COUNTRY>
|
||||
<COMPANY>Columbia</COMPANY>
|
||||
<PRICE>10.90</PRICE>
|
||||
<YEAR>1985</YEAR>
|
||||
</CD>
|
||||
<CD>
|
||||
<TITLE>Hide your heart</TITLE>
|
||||
<ARTIST>Bonnie Tyler</ARTIST>
|
||||
<COUNTRY>UK</COUNTRY>
|
||||
<COMPANY>CBS Records</COMPANY>
|
||||
<PRICE>9.90</PRICE>
|
||||
<YEAR>1988</YEAR>
|
||||
</CD>
|
||||
...
|
||||
|
||||
$ cat cd_catalog.xml | jc --xml -p
|
||||
{
|
||||
"CATALOG": {
|
||||
"CD": [
|
||||
{
|
||||
"TITLE": "Empire Burlesque",
|
||||
"ARTIST": "Bob Dylan",
|
||||
"COUNTRY": "USA",
|
||||
"COMPANY": "Columbia",
|
||||
"PRICE": "10.90",
|
||||
"YEAR": "1985"
|
||||
},
|
||||
{
|
||||
"TITLE": "Hide your heart",
|
||||
"ARTIST": "Bonnie Tyler",
|
||||
"COUNTRY": "UK",
|
||||
"COMPANY": "CBS Records",
|
||||
"PRICE": "9.90",
|
||||
"YEAR": "1988"
|
||||
},
|
||||
...
|
||||
}
|
||||
"""
|
||||
import jc.utils
|
||||
import xmltodict
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'XML file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
details = 'Using the xmltodict library at https://github.com/martinblech/xmltodict'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
|
||||
|
||||
__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 representing an XML document:
|
||||
|
||||
{
|
||||
XML Document converted to a Dictionary
|
||||
See https://github.com/martinblech/xmltodict for details
|
||||
}
|
||||
"""
|
||||
|
||||
# No further processing
|
||||
return proc_data
|
||||
|
||||
|
||||
def parse(data, raw=False, quiet=False):
|
||||
"""
|
||||
Main text parsing function
|
||||
|
||||
Parameters:
|
||||
|
||||
data: (string) text data to parse
|
||||
raw: (boolean) output preprocessed JSON if True
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
"""
|
||||
if not quiet:
|
||||
jc.utils.compatibility(__name__, info.compatible)
|
||||
|
||||
if data:
|
||||
raw_output = xmltodict.parse(data)
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
137
jc/parsers/yaml.py
Normal file
137
jc/parsers/yaml.py
Normal file
@@ -0,0 +1,137 @@
|
||||
"""jc - JSON CLI output utility YAML Parser
|
||||
|
||||
Usage:
|
||||
|
||||
specify --yaml as the first argument if the piped input is coming from a YAML file
|
||||
|
||||
Compatibility:
|
||||
|
||||
'linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd'
|
||||
|
||||
Examples:
|
||||
|
||||
$ cat istio-mtls-permissive.yaml
|
||||
apiVersion: "authentication.istio.io/v1alpha1"
|
||||
kind: "Policy"
|
||||
metadata:
|
||||
name: "default"
|
||||
namespace: "default"
|
||||
spec:
|
||||
peers:
|
||||
- mtls: {}
|
||||
---
|
||||
apiVersion: "networking.istio.io/v1alpha3"
|
||||
kind: "DestinationRule"
|
||||
metadata:
|
||||
name: "default"
|
||||
namespace: "default"
|
||||
spec:
|
||||
host: "*.default.svc.cluster.local"
|
||||
trafficPolicy:
|
||||
tls:
|
||||
mode: ISTIO_MUTUAL
|
||||
|
||||
$ cat istio-mtls-permissive.yaml | jc --yaml -p
|
||||
[
|
||||
{
|
||||
"apiVersion": "authentication.istio.io/v1alpha1",
|
||||
"kind": "Policy",
|
||||
"metadata": {
|
||||
"name": "default",
|
||||
"namespace": "default"
|
||||
},
|
||||
"spec": {
|
||||
"peers": [
|
||||
{
|
||||
"mtls": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"apiVersion": "networking.istio.io/v1alpha3",
|
||||
"kind": "DestinationRule",
|
||||
"metadata": {
|
||||
"name": "default",
|
||||
"namespace": "default"
|
||||
},
|
||||
"spec": {
|
||||
"host": "*.default.svc.cluster.local",
|
||||
"trafficPolicy": {
|
||||
"tls": {
|
||||
"mode": "ISTIO_MUTUAL"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
"""
|
||||
import jc.utils
|
||||
from ruamel.yaml import YAML
|
||||
|
||||
|
||||
class info():
|
||||
version = '1.0'
|
||||
description = 'YAML file parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
details = 'Using the ruamel.yaml library at https://pypi.org/project/ruamel.yaml'
|
||||
|
||||
# compatible options: linux, darwin, cygwin, win32, aix, freebsd
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def process(proc_data):
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of dictionaries. Each dictionary represents a YAML document:
|
||||
|
||||
[
|
||||
{
|
||||
YAML Document converted to a Dictionary
|
||||
See https://pypi.org/project/ruamel.yaml for details
|
||||
}
|
||||
]
|
||||
"""
|
||||
|
||||
# No further processing
|
||||
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)
|
||||
|
||||
raw_output = []
|
||||
yaml = YAML(typ='safe')
|
||||
|
||||
for document in yaml.load_all(data):
|
||||
raw_output.append(document)
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return process(raw_output)
|
||||
9
setup.py
9
setup.py
@@ -5,12 +5,14 @@ with open('README.md', 'r') as f:
|
||||
|
||||
setuptools.setup(
|
||||
name='jc',
|
||||
version='1.6.1',
|
||||
version='1.8.0',
|
||||
author='Kelly Brazil',
|
||||
author_email='kellyjonbrazil@gmail.com',
|
||||
description='This tool serializes the output of popular command line tools to structured JSON output.',
|
||||
description='This tool serializes the output of popular command line tools and filetypes to structured JSON output.',
|
||||
install_requires=[
|
||||
'ifconfig-parser>=0.0.5'
|
||||
'ifconfig-parser>=0.0.5',
|
||||
'ruamel.yaml>=0.15.0',
|
||||
'xmltodict>=0.12.0'
|
||||
],
|
||||
license='MIT',
|
||||
long_description=long_description,
|
||||
@@ -18,6 +20,7 @@ setuptools.setup(
|
||||
python_requires='>=3.6',
|
||||
url='https://github.com/kellyjonbrazil/jc',
|
||||
packages=setuptools.find_packages(),
|
||||
include_package_data=True,
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
'jc=jc.cli:main'
|
||||
|
||||
1
tests/fixtures/centos-7.7/blkid-ip-multi.json
vendored
Normal file
1
tests/fixtures/centos-7.7/blkid-ip-multi.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[{"uuid": "3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM", "version": "LVM2 001", "type": "LVM2_member", "usage": "raid", "minimum_io_size": 512, "physical_sector_size": 512, "logical_sector_size": 512, "part_entry_scheme": "dos", "part_entry_type": "0x8e", "part_entry_number": 2, "part_entry_offset": 2099200, "part_entry_size": 39843840, "part_entry_disk": "8:0", "device": "/dev/sda2"}, {"uuid": "05d927bb-5875-49e3-ada1-7f46cb31c932", "type": "xfs", "usage": "filesystem", "minimum_io_size": 512, "physical_sector_size": 512, "logical_sector_size": 512, "part_entry_scheme": "dos", "part_entry_type": "0x83", "part_entry_flags": "0x80", "part_entry_number": 1, "part_entry_offset": 2048, "part_entry_size": 2097152, "part_entry_disk": "8:0", "device": "/dev/sda1"}]
|
||||
29
tests/fixtures/centos-7.7/blkid-ip-multi.out
vendored
Normal file
29
tests/fixtures/centos-7.7/blkid-ip-multi.out
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
DEVNAME=/dev/sda2
|
||||
UUID=3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM
|
||||
VERSION=LVM2 001
|
||||
TYPE=LVM2_member
|
||||
USAGE=raid
|
||||
MINIMUM_IO_SIZE=512
|
||||
PHYSICAL_SECTOR_SIZE=512
|
||||
LOGICAL_SECTOR_SIZE=512
|
||||
PART_ENTRY_SCHEME=dos
|
||||
PART_ENTRY_TYPE=0x8e
|
||||
PART_ENTRY_NUMBER=2
|
||||
PART_ENTRY_OFFSET=2099200
|
||||
PART_ENTRY_SIZE=39843840
|
||||
PART_ENTRY_DISK=8:0
|
||||
|
||||
DEVNAME=/dev/sda1
|
||||
UUID=05d927bb-5875-49e3-ada1-7f46cb31c932
|
||||
TYPE=xfs
|
||||
USAGE=filesystem
|
||||
MINIMUM_IO_SIZE=512
|
||||
PHYSICAL_SECTOR_SIZE=512
|
||||
LOGICAL_SECTOR_SIZE=512
|
||||
PART_ENTRY_SCHEME=dos
|
||||
PART_ENTRY_TYPE=0x83
|
||||
PART_ENTRY_FLAGS=0x80
|
||||
PART_ENTRY_NUMBER=1
|
||||
PART_ENTRY_OFFSET=2048
|
||||
PART_ENTRY_SIZE=2097152
|
||||
PART_ENTRY_DISK=8:0
|
||||
1
tests/fixtures/centos-7.7/blkid-ip-udev-multi.json
vendored
Normal file
1
tests/fixtures/centos-7.7/blkid-ip-udev-multi.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[{"id_fs_uuid": "3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM", "id_fs_uuid_enc": "3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM", "id_fs_version": "LVM2\\x20001", "id_fs_type": "LVM2_member", "id_fs_usage": "raid", "id_iolimit_minimum_io_size": 512, "id_iolimit_physical_sector_size": 512, "id_iolimit_logical_sector_size": 512, "id_part_entry_scheme": "dos", "id_part_entry_type": "0x8e", "id_part_entry_number": 2, "id_part_entry_offset": 2099200, "id_part_entry_size": 39843840, "id_part_entry_disk": "8:0"}, {"id_fs_uuid": "05d927bb-5875-49e3-ada1-7f46cb31c932", "id_fs_uuid_enc": "05d927bb-5875-49e3-ada1-7f46cb31c932", "id_fs_type": "xfs", "id_fs_usage": "filesystem", "id_iolimit_minimum_io_size": 512, "id_iolimit_physical_sector_size": 512, "id_iolimit_logical_sector_size": 512, "id_part_entry_scheme": "dos", "id_part_entry_type": "0x83", "id_part_entry_flags": "0x80", "id_part_entry_number": 1, "id_part_entry_offset": 2048, "id_part_entry_size": 2097152, "id_part_entry_disk": "8:0"}]
|
||||
29
tests/fixtures/centos-7.7/blkid-ip-udev-multi.out
vendored
Normal file
29
tests/fixtures/centos-7.7/blkid-ip-udev-multi.out
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
ID_FS_UUID=3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM
|
||||
ID_FS_UUID_ENC=3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM
|
||||
ID_FS_VERSION=LVM2\x20001
|
||||
ID_FS_TYPE=LVM2_member
|
||||
ID_FS_USAGE=raid
|
||||
ID_IOLIMIT_MINIMUM_IO_SIZE=512
|
||||
ID_IOLIMIT_PHYSICAL_SECTOR_SIZE=512
|
||||
ID_IOLIMIT_LOGICAL_SECTOR_SIZE=512
|
||||
ID_PART_ENTRY_SCHEME=dos
|
||||
ID_PART_ENTRY_TYPE=0x8e
|
||||
ID_PART_ENTRY_NUMBER=2
|
||||
ID_PART_ENTRY_OFFSET=2099200
|
||||
ID_PART_ENTRY_SIZE=39843840
|
||||
ID_PART_ENTRY_DISK=8:0
|
||||
|
||||
ID_FS_UUID=05d927bb-5875-49e3-ada1-7f46cb31c932
|
||||
ID_FS_UUID_ENC=05d927bb-5875-49e3-ada1-7f46cb31c932
|
||||
ID_FS_TYPE=xfs
|
||||
ID_FS_USAGE=filesystem
|
||||
ID_IOLIMIT_MINIMUM_IO_SIZE=512
|
||||
ID_IOLIMIT_PHYSICAL_SECTOR_SIZE=512
|
||||
ID_IOLIMIT_LOGICAL_SECTOR_SIZE=512
|
||||
ID_PART_ENTRY_SCHEME=dos
|
||||
ID_PART_ENTRY_TYPE=0x83
|
||||
ID_PART_ENTRY_FLAGS=0x80
|
||||
ID_PART_ENTRY_NUMBER=1
|
||||
ID_PART_ENTRY_OFFSET=2048
|
||||
ID_PART_ENTRY_SIZE=2097152
|
||||
ID_PART_ENTRY_DISK=8:0
|
||||
1
tests/fixtures/centos-7.7/blkid-ip-udev.json
vendored
Normal file
1
tests/fixtures/centos-7.7/blkid-ip-udev.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[{"id_fs_uuid": "05d927bb-5875-49e3-ada1-7f46cb31c932", "id_fs_uuid_enc": "05d927bb-5875-49e3-ada1-7f46cb31c932", "id_fs_type": "xfs", "id_fs_usage": "filesystem", "id_iolimit_minimum_io_size": 512, "id_iolimit_physical_sector_size": 512, "id_iolimit_logical_sector_size": 512, "id_part_entry_scheme": "dos", "id_part_entry_type": "0x83", "id_part_entry_flags": "0x80", "id_part_entry_number": 1, "id_part_entry_offset": 2048, "id_part_entry_size": 2097152, "id_part_entry_disk": "8:0"}]
|
||||
14
tests/fixtures/centos-7.7/blkid-ip-udev.out
vendored
Normal file
14
tests/fixtures/centos-7.7/blkid-ip-udev.out
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
ID_FS_UUID=05d927bb-5875-49e3-ada1-7f46cb31c932
|
||||
ID_FS_UUID_ENC=05d927bb-5875-49e3-ada1-7f46cb31c932
|
||||
ID_FS_TYPE=xfs
|
||||
ID_FS_USAGE=filesystem
|
||||
ID_IOLIMIT_MINIMUM_IO_SIZE=512
|
||||
ID_IOLIMIT_PHYSICAL_SECTOR_SIZE=512
|
||||
ID_IOLIMIT_LOGICAL_SECTOR_SIZE=512
|
||||
ID_PART_ENTRY_SCHEME=dos
|
||||
ID_PART_ENTRY_TYPE=0x83
|
||||
ID_PART_ENTRY_FLAGS=0x80
|
||||
ID_PART_ENTRY_NUMBER=1
|
||||
ID_PART_ENTRY_OFFSET=2048
|
||||
ID_PART_ENTRY_SIZE=2097152
|
||||
ID_PART_ENTRY_DISK=8:0
|
||||
1
tests/fixtures/centos-7.7/blkid-sda2.json
vendored
Normal file
1
tests/fixtures/centos-7.7/blkid-sda2.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[{"device": "/dev/sda2", "uuid": "3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM", "type": "LVM2_member"}]
|
||||
1
tests/fixtures/centos-7.7/blkid-sda2.out
vendored
Normal file
1
tests/fixtures/centos-7.7/blkid-sda2.out
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/dev/sda2: UUID="3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM" TYPE="LVM2_member"
|
||||
1
tests/fixtures/centos-7.7/blkid.json
vendored
Normal file
1
tests/fixtures/centos-7.7/blkid.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[{"device": "/dev/sda1", "uuid": "05d927bb-5875-49e3-ada1-7f46cb31c932", "type": "xfs"}, {"device": "/dev/sda2", "uuid": "3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM", "type": "LVM2_member"}, {"device": "/dev/mapper/centos-root", "uuid": "07d718ef-950c-4e5b-98e0-42a1147b77d9", "type": "xfs"}, {"device": "/dev/mapper/centos-swap", "uuid": "615eb89d-bcbf-46ad-80e3-c483ef5c931f", "type": "swap"}]
|
||||
4
tests/fixtures/centos-7.7/blkid.out
vendored
Normal file
4
tests/fixtures/centos-7.7/blkid.out
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/dev/sda1: UUID="05d927bb-5875-49e3-ada1-7f46cb31c932" TYPE="xfs"
|
||||
/dev/sda2: UUID="3klkIj-w1qk-DkJi-0XBJ-y3o7-i2Ac-vHqWBM" TYPE="LVM2_member"
|
||||
/dev/mapper/centos-root: UUID="07d718ef-950c-4e5b-98e0-42a1147b77d9" TYPE="xfs"
|
||||
/dev/mapper/centos-swap: UUID="615eb89d-bcbf-46ad-80e3-c483ef5c931f" TYPE="swap"
|
||||
1
tests/fixtures/centos-7.7/crontab-u.json
vendored
Normal file
1
tests/fixtures/centos-7.7/crontab-u.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"variables": [{"name": "MAILTO", "value": "root"}, {"name": "PATH", "value": "/sbin:/bin:/usr/sbin:/usr/bin"}, {"name": "SHELL", "value": "/bin/bash"}], "schedule": [{"minute": ["01"], "hour": ["*"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "user": "root", "command": "run-parts /etc/cron.hourly"}, {"occurrence": "hourly", "user": "root", "command": "/usr/local/bin/backup"}]}
|
||||
6
tests/fixtures/centos-7.7/crontab-u.out
vendored
Normal file
6
tests/fixtures/centos-7.7/crontab-u.out
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# Run the hourly jobs
|
||||
SHELL=/bin/bash
|
||||
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
||||
MAILTO=root
|
||||
@hourly root /usr/local/bin/backup
|
||||
01 * * * * root run-parts /etc/cron.hourly
|
||||
2
tests/fixtures/centos-7.7/crontab.json
vendored
2
tests/fixtures/centos-7.7/crontab.json
vendored
@@ -1 +1 @@
|
||||
{"variables": [{"name": "MAILTO", "value": "root"}, {"name": "PATH", "value": "/sbin:/bin:/usr/sbin:/usr/bin"}, {"name": "SHELL", "value": "/bin/bash"}], "schedule": [{"minute": ["*"], "hour": ["*"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/devdaily.com/bin/check-apache.sh"}, {"minute": ["5"], "hour": ["10-11", "22"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/devdaily.com/bin/mk-new-links.php"}, {"minute": ["30"], "hour": ["4/2"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/devdaily.com/bin/create-all-backups.sh"}, {"minute": ["5"], "hour": ["0", "4", "10", "16"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/devdaily.com/bin/create-cat-list.sh"}, {"minute": ["5"], "hour": ["0"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/devdaily.com/bin/resetContactForm.sh"}, {"minute": ["0", "20", "40"], "hour": ["*"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/bin/ads/freshMint.sh"}, {"minute": ["5", "25", "45"], "hour": ["*"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/bin/ads/greenTaffy.sh"}, {"minute": ["10", "30", "50"], "hour": ["*"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/bin/ads/raspberry.sh"}, {"minute": ["15", "35", "55"], "hour": ["*"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/bin/ads/robinsEgg.sh"}, {"occurrence": "yearly", "command": "/home/maverick/bin/annual-maintenance"}, {"occurrence": "reboot", "command": "/home/cleanup"}, {"occurrence": "monthly", "command": "/home/maverick/bin/tape-backup"}]}
|
||||
{"variables": [{"name": "MAILTO", "value": "root"}, {"name": "PATH", "value": "/sbin:/bin:/usr/sbin:/usr/bin"}, {"name": "SHELL", "value": "/bin/bash"}], "schedule": [{"minute": ["0"], "hour": ["*"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/usr/bin/wget -O - -q -t 1 http://localhost/cron.php"}, {"minute": ["*"], "hour": ["*"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/devdaily.com/bin/check-apache.sh"}, {"minute": ["5"], "hour": ["10-11", "22"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/devdaily.com/bin/mk-new-links.php"}, {"minute": ["30"], "hour": ["4/2"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/devdaily.com/bin/create-all-backups.sh"}, {"minute": ["5"], "hour": ["0", "4", "10", "16"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/devdaily.com/bin/create-cat-list.sh"}, {"minute": ["5"], "hour": ["0"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/devdaily.com/bin/resetContactForm.sh"}, {"minute": ["0", "20", "40"], "hour": ["*"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/bin/ads/freshMint.sh"}, {"minute": ["5", "25", "45"], "hour": ["*"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/bin/ads/greenTaffy.sh"}, {"minute": ["10", "30", "50"], "hour": ["*"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/bin/ads/raspberry.sh"}, {"minute": ["15", "35", "55"], "hour": ["*"], "day_of_month": ["*"], "month": ["*"], "day_of_week": ["*"], "command": "/var/www/bin/ads/robinsEgg.sh"}, {"occurrence": "yearly", "command": "/home/maverick/bin/annual-maintenance"}, {"occurrence": "reboot", "command": "/home/cleanup"}, {"occurrence": "monthly", "command": "/home/maverick/bin/tape-backup"}]}
|
||||
|
||||
1
tests/fixtures/centos-7.7/group.json
vendored
Normal file
1
tests/fixtures/centos-7.7/group.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[{"group_name": "root", "password": "x", "gid": 0, "members": []}, {"group_name": "bin", "password": "x", "gid": 1, "members": []}, {"group_name": "daemon", "password": "x", "gid": 2, "members": []}, {"group_name": "sys", "password": "x", "gid": 3, "members": []}, {"group_name": "adm", "password": "x", "gid": 4, "members": []}, {"group_name": "tty", "password": "x", "gid": 5, "members": []}, {"group_name": "disk", "password": "x", "gid": 6, "members": []}, {"group_name": "lp", "password": "x", "gid": 7, "members": []}, {"group_name": "mem", "password": "x", "gid": 8, "members": []}, {"group_name": "kmem", "password": "x", "gid": 9, "members": []}, {"group_name": "wheel", "password": "x", "gid": 10, "members": ["joeuser"]}, {"group_name": "cdrom", "password": "x", "gid": 11, "members": []}, {"group_name": "mail", "password": "x", "gid": 12, "members": ["postfix"]}, {"group_name": "man", "password": "x", "gid": 15, "members": []}, {"group_name": "dialout", "password": "x", "gid": 18, "members": []}, {"group_name": "floppy", "password": "x", "gid": 19, "members": []}, {"group_name": "games", "password": "x", "gid": 20, "members": []}, {"group_name": "tape", "password": "x", "gid": 33, "members": []}, {"group_name": "video", "password": "x", "gid": 39, "members": []}, {"group_name": "ftp", "password": "x", "gid": 50, "members": []}, {"group_name": "lock", "password": "x", "gid": 54, "members": []}, {"group_name": "audio", "password": "x", "gid": 63, "members": []}, {"group_name": "nobody", "password": "x", "gid": 99, "members": []}, {"group_name": "users", "password": "x", "gid": 100, "members": []}, {"group_name": "utmp", "password": "x", "gid": 22, "members": []}, {"group_name": "utempter", "password": "x", "gid": 35, "members": []}, {"group_name": "input", "password": "x", "gid": 999, "members": []}, {"group_name": "systemd-journal", "password": "x", "gid": 190, "members": []}, {"group_name": "systemd-network", "password": "x", "gid": 192, "members": []}, {"group_name": "dbus", "password": "x", "gid": 81, "members": []}, {"group_name": "polkitd", "password": "x", "gid": 998, "members": []}, {"group_name": "ssh_keys", "password": "x", "gid": 997, "members": []}, {"group_name": "sshd", "password": "x", "gid": 74, "members": []}, {"group_name": "postdrop", "password": "x", "gid": 90, "members": []}, {"group_name": "postfix", "password": "x", "gid": 89, "members": []}, {"group_name": "chrony", "password": "x", "gid": 996, "members": []}, {"group_name": "joeuser", "password": "x", "gid": 1000, "members": ["joeuser"]}, {"group_name": "cgred", "password": "x", "gid": 995, "members": []}, {"group_name": "dockerroot", "password": "x", "gid": 994, "members": []}]
|
||||
39
tests/fixtures/centos-7.7/group.out
vendored
Normal file
39
tests/fixtures/centos-7.7/group.out
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
root:x:0:
|
||||
bin:x:1:
|
||||
daemon:x:2:
|
||||
sys:x:3:
|
||||
adm:x:4:
|
||||
tty:x:5:
|
||||
disk:x:6:
|
||||
lp:x:7:
|
||||
mem:x:8:
|
||||
kmem:x:9:
|
||||
wheel:x:10:joeuser
|
||||
cdrom:x:11:
|
||||
mail:x:12:postfix
|
||||
man:x:15:
|
||||
dialout:x:18:
|
||||
floppy:x:19:
|
||||
games:x:20:
|
||||
tape:x:33:
|
||||
video:x:39:
|
||||
ftp:x:50:
|
||||
lock:x:54:
|
||||
audio:x:63:
|
||||
nobody:x:99:
|
||||
users:x:100:
|
||||
utmp:x:22:
|
||||
utempter:x:35:
|
||||
input:x:999:
|
||||
systemd-journal:x:190:
|
||||
systemd-network:x:192:
|
||||
dbus:x:81:
|
||||
polkitd:x:998:
|
||||
ssh_keys:x:997:
|
||||
sshd:x:74:
|
||||
postdrop:x:90:
|
||||
postfix:x:89:
|
||||
chrony:x:996:
|
||||
joeuser:x:1000:joeuser
|
||||
cgred:x:995:
|
||||
dockerroot:x:994:
|
||||
1
tests/fixtures/centos-7.7/gshadow.json
vendored
Normal file
1
tests/fixtures/centos-7.7/gshadow.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[{"group_name": "root", "password": "", "administrators": [], "members": []}, {"group_name": "bin", "password": "", "administrators": [], "members": []}, {"group_name": "daemon", "password": "", "administrators": [], "members": []}, {"group_name": "sys", "password": "", "administrators": [], "members": []}, {"group_name": "adm", "password": "", "administrators": [], "members": []}, {"group_name": "tty", "password": "", "administrators": [], "members": []}, {"group_name": "disk", "password": "", "administrators": [], "members": []}, {"group_name": "lp", "password": "", "administrators": [], "members": []}, {"group_name": "mem", "password": "", "administrators": [], "members": []}, {"group_name": "kmem", "password": "", "administrators": [], "members": []}, {"group_name": "wheel", "password": "", "administrators": [], "members": ["joeuser"]}, {"group_name": "cdrom", "password": "", "administrators": [], "members": []}, {"group_name": "mail", "password": "", "administrators": [], "members": ["postfix"]}, {"group_name": "man", "password": "", "administrators": [], "members": []}, {"group_name": "dialout", "password": "", "administrators": [], "members": []}, {"group_name": "floppy", "password": "", "administrators": [], "members": []}, {"group_name": "games", "password": "", "administrators": [], "members": []}, {"group_name": "tape", "password": "", "administrators": [], "members": []}, {"group_name": "video", "password": "", "administrators": [], "members": []}, {"group_name": "ftp", "password": "", "administrators": [], "members": []}, {"group_name": "lock", "password": "", "administrators": [], "members": []}, {"group_name": "audio", "password": "", "administrators": [], "members": []}, {"group_name": "nobody", "password": "", "administrators": [], "members": []}, {"group_name": "users", "password": "", "administrators": [], "members": []}, {"group_name": "utmp", "password": "!", "administrators": [], "members": []}, {"group_name": "utempter", "password": "!", "administrators": [], "members": []}, {"group_name": "input", "password": "!", "administrators": [], "members": []}, {"group_name": "systemd-journal", "password": "!", "administrators": [], "members": []}, {"group_name": "systemd-network", "password": "!", "administrators": [], "members": []}, {"group_name": "dbus", "password": "!", "administrators": [], "members": []}, {"group_name": "polkitd", "password": "!", "administrators": [], "members": []}, {"group_name": "ssh_keys", "password": "!", "administrators": [], "members": []}, {"group_name": "sshd", "password": "!", "administrators": [], "members": []}, {"group_name": "postdrop", "password": "!", "administrators": [], "members": []}, {"group_name": "postfix", "password": "!", "administrators": [], "members": []}, {"group_name": "chrony", "password": "!", "administrators": [], "members": []}, {"group_name": "joeuser", "password": "!!", "administrators": [], "members": ["joeuser"]}, {"group_name": "cgred", "password": "!", "administrators": [], "members": []}, {"group_name": "dockerroot", "password": "!", "administrators": [], "members": []}]
|
||||
39
tests/fixtures/centos-7.7/gshadow.out
vendored
Normal file
39
tests/fixtures/centos-7.7/gshadow.out
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
root:::
|
||||
bin:::
|
||||
daemon:::
|
||||
sys:::
|
||||
adm:::
|
||||
tty:::
|
||||
disk:::
|
||||
lp:::
|
||||
mem:::
|
||||
kmem:::
|
||||
wheel:::joeuser
|
||||
cdrom:::
|
||||
mail:::postfix
|
||||
man:::
|
||||
dialout:::
|
||||
floppy:::
|
||||
games:::
|
||||
tape:::
|
||||
video:::
|
||||
ftp:::
|
||||
lock:::
|
||||
audio:::
|
||||
nobody:::
|
||||
users:::
|
||||
utmp:!::
|
||||
utempter:!::
|
||||
input:!::
|
||||
systemd-journal:!::
|
||||
systemd-network:!::
|
||||
dbus:!::
|
||||
polkitd:!::
|
||||
ssh_keys:!::
|
||||
sshd:!::
|
||||
postdrop:!::
|
||||
postfix:!::
|
||||
chrony:!::
|
||||
joeuser:!!::joeuser
|
||||
cgred:!::
|
||||
dockerroot:!::
|
||||
2
tests/fixtures/centos-7.7/history.json
vendored
2
tests/fixtures/centos-7.7/history.json
vendored
File diff suppressed because one or more lines are too long
1
tests/fixtures/centos-7.7/id.json
vendored
Normal file
1
tests/fixtures/centos-7.7/id.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"uid": {"id": 1000, "name": "kbrazil"}, "gid": {"id": 1000, "name": "kbrazil"}, "groups": [{"id": 1000, "name": "kbrazil"}, {"id": 10, "name": "wheel"}], "context": {"user": "unconfined_u", "role": "unconfined_r", "type": "unconfined_t", "level": "s0-s0:c0.c1023"}}
|
||||
1
tests/fixtures/centos-7.7/id.out
vendored
Normal file
1
tests/fixtures/centos-7.7/id.out
vendored
Normal file
@@ -0,0 +1 @@
|
||||
uid=1000(kbrazil) gid=1000(kbrazil) groups=1000(kbrazil),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
|
||||
1
tests/fixtures/centos-7.7/last-w.json
vendored
Normal file
1
tests/fixtures/centos-7.7/last-w.json
vendored
Normal file
File diff suppressed because one or more lines are too long
69
tests/fixtures/centos-7.7/last-w.out
vendored
Normal file
69
tests/fixtures/centos-7.7/last-w.out
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
kbrazil ttyS0 Fri Feb 28 13:49 still logged in
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Fri Feb 28 12:56 - 14:54 (01:58)
|
||||
kbrazil ttyS0 Thu Feb 27 16:01 - crash (20:54)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Thu Feb 27 15:51 - 14:54 (23:02)
|
||||
kbrazil ttyS0 Thu Feb 27 10:50 - crash (05:01)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Wed Feb 26 20:05 - 14:54 (1+18:49)
|
||||
kbrazil ttyS0 Thu Feb 20 14:42 - crash (6+05:23)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Thu Feb 20 14:41 - 14:54 (8+00:12)
|
||||
kbrazil ttyS0 Mon Feb 17 17:48 - crash (2+20:52)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Mon Feb 17 17:48 - 14:54 (10+21:06)
|
||||
kbrazil ttyS0 Thu Feb 13 16:44 - crash (4+01:03)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Thu Feb 13 16:44 - 14:54 (14+22:10)
|
||||
kbrazil ttyS0 Wed Feb 5 14:23 - crash (8+02:20)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Wed Feb 5 11:43 - 14:54 (23+03:11)
|
||||
kbrazil ttyS0 Tue Feb 4 14:28 - crash (21:15)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Tue Feb 4 01:28 - 14:54 (24+13:26)
|
||||
kbrazil ttyS0 Mon Jan 13 17:28 - crash (21+07:59)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Mon Jan 13 16:16 - 14:54 (45+22:38)
|
||||
kbrazil ttyS0 Mon Dec 16 11:15 - crash (28+05:01)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Mon Dec 16 11:14 - 14:54 (74+03:40)
|
||||
kbrazil ttyS0 Wed Dec 4 21:41 - crash (11+13:33)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Wed Dec 4 21:40 - 14:54 (85+17:13)
|
||||
kbrazil pts/1 Sat Nov 16 14:40 - 14:40 (00:00)
|
||||
kbrazil pts/1 Sat Nov 16 14:39 - 14:39 (00:00)
|
||||
kbrazil pts/0 localhost Tue Nov 12 07:19 - crash (22+14:21)
|
||||
kbrazil ttyS0 Tue Nov 12 07:18 - crash (22+14:22)
|
||||
kbrazil pts/0 localhost Sun Nov 10 08:21 - 15:22 (1+07:01)
|
||||
kbrazil ttyS0 Sat Nov 9 10:34 - 07:16 (2+20:42)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Sat Nov 9 10:34 - 14:54 (111+04:20)
|
||||
kbrazil tty1 Fri Nov 8 07:49 - crash (1+02:45)
|
||||
kbrazil pts/0 192.168.71.1 Fri Nov 8 06:29 - crash (1+04:04)
|
||||
kbrazil ttyS0 Fri Nov 8 06:24 - crash (1+04:09)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Fri Nov 8 06:14 - 14:54 (112+08:40)
|
||||
kbrazil tty1 Sun Nov 3 12:20 - crash (4+17:54)
|
||||
kbrazil ttyS0 Sun Nov 3 11:04 - 11:05 (00:01)
|
||||
kbrazil pts/0 192.168.71.1 Sat Nov 2 19:26 - crash (5+11:47)
|
||||
kbrazil ttyS0 Fri Nov 1 15:14 - 11:03 (1+20:49)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Fri Nov 1 15:13 - 14:54 (119+00:41)
|
||||
kbrazil ttyS0 Fri Nov 1 11:16 - 11:36 (00:20)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Fri Nov 1 06:00 - 11:36 (05:36)
|
||||
kbrazil ttyS0 Tue Oct 29 18:17 - crash (2+11:43)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Tue Oct 29 18:16 - 11:36 (2+17:19)
|
||||
kbrazil pts/0 192.168.71.1 Sat Oct 26 09:53 - 15:13 (05:19)
|
||||
kbrazil ttyS0 Fri Oct 25 18:22 - crash (3+23:54)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Fri Oct 25 18:21 - 11:36 (6+17:14)
|
||||
kbrazil ttyS0 Fri Oct 25 17:14 - 18:21 (01:06)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Fri Oct 25 17:13 - 11:36 (6+18:22)
|
||||
kbrazil ttyS0 Fri Oct 25 15:43 - 17:13 (01:29)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Fri Oct 25 13:29 - 17:13 (03:44)
|
||||
kbrazil ttyS0 Mon Oct 21 13:19 - 19:22 (2+06:03)
|
||||
reboot system boot 3.10.0-1062.1.2.el7.x86_64 Mon Oct 21 13:17 - 19:22 (2+06:05)
|
||||
kbrazil ttyS0 Wed Oct 16 03:23 - crash (5+09:54)
|
||||
kbrazil ttyS0 Tue Oct 15 16:49 - 03:23 (10:34)
|
||||
kbrazil ttyS0 Tue Oct 15 10:39 - 16:48 (06:09)
|
||||
reboot system boot 3.10.0-957.27.2.el7.x86_64 Tue Oct 15 10:39 - 19:22 (8+08:43)
|
||||
kbrazil ttyS0 Thu Aug 15 16:05 - 16:05 (00:00)
|
||||
reboot system boot 3.10.0-957.27.2.el7.x86_64 Thu Aug 15 16:05 - 16:05 (00:00)
|
||||
reboot system boot 3.10.0-957.27.2.el7.x86_64 Thu Aug 15 16:00 - 16:05 (00:05)
|
||||
kbrazil ttyS0 Thu Aug 15 14:25 - crash (01:35)
|
||||
reboot system boot 3.10.0-957.27.2.el7.x86_64 Thu Aug 15 14:24 - 16:05 (01:41)
|
||||
kbrazil ttyS0 Thu Aug 15 11:58 - crash (02:25)
|
||||
reboot system boot 3.10.0-957.el7.x86_64 Thu Aug 15 11:58 - 16:05 (04:07)
|
||||
kbrazil ttyS0 Thu Aug 15 11:57 - 11:57 (00:00)
|
||||
reboot system boot 3.10.0-957.el7.x86_64 Thu Aug 15 11:57 - 16:05 (04:08)
|
||||
kbrazil pts/0 192.168.71.1 Thu Aug 15 10:58 - 11:56 (00:58)
|
||||
root tty1 Thu Aug 15 10:57 - 11:56 (00:59)
|
||||
reboot system boot 3.10.0-957.el7.x86_64 Thu Aug 15 10:57 - 11:56 (00:59)
|
||||
|
||||
wtmp begins Thu Aug 15 10:57:06 2019
|
||||
1
tests/fixtures/centos-7.7/last.json
vendored
Normal file
1
tests/fixtures/centos-7.7/last.json
vendored
Normal file
File diff suppressed because one or more lines are too long
69
tests/fixtures/centos-7.7/last.out
vendored
Normal file
69
tests/fixtures/centos-7.7/last.out
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
kbrazil ttyS0 Fri Feb 28 13:49 still logged in
|
||||
reboot system boot 3.10.0-1062.1.2. Fri Feb 28 12:56 - 14:52 (01:56)
|
||||
kbrazil ttyS0 Thu Feb 27 16:01 - crash (20:54)
|
||||
reboot system boot 3.10.0-1062.1.2. Thu Feb 27 15:51 - 14:52 (23:01)
|
||||
kbrazil ttyS0 Thu Feb 27 10:50 - crash (05:01)
|
||||
reboot system boot 3.10.0-1062.1.2. Wed Feb 26 20:05 - 14:52 (1+18:47)
|
||||
kbrazil ttyS0 Thu Feb 20 14:42 - crash (6+05:23)
|
||||
reboot system boot 3.10.0-1062.1.2. Thu Feb 20 14:41 - 14:52 (8+00:11)
|
||||
kbrazil ttyS0 Mon Feb 17 17:48 - crash (2+20:52)
|
||||
reboot system boot 3.10.0-1062.1.2. Mon Feb 17 17:48 - 14:52 (10+21:04)
|
||||
kbrazil ttyS0 Thu Feb 13 16:44 - crash (4+01:03)
|
||||
reboot system boot 3.10.0-1062.1.2. Thu Feb 13 16:44 - 14:52 (14+22:08)
|
||||
kbrazil ttyS0 Wed Feb 5 14:23 - crash (8+02:20)
|
||||
reboot system boot 3.10.0-1062.1.2. Wed Feb 5 11:43 - 14:52 (23+03:09)
|
||||
kbrazil ttyS0 Tue Feb 4 14:28 - crash (21:15)
|
||||
reboot system boot 3.10.0-1062.1.2. Tue Feb 4 01:28 - 14:52 (24+13:24)
|
||||
kbrazil ttyS0 Mon Jan 13 17:28 - crash (21+07:59)
|
||||
reboot system boot 3.10.0-1062.1.2. Mon Jan 13 16:16 - 14:52 (45+22:36)
|
||||
kbrazil ttyS0 Mon Dec 16 11:15 - crash (28+05:01)
|
||||
reboot system boot 3.10.0-1062.1.2. Mon Dec 16 11:14 - 14:52 (74+03:38)
|
||||
kbrazil ttyS0 Wed Dec 4 21:41 - crash (11+13:33)
|
||||
reboot system boot 3.10.0-1062.1.2. Wed Dec 4 21:40 - 14:52 (85+17:12)
|
||||
kbrazil pts/1 Sat Nov 16 14:40 - 14:40 (00:00)
|
||||
kbrazil pts/1 Sat Nov 16 14:39 - 14:39 (00:00)
|
||||
kbrazil pts/0 localhost Tue Nov 12 07:19 - crash (22+14:21)
|
||||
kbrazil ttyS0 Tue Nov 12 07:18 - crash (22+14:22)
|
||||
kbrazil pts/0 localhost Sun Nov 10 08:21 - 15:22 (1+07:01)
|
||||
kbrazil ttyS0 Sat Nov 9 10:34 - 07:16 (2+20:42)
|
||||
reboot system boot 3.10.0-1062.1.2. Sat Nov 9 10:34 - 14:52 (111+04:18)
|
||||
kbrazil tty1 Fri Nov 8 07:49 - crash (1+02:45)
|
||||
kbrazil pts/0 192.168.71.1 Fri Nov 8 06:29 - crash (1+04:04)
|
||||
kbrazil ttyS0 Fri Nov 8 06:24 - crash (1+04:09)
|
||||
reboot system boot 3.10.0-1062.1.2. Fri Nov 8 06:14 - 14:52 (112+08:38)
|
||||
kbrazil tty1 Sun Nov 3 12:20 - crash (4+17:54)
|
||||
kbrazil ttyS0 Sun Nov 3 11:04 - 11:05 (00:01)
|
||||
kbrazil pts/0 192.168.71.1 Sat Nov 2 19:26 - crash (5+11:47)
|
||||
kbrazil ttyS0 Fri Nov 1 15:14 - 11:03 (1+20:49)
|
||||
reboot system boot 3.10.0-1062.1.2. Fri Nov 1 15:13 - 14:52 (119+00:39)
|
||||
kbrazil ttyS0 Fri Nov 1 11:16 - 11:36 (00:20)
|
||||
reboot system boot 3.10.0-1062.1.2. Fri Nov 1 06:00 - 11:36 (05:36)
|
||||
kbrazil ttyS0 Tue Oct 29 18:17 - crash (2+11:43)
|
||||
reboot system boot 3.10.0-1062.1.2. Tue Oct 29 18:16 - 11:36 (2+17:19)
|
||||
kbrazil pts/0 192.168.71.1 Sat Oct 26 09:53 - 15:13 (05:19)
|
||||
kbrazil ttyS0 Fri Oct 25 18:22 - crash (3+23:54)
|
||||
reboot system boot 3.10.0-1062.1.2. Fri Oct 25 18:21 - 11:36 (6+17:14)
|
||||
kbrazil ttyS0 Fri Oct 25 17:14 - 18:21 (01:06)
|
||||
reboot system boot 3.10.0-1062.1.2. Fri Oct 25 17:13 - 11:36 (6+18:22)
|
||||
kbrazil ttyS0 Fri Oct 25 15:43 - 17:13 (01:29)
|
||||
reboot system boot 3.10.0-1062.1.2. Fri Oct 25 13:29 - 17:13 (03:44)
|
||||
kbrazil ttyS0 Mon Oct 21 13:19 - 19:22 (2+06:03)
|
||||
reboot system boot 3.10.0-1062.1.2. Mon Oct 21 13:17 - 19:22 (2+06:05)
|
||||
kbrazil ttyS0 Wed Oct 16 03:23 - crash (5+09:54)
|
||||
kbrazil ttyS0 Tue Oct 15 16:49 - 03:23 (10:34)
|
||||
kbrazil ttyS0 Tue Oct 15 10:39 - 16:48 (06:09)
|
||||
reboot system boot 3.10.0-957.27.2. Tue Oct 15 10:39 - 19:22 (8+08:43)
|
||||
kbrazil ttyS0 Thu Aug 15 16:05 - 16:05 (00:00)
|
||||
reboot system boot 3.10.0-957.27.2. Thu Aug 15 16:05 - 16:05 (00:00)
|
||||
reboot system boot 3.10.0-957.27.2. Thu Aug 15 16:00 - 16:05 (00:05)
|
||||
kbrazil ttyS0 Thu Aug 15 14:25 - crash (01:35)
|
||||
reboot system boot 3.10.0-957.27.2. Thu Aug 15 14:24 - 16:05 (01:41)
|
||||
kbrazil ttyS0 Thu Aug 15 11:58 - crash (02:25)
|
||||
reboot system boot 3.10.0-957.el7.x Thu Aug 15 11:58 - 16:05 (04:07)
|
||||
kbrazil ttyS0 Thu Aug 15 11:57 - 11:57 (00:00)
|
||||
reboot system boot 3.10.0-957.el7.x Thu Aug 15 11:57 - 16:05 (04:08)
|
||||
kbrazil pts/0 192.168.71.1 Thu Aug 15 10:58 - 11:56 (00:58)
|
||||
root tty1 Thu Aug 15 10:57 - 11:56 (00:59)
|
||||
reboot system boot 3.10.0-957.el7.x Thu Aug 15 10:57 - 11:56 (00:59)
|
||||
|
||||
wtmp begins Thu Aug 15 10:57:06 2019
|
||||
1
tests/fixtures/centos-7.7/lastb.json
vendored
Normal file
1
tests/fixtures/centos-7.7/lastb.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[{"user": "kbrazil", "tty": "ttyS0", "hostname": null, "login": "Fri Feb 28 13:49", "logout": "13:49", "duration": "00:00"}, {"user": "kbrazil", "tty": "ssh:notty", "hostname": "192.168.71.1", "login": "Thu Feb 27 10:13", "logout": "10:13", "duration": "00:00"}, {"user": "kbrazil", "tty": "ttyS0", "hostname": null, "login": "Thu Feb 20 14:41", "logout": "14:41", "duration": "00:00"}, {"user": "kbrazil", "tty": "ttyS0", "hostname": null, "login": "Mon Feb 17 17:48", "logout": "17:48", "duration": "00:00"}]
|
||||
6
tests/fixtures/centos-7.7/lastb.out
vendored
Normal file
6
tests/fixtures/centos-7.7/lastb.out
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
kbrazil ttyS0 Fri Feb 28 13:49 - 13:49 (00:00)
|
||||
kbrazil ssh:notty 192.168.71.1 Thu Feb 27 10:13 - 10:13 (00:00)
|
||||
kbrazil ttyS0 Thu Feb 20 14:41 - 14:41 (00:00)
|
||||
kbrazil ttyS0 Mon Feb 17 17:48 - 17:48 (00:00)
|
||||
|
||||
btmp begins Mon Feb 17 17:48:53 2020
|
||||
1
tests/fixtures/centos-7.7/ls-R-newlines.json
vendored
Normal file
1
tests/fixtures/centos-7.7/ls-R-newlines.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
[{"filename": "systemd-private-016de60725a3426792b93fc9f120b8f0-chronyd.service-oZqq4u", "parent": "."}, {"filename": "systemd-private-a30a5a178daa4042b42dfaf5ff9e5f68-chronyd.service-a1tpxv", "parent": "."}, {"filename": "systemd-private-af69d7360f3e40cfa947358c0fb5a6f8-chronyd.service-T3MQ4j", "parent": "."}, {"filename": "tmp.CvALl2jE6u", "parent": "."}, {"filename": "tmp.e7AlxSxY5a", "parent": "."}, {"filename": "tmp.uXm9yegjwj", "parent": "."}, {"filename": "a regular filename", "parent": "./lstest"}, {"filename": "this file has", "parent": "./lstest"}, {"filename": "a combination", "parent": "./lstest"}, {"filename": "of everything", "parent": "./lstest"}, {"filename": "this file has", "parent": "./lstest"}, {"filename": "a newline inside", "parent": "./lstest"}, {"filename": "this file has", "parent": "./lstest"}, {"filename": "four contiguous newlines inside", "parent": "./lstest"}, {"filename": "this file", "parent": "./lstest"}, {"filename": "has", "parent": "./lstest"}, {"filename": "six", "parent": "./lstest"}, {"filename": "newlines", "parent": "./lstest"}, {"filename": "within", "parent": "./lstest"}, {"filename": "this file starts with four newlines", "parent": "./lstest"}, {"filename": "this file starts with one newline", "parent": "./lstest"}]
|
||||
43
tests/fixtures/centos-7.7/ls-R-newlines.out
vendored
Normal file
43
tests/fixtures/centos-7.7/ls-R-newlines.out
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
.:
|
||||
lstest
|
||||
systemd-private-016de60725a3426792b93fc9f120b8f0-chronyd.service-oZqq4u
|
||||
systemd-private-a30a5a178daa4042b42dfaf5ff9e5f68-chronyd.service-a1tpxv
|
||||
systemd-private-af69d7360f3e40cfa947358c0fb5a6f8-chronyd.service-T3MQ4j
|
||||
tmp.CvALl2jE6u
|
||||
tmp.e7AlxSxY5a
|
||||
tmp.uXm9yegjwj
|
||||
|
||||
./lstest:
|
||||
a regular filename
|
||||
|
||||
|
||||
this file has
|
||||
a combination
|
||||
|
||||
|
||||
of everything
|
||||
|
||||
|
||||
|
||||
|
||||
this file has
|
||||
a newline inside
|
||||
this file has
|
||||
|
||||
|
||||
|
||||
four contiguous newlines inside
|
||||
this file
|
||||
has
|
||||
six
|
||||
|
||||
newlines
|
||||
|
||||
within
|
||||
|
||||
|
||||
|
||||
|
||||
this file starts with four newlines
|
||||
|
||||
this file starts with one newline
|
||||
1
tests/fixtures/centos-7.7/ls-R.json
vendored
Normal file
1
tests/fixtures/centos-7.7/ls-R.json
vendored
Normal file
File diff suppressed because one or more lines are too long
5089
tests/fixtures/centos-7.7/ls-R.out
vendored
Normal file
5089
tests/fixtures/centos-7.7/ls-R.out
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
tests/fixtures/centos-7.7/ls-alR.json
vendored
Normal file
1
tests/fixtures/centos-7.7/ls-alR.json
vendored
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user