mirror of
https://github.com/kellyjonbrazil/jc.git
synced 2026-04-03 17:44:07 +02:00
Compare commits
101 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
776ee66bae | ||
|
|
9bf2cd0691 | ||
|
|
fec74cf305 | ||
|
|
d3d7fbca61 | ||
|
|
550862a415 | ||
|
|
1763b530da | ||
|
|
8307150cae | ||
|
|
d2223c45d1 | ||
|
|
472ee5e295 | ||
|
|
1d0aebd836 | ||
|
|
8240626043 | ||
|
|
2cd14235c8 | ||
|
|
f774513554 | ||
|
|
388da9f003 | ||
|
|
fa18243491 | ||
|
|
5df1c1702b | ||
|
|
b6557802f4 | ||
|
|
15e3a511b6 | ||
|
|
08fbde0e8f | ||
|
|
28ebb4e8dd | ||
|
|
04fda57cbe | ||
|
|
b24495136c | ||
|
|
7d3fa55571 | ||
|
|
a76b5db8db | ||
|
|
667dd01ac7 | ||
|
|
559bee962a | ||
|
|
9f977d06e0 | ||
|
|
f67a916940 | ||
|
|
8a1308948f | ||
|
|
4e130d11a3 | ||
|
|
51aa5b268f | ||
|
|
6869133f53 | ||
|
|
ad3d88e47f | ||
|
|
6d29f8ba74 | ||
|
|
c7cb89e91d | ||
|
|
27f5118abd | ||
|
|
ac5a6e516d | ||
|
|
5d5bfbc1d1 | ||
|
|
9f4ba80000 | ||
|
|
c21c334b73 | ||
|
|
14093d9d43 | ||
|
|
176ca2f75d | ||
|
|
cfb71c7dad | ||
|
|
722eab83b1 | ||
|
|
d30edb2dae | ||
|
|
cba461ce8a | ||
|
|
f876505e25 | ||
|
|
5b9fcd5852 | ||
|
|
8a122cd9e1 | ||
|
|
557e68225c | ||
|
|
dc0947b87e | ||
|
|
af2c06cd28 | ||
|
|
67a4c6f797 | ||
|
|
0d1c857410 | ||
|
|
c7684dc94d | ||
|
|
a247572f64 | ||
|
|
306111303a | ||
|
|
c12b48537a | ||
|
|
0bf69713ab | ||
|
|
c05f1475ed | ||
|
|
416c262f02 | ||
|
|
40a5976f11 | ||
|
|
dc582fbec8 | ||
|
|
7047f0a449 | ||
|
|
d7a884a567 | ||
|
|
28de57792c | ||
|
|
a230cdbd21 | ||
|
|
251a261679 | ||
|
|
3baef254fd | ||
|
|
9e69e928b2 | ||
|
|
6eb595d2ca | ||
|
|
acf07a5144 | ||
|
|
7f53c58057 | ||
|
|
a069dc4855 | ||
|
|
febf544202 | ||
|
|
f2dd7b8815 | ||
|
|
d758e37fe3 | ||
|
|
9bc02a5623 | ||
|
|
eb0ec265d0 | ||
|
|
1f236dc02a | ||
|
|
86c279cbb2 | ||
|
|
4a7f1bed3a | ||
|
|
a730ae18c8 | ||
|
|
930bf439c0 | ||
|
|
f5f3133b87 | ||
|
|
cbca96de84 | ||
|
|
4d8ae3f124 | ||
|
|
653127431d | ||
|
|
22acef3765 | ||
|
|
0d5bf11f0d | ||
|
|
a824ccaff3 | ||
|
|
97ac965ba5 | ||
|
|
3e7f284df5 | ||
|
|
5c749fe26f | ||
|
|
aa48b46f48 | ||
|
|
6eaa4ae176 | ||
|
|
60c330b342 | ||
|
|
fdeb994121 | ||
|
|
65ed92fe7b | ||
|
|
9c8730786b | ||
|
|
7608823ea7 |
41
CHANGELOG
41
CHANGELOG
@@ -1,31 +1,50 @@
|
||||
jc changelog
|
||||
|
||||
20220531 v1.20.0
|
||||
- Add YAML output option with `-y`
|
||||
- Add `top -b` standard and streaming parsers tested on linux
|
||||
- Add `plugin_parser_count`, `standard_parser_count`, and `streaming_parser_count`
|
||||
keys to `jc -a` output
|
||||
- Add `is_compatible` function to the `utils` module
|
||||
- Fix `pip-show` parser for packages with a multi-line license field
|
||||
- Fix ASCII Table parser for cases where centered headers cause mis-aligned fields
|
||||
|
||||
20220513 v1.19.0
|
||||
- Add `chage --list` command parser tested on linux
|
||||
- Add `git log` command streaming parser
|
||||
- Fix `git log` standard parser for corner-cases where hash values are in messages
|
||||
- Fix `df` command parser for rare instances when a newline is found at the end
|
||||
- Allow jc to pip install on unsupported python version 3.6
|
||||
- Fix `asciitable-m` parser to skip some rows that contain column separator
|
||||
characters in cell data. A warning message will be printed to STDERR
|
||||
unless `-q` or `quiet=True` is used.
|
||||
|
||||
20220427 v1.18.8
|
||||
- Fix update-alternatives --query parser for cases where `slaves` are not present
|
||||
- Fix `update-alternatives --query` parser for cases where `slaves` are not present
|
||||
- Fix UnicodeEncodeError on some systems where LANG=C is set and unicode
|
||||
characters are in the output
|
||||
- Update history parser: do not drop non-ASCII characters if the system
|
||||
- Update `history` parser: do not drop non-ASCII characters if the system
|
||||
is configured for UTF-8 encoding
|
||||
- Enhance "magic syntax" to always use UTF-8 encoding
|
||||
|
||||
20220425 v1.18.7
|
||||
- Add git log command parser
|
||||
- Add update-alternatives --query parser
|
||||
- Add update-alternatives --get-selections parser
|
||||
- Add `git log` command parser
|
||||
- Add `update-alternatives --query` parser
|
||||
- Add `update-alternatives --get-selections` parser
|
||||
- Fix key/value and ini parsers to allow duplicate keys
|
||||
- Fix yaml file parser for files including timestamp objects
|
||||
- Update xrandr parser: add a 'rotation' field
|
||||
- Update `xrandr` parser: add a 'rotation' field
|
||||
- Fix failing tests by moving template files
|
||||
- Add python interpreter version and path to -v and -a output
|
||||
|
||||
20220325 v1.18.6
|
||||
- Add pidstat command parser tested on linux
|
||||
- Add pidstat command streaming parser tested on linux
|
||||
- Add mpstat command parser tested on linux
|
||||
- Add mpstat command streaming parser tested on linux
|
||||
- Add `pidstat` command parser tested on linux
|
||||
- Add `pidstat` command streaming parser tested on linux
|
||||
- Add `mpstat` command parser tested on linux
|
||||
- Add `mpstat` command streaming parser tested on linux
|
||||
- Add single-line ASCII and Unicode table parser
|
||||
- Add multi-line ASCII and Unicode table parser
|
||||
- Add documentation option to parser_info() and all_parser_info()
|
||||
- Add documentation option to `parser_info()` and `all_parser_info()`
|
||||
|
||||
20220305 v1.18.5
|
||||
- Fix date parser to ensure AM/PM period string is always uppercase
|
||||
|
||||
62
EXAMPLES.md
62
EXAMPLES.md
@@ -265,6 +265,21 @@ blkid -o udev -ip /dev/sda2 | jc --blkid -p # or: jc -p blkid -o udev
|
||||
}
|
||||
]
|
||||
```
|
||||
### chage --list
|
||||
```bash
|
||||
chage --list joeuser | jc --chage -p # or: jc -p chage --list joeuser
|
||||
```
|
||||
```json
|
||||
{
|
||||
"password_last_changed": "never",
|
||||
"password_expires": "never",
|
||||
"password_inactive": "never",
|
||||
"account_expires": "never",
|
||||
"min_days_between_password_change": 0,
|
||||
"max_days_between_password_change": 99999,
|
||||
"warning_days_before_password_expires": 7
|
||||
}
|
||||
```
|
||||
### cksum
|
||||
```bash
|
||||
cksum * | jc --cksum -p # or: jc -p cksum *
|
||||
@@ -1059,6 +1074,53 @@ cat /etc/fstab | jc --fstab -p
|
||||
}
|
||||
]
|
||||
```
|
||||
### git log
|
||||
```bash
|
||||
git log --stat | jc --git-log -p or: jc -p git log --stat
|
||||
```
|
||||
```json
|
||||
[
|
||||
{
|
||||
"commit": "728d882ed007b3c8b785018874a0eb06e1143b66",
|
||||
"author": "Kelly Brazil",
|
||||
"author_email": "kellyjonbrazil@gmail.com",
|
||||
"date": "Wed Apr 20 09:50:19 2022 -0400",
|
||||
"stats": {
|
||||
"files_changed": 2,
|
||||
"insertions": 90,
|
||||
"deletions": 12,
|
||||
"files": [
|
||||
"docs/parsers/git_log.md",
|
||||
"jc/parsers/git_log.py"
|
||||
]
|
||||
},
|
||||
"message": "add timestamp docs and examples",
|
||||
"epoch": 1650462619,
|
||||
"epoch_utc": null
|
||||
},
|
||||
{
|
||||
"commit": "b53e42aca623181aa9bc72194e6eeef1e9a3a237",
|
||||
"author": "Kelly Brazil",
|
||||
"author_email": "kellyjonbrazil@gmail.com",
|
||||
"date": "Wed Apr 20 09:44:42 2022 -0400",
|
||||
"stats": {
|
||||
"files_changed": 5,
|
||||
"insertions": 29,
|
||||
"deletions": 6,
|
||||
"files": [
|
||||
"docs/parsers/git_log.md",
|
||||
"docs/utils.md",
|
||||
"jc/parsers/git_log.py",
|
||||
"jc/utils.py",
|
||||
"man/jc.1"
|
||||
]
|
||||
},
|
||||
"message": "add calculated timestamp",
|
||||
"epoch": 1650462282,
|
||||
"epoch_utc": null
|
||||
}
|
||||
]
|
||||
```
|
||||
### /etc/group file
|
||||
```bash
|
||||
cat /etc/group | jc --group -p
|
||||
|
||||
255
README.md
255
README.md
@@ -111,13 +111,13 @@ pip3 install jc
|
||||
| Debian/Ubuntu linux | `apt-get install jc` |
|
||||
| Fedora linux | `dnf install jc` |
|
||||
| openSUSE linux | `zypper install jc` |
|
||||
| Archlinux User Repositories (AUR) | `paru -S jc` or `aura -A jc` or `yay -S jc` |
|
||||
| Archlinux Community Repository | `paru -S jc` or `aura -S jc` or `yay -S jc` |
|
||||
| NixOS linux | `nix-env -iA nixpkgs.jc` or `nix-env -iA nixos.jc` |
|
||||
| Guix System linux | `guix install jc` |
|
||||
| Gentoo Linux | `emerge dev-python/jc` |
|
||||
| macOS | `brew install jc` |
|
||||
| FreeBSD | `portsnap fetch update && cd /usr/ports/textproc/py-jc && make install clean` |
|
||||
| Ansible filter plugin | `ansible-galaxy collection install community.general` |
|
||||
| Gentoo Linux | `emerge dev-python/jc` |
|
||||
|
||||
> For more OS Packages, see https://repology.org/project/jc/versions.
|
||||
|
||||
@@ -144,108 +144,114 @@ option.
|
||||
|
||||
### Parsers
|
||||
|
||||
- `--acpi` enables the `acpi` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/acpi))
|
||||
- `--airport` enables the `airport -I` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/airport))
|
||||
- `--airport-s` enables the `airport -s` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/airport_s))
|
||||
- `--arp` enables the `arp` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/arp))
|
||||
- `--asciitable` enables the ASCII and Unicode table parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable))
|
||||
- `--asciitable-m` enables the multi-line ASCII and Unicode table parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable_m))
|
||||
- `--blkid` enables the `blkid` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/blkid))
|
||||
- `--cksum` enables the `cksum` and `sum` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/cksum))
|
||||
- `--crontab` enables the `crontab` command and file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab))
|
||||
- `--crontab-u` enables the `crontab` file parser with user support ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab_u))
|
||||
- `--csv` enables the CSV file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/csv))
|
||||
- `--csv-s` enables the CSV file streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/csv_s))
|
||||
- `--date` enables the `date` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/date))
|
||||
- `--df` enables the `df` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/df))
|
||||
- `--dig` enables the `dig` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/dig))
|
||||
- `--dir` enables the `dir` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/dir))
|
||||
- `--dmidecode` enables the `dmidecode` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/dmidecode))
|
||||
- `--dpkg-l` enables the `dpkg -l` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/dpkg_l))
|
||||
- `--du` enables the `du` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/du))
|
||||
- `--env` enables the `env` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/env))
|
||||
- `--file` enables the `file` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/file))
|
||||
- `--finger` enables the `finger` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/finger))
|
||||
- `--free` enables the `free` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/free))
|
||||
- `--fstab` enables the `/etc/fstab` file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/fstab))
|
||||
- `--git-log` enables the `git log` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/git_log))
|
||||
- `--group` enables the `/etc/group` file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/group))
|
||||
- `--gshadow` enables the `/etc/gshadow` file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/gshadow))
|
||||
- `--hash` enables the `hash` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/hash))
|
||||
- `--hashsum` enables the hashsum command parser (`md5sum`, `shasum`, etc.) ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/hashsum))
|
||||
- `--hciconfig` enables the `hciconfig` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/hciconfig))
|
||||
- `--history` enables the `history` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/history))
|
||||
- `--hosts` enables the `/etc/hosts` file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/hosts))
|
||||
- `--id` enables the `id` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/id))
|
||||
- `--ifconfig` enables the `ifconfig` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ifconfig))
|
||||
- `--ini` enables the INI file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ini))
|
||||
- `--iostat` enables the `iostat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat))
|
||||
- `--iostat-s` enables the `iostat` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat_s))
|
||||
- `--iptables` enables the `iptables` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/iptables))
|
||||
- `--iw-scan` enables the `iw dev [device] scan` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/iw_scan))
|
||||
- `--jar-manifest` enables the MANIFEST.MF file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/jar_manifest))
|
||||
- `--jobs` enables the `jobs` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/jobs))
|
||||
- `--kv` enables the Key/Value file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/kv))
|
||||
- `--last` enables the `last` and `lastb` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/last))
|
||||
- `--ls` enables the `ls` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ls))
|
||||
- `--ls-s` enables the `ls` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ls_s))
|
||||
- `--lsblk` enables the `lsblk` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/lsblk))
|
||||
- `--lsmod` enables the `lsmod` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/lsmod))
|
||||
- `--lsof` enables the `lsof` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/lsof))
|
||||
- `--lsusb` enables the `lsusb` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/lsusb))
|
||||
- `--mount` enables the `mount` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/mount))
|
||||
- `--mpstat` enables the `mpstat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat))
|
||||
- `--mpstat-s` enables the `mpstat` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat_s))
|
||||
- `--netstat` enables the `netstat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/netstat))
|
||||
- `--nmcli` enables the `nmcli` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/nmcli))
|
||||
- `--ntpq` enables the `ntpq -p` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ntpq))
|
||||
- `--passwd` enables the `/etc/passwd` file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/passwd))
|
||||
- `--pidstat` enables the `pidstat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat))
|
||||
- `--pidstat-s` enables the `pidstat` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat_s))
|
||||
- `--ping` enables the `ping` and `ping6` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ping))
|
||||
- `--ping-s` enables the `ping` and `ping6` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ping_s))
|
||||
- `--pip-list` enables the `pip list` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_list))
|
||||
- `--pip-show` enables the `pip show` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_show))
|
||||
- `--ps` enables the `ps` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ps))
|
||||
- `--route` enables the `route` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/route))
|
||||
- `--rpm-qi` enables the `rpm -qi` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/rpm_qi))
|
||||
- `--rsync` enables the `rsync` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync))
|
||||
- `--rsync-s` enables the `rsync` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync_s))
|
||||
- `--sfdisk` enables the `sfdisk` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/sfdisk))
|
||||
- `--shadow` enables the `/etc/shadow` file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/shadow))
|
||||
- `--ss` enables the `ss` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ss))
|
||||
- `--stat` enables the `stat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/stat))
|
||||
- `--stat-s` enables the `stat` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/stat_s))
|
||||
- `--sysctl` enables the `sysctl` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/sysctl))
|
||||
- `--systemctl` enables the `systemctl` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl))
|
||||
- `--systemctl-lj` enables the `systemctl list-jobs` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_lj))
|
||||
- `--systemctl-ls` enables the `systemctl list-sockets` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_ls))
|
||||
- `--systemctl-luf` enables the `systemctl list-unit-files` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_luf))
|
||||
- `--systeminfo` enables the `systeminfo` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/systeminfo))
|
||||
- `--time` enables the `/usr/bin/time` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/time))
|
||||
- `--timedatectl` enables the `timedatectl status` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/timedatectl))
|
||||
- `--tracepath` enables the `tracepath` and `tracepath6` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/tracepath))
|
||||
- `--traceroute` enables the `traceroute` and `traceroute6` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/traceroute))
|
||||
- `--ufw` enables the `ufw status` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw))
|
||||
- `--ufw-appinfo` enables the `ufw app info [application]` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw_appinfo))
|
||||
- `--uname` enables the `uname -a` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/uname))
|
||||
- `--update-alt-gs` enables the `update-alternatives --get-selections` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/update_alt_gs))
|
||||
- `--update-alt-q` enables the `update-alternatives --query` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/update_alt_q))
|
||||
- `--upower` enables the `upower` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/upower))
|
||||
- `--uptime` enables the `uptime` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/uptime))
|
||||
- `--vmstat` enables the `vmstat` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/vmstat))
|
||||
- `--vmstat-s` enables the `vmstat` command streaming parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/vmstat_s))
|
||||
- `--w` enables the `w` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/w))
|
||||
- `--wc` enables the `wc` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/wc))
|
||||
- `--who` enables the `who` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/who))
|
||||
- `--xml` enables the XML file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/xml))
|
||||
- `--xrandr` enables the `xrandr` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/xrandr))
|
||||
- `--yaml` enables the YAML file parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/yaml))
|
||||
- `--zipinfo` enables the `zipinfo` command parser ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/zipinfo))
|
||||
| Argument | Command or Filetype | Documentation |
|
||||
|-------------------|---------------------------------------------------------|-------------------------------------------------------------------------|
|
||||
| ` --acpi` | `acpi` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/acpi) |
|
||||
| ` --airport` | `airport -I` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/airport) |
|
||||
| ` --airport-s` | `airport -s` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/airport_s) |
|
||||
| ` --arp` | `arp` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/arp) |
|
||||
| ` --asciitable` | ASCII and Unicode table parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable) |
|
||||
| ` --asciitable-m` | multi-line ASCII and Unicode table parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/asciitable_m) |
|
||||
| ` --blkid` | `blkid` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/blkid) |
|
||||
| ` --chage` | `chage --list` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/chage) |
|
||||
| ` --cksum` | `cksum` and `sum` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/cksum) |
|
||||
| ` --crontab` | `crontab` command and file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab) |
|
||||
| ` --crontab-u` | `crontab` file parser with user support | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/crontab_u) |
|
||||
| ` --csv` | CSV file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/csv) |
|
||||
| ` --csv-s` | CSV file streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/csv_s) |
|
||||
| ` --date` | `date` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/date) |
|
||||
| ` --df` | `df` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/df) |
|
||||
| ` --dig` | `dig` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/dig) |
|
||||
| ` --dir` | `dir` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/dir) |
|
||||
| ` --dmidecode` | `dmidecode` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/dmidecode) |
|
||||
| ` --dpkg-l` | `dpkg -l` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/dpkg_l) |
|
||||
| ` --du` | `du` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/du) |
|
||||
| ` --env` | `env` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/env) |
|
||||
| ` --file` | `file` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/file) |
|
||||
| ` --finger` | `finger` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/finger) |
|
||||
| ` --free` | `free` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/free) |
|
||||
| ` --fstab` | `/etc/fstab` file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/fstab) |
|
||||
| ` --git-log` | `git log` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/git_log) |
|
||||
| ` --git-log-s` | `git log` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/git_log_s) |
|
||||
| ` --group` | `/etc/group` file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/group) |
|
||||
| ` --gshadow` | `/etc/gshadow` file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/gshadow) |
|
||||
| ` --hash` | `hash` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/hash) |
|
||||
| ` --hashsum` | hashsum command parser (`md5sum`, `shasum`, etc.) | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/hashsum) |
|
||||
| ` --hciconfig` | `hciconfig` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/hciconfig) |
|
||||
| ` --history` | `history` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/history) |
|
||||
| ` --hosts` | `/etc/hosts` file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/hosts) |
|
||||
| ` --id` | `id` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/id) |
|
||||
| ` --ifconfig` | `ifconfig` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ifconfig) |
|
||||
| ` --ini` | INI file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ini) |
|
||||
| ` --iostat` | `iostat` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat) |
|
||||
| ` --iostat-s` | `iostat` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/iostat_s) |
|
||||
| ` --iptables` | `iptables` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/iptables) |
|
||||
| ` --iw-scan` | `iw dev [device] scan` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/iw_scan) |
|
||||
| ` --jar-manifest` | MANIFEST.MF file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/jar_manifest) |
|
||||
| ` --jobs` | `jobs` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/jobs) |
|
||||
| ` --kv` | Key/Value file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/kv) |
|
||||
| ` --last` | `last` and `lastb` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/last) |
|
||||
| ` --ls` | `ls` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ls) |
|
||||
| ` --ls-s` | `ls` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ls_s) |
|
||||
| ` --lsblk` | `lsblk` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/lsblk) |
|
||||
| ` --lsmod` | `lsmod` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/lsmod) |
|
||||
| ` --lsof` | `lsof` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/lsof) |
|
||||
| ` --lsusb` | `lsusb` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/lsusb) |
|
||||
| ` --mount` | `mount` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/mount) |
|
||||
| ` --mpstat` | `mpstat` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat) |
|
||||
| ` --mpstat-s` | `mpstat` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat_s) |
|
||||
| ` --netstat` | `netstat` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/netstat) |
|
||||
| ` --nmcli` | `nmcli` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/nmcli) |
|
||||
| ` --ntpq` | `ntpq -p` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ntpq) |
|
||||
| ` --passwd` | `/etc/passwd` file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/passwd) |
|
||||
| ` --pidstat` | `pidstat -h` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat) |
|
||||
| ` --pidstat-s` | `pidstat -h` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/pidstat_s) |
|
||||
| ` --ping` | `ping` and `ping6` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ping) |
|
||||
| ` --ping-s` | `ping` and `ping6` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ping_s) |
|
||||
| ` --pip-list` | `pip list` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_list) |
|
||||
| ` --pip-show` | `pip show` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/pip_show) |
|
||||
| ` --ps` | `ps` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ps) |
|
||||
| ` --route` | `route` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/route) |
|
||||
| ` --rpm-qi` | `rpm -qi` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/rpm_qi) |
|
||||
| ` --rsync` | `rsync` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync) |
|
||||
| ` --rsync-s` | `rsync` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync_s) |
|
||||
| ` --sfdisk` | `sfdisk` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/sfdisk) |
|
||||
| ` --shadow` | `/etc/shadow` file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/shadow) |
|
||||
| ` --ss` | `ss` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ss) |
|
||||
| ` --stat` | `stat` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/stat) |
|
||||
| ` --stat-s` | `stat` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/stat_s) |
|
||||
| ` --sysctl` | `sysctl` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/sysctl) |
|
||||
| ` --systemctl` | `systemctl` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl) |
|
||||
| ` --systemctl-lj` | `systemctl list-jobs` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_lj) |
|
||||
| ` --systemctl-ls` | `systemctl list-sockets` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_ls) |
|
||||
| `--systemctl-luf` | `systemctl list-unit-files` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/systemctl_luf) |
|
||||
| ` --systeminfo` | `systeminfo` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/systeminfo) |
|
||||
| ` --time` | `/usr/bin/time` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/time) |
|
||||
| ` --timedatectl` | `timedatectl status` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/timedatectl) |
|
||||
| ` --top` | `top -b` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/top) |
|
||||
| ` --top-s` | `top -b` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/top_s) |
|
||||
| ` --tracepath` | `tracepath` and `tracepath6` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/tracepath) |
|
||||
| ` --traceroute` | `traceroute` and `traceroute6` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/traceroute) |
|
||||
| ` --ufw` | `ufw status` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw) |
|
||||
| ` --ufw-appinfo` | `ufw app info [application]` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw_appinfo) |
|
||||
| ` --uname` | `uname -a` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/uname) |
|
||||
| `--update-alt-gs` | `update-alternatives --get-selections` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/update_alt_gs) |
|
||||
| ` --update-alt-q` | `update-alternatives --query` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/update_alt_q) |
|
||||
| ` --upower` | `upower` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/upower) |
|
||||
| ` --uptime` | `uptime` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/uptime) |
|
||||
| ` --vmstat` | `vmstat` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/vmstat) |
|
||||
| ` --vmstat-s` | `vmstat` command streaming parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/vmstat_s) |
|
||||
| ` --w` | `w` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/w) |
|
||||
| ` --wc` | `wc` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/wc) |
|
||||
| ` --who` | `who` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/who) |
|
||||
| ` --xml` | XML file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/xml) |
|
||||
| ` --xrandr` | `xrandr` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/xrandr) |
|
||||
| ` --yaml` | YAML file parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/yaml) |
|
||||
| ` --zipinfo` | `zipinfo` command parser | [📃](https://kellyjonbrazil.github.io/jc/docs/parsers/zipinfo) |
|
||||
|
||||
### Options
|
||||
- `-a` about `jc`. Prints information about `jc` and the parsers (in JSON, of
|
||||
course!)
|
||||
- `-a` about `jc`. Prints information about `jc` and the parsers (in JSON or
|
||||
YAML, of course!)
|
||||
- `-C` force color output even when using pipes (overrides `-m` and the
|
||||
`NO_COLOR` env variable)
|
||||
- `-d` debug mode. Prints trace messages if parsing issues are encountered (use
|
||||
@@ -259,6 +265,7 @@ option.
|
||||
values and no additional semantic processing
|
||||
- `-u` unbuffer output
|
||||
- `-v` version information
|
||||
- `-y` YAML output
|
||||
|
||||
### Exit Codes
|
||||
Any fatal errors within `jc` will generate an exit code of `100`, otherwise the
|
||||
@@ -305,11 +312,11 @@ color output will override both the `NO_COLOR` environment variable and the `-m`
|
||||
option.
|
||||
|
||||
### Streaming Parsers
|
||||
Most parsers load all of the data from STDIN, parse it, then output the entire
|
||||
Most parsers load all of the data from `STDIN`, parse it, then output the entire
|
||||
JSON document serially. There are some streaming parsers (e.g. `ls-s` and
|
||||
`ping-s`) that immediately start processing and outputing the data line-by-line
|
||||
as [JSON Lines](https://jsonlines.org/) (aka [NDJSON](http://ndjson.org/)) while
|
||||
it is being received from STDIN. This can significantly reduce the amount of
|
||||
it is being received from `STDIN`. This can significantly reduce the amount of
|
||||
memory required to parse large amounts of command output (e.g. `ls -lR /`) and
|
||||
can sometimes process the data more quickly. Streaming parsers have slightly
|
||||
different behavior than standard parsers as outlined below.
|
||||
@@ -374,14 +381,14 @@ $ ping 1.1.1.1 | jc --ping-s -u | jq
|
||||
|
||||
#### Using Streaming Parsers as Python Modules
|
||||
|
||||
Streaming parsers accept any iterable object and return an iterator object
|
||||
(generator) allowing lazy processing of the data. The input data should
|
||||
iterate on lines of string data. Examples of good input data are `sys.stdin` or
|
||||
Streaming parsers accept any iterable object and return an iterable object
|
||||
allowing lazy processing of the data. The input data should iterate on lines
|
||||
of string data. Examples of good input data are `sys.stdin` or
|
||||
`str.splitlines()`.
|
||||
|
||||
To use the generator object in your code, simply loop through it or use the
|
||||
[next()](https://docs.python.org/3/library/functions.html#next) builtin
|
||||
function:
|
||||
To use the returned iterable object in your code, simply loop through it or
|
||||
use the [next()](https://docs.python.org/3/library/functions.html#next)
|
||||
builtin function:
|
||||
```python
|
||||
import jc
|
||||
|
||||
@@ -404,8 +411,8 @@ or [`jc/parsers/foo_s.py (streaming)`](https://github.com/kellyjonbrazil/jc/blob
|
||||
parser as a template and simply place a `.py` file in the `jcparsers` subfolder.
|
||||
|
||||
Local plugin filenames must be valid python module names and therefore must
|
||||
start with a letter and consist entirely of alphanumerics. Local plugins
|
||||
may override default parsers.
|
||||
start with a letter and consist entirely of alphanumerics and underscores.
|
||||
Local plugins may override default parsers.
|
||||
|
||||
> Note: The application data directory follows the
|
||||
[XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html)
|
||||
@@ -438,15 +445,30 @@ If a UTC timezone can be detected in the text of the command output, the
|
||||
timestamp will be timezone aware and have a `_utc` suffix on the key name.
|
||||
(e.g. `epoch_utc`) No other timezones are supported for aware timestamps.
|
||||
|
||||
## Use In Other Shells
|
||||
`jc` can be used in most any shell. Some modern shells have JSON deserialization
|
||||
and filtering capabilities built-in which makes using `jc` even more convenient.
|
||||
|
||||
For example, the following is possible in [NGS](https://ngs-lang.org/)
|
||||
(Next Generation Shell):
|
||||
```bash
|
||||
myvar = ``jc dig www.google.com``[0].answer[0].data
|
||||
```
|
||||
This runs `jc`, parses the output JSON, and assigs the resulting data structure
|
||||
to a variable in a single line of code.
|
||||
|
||||
For more examples of how to use `jc` in other shells, see this
|
||||
[wiki page](https://github.com/kellyjonbrazil/jc/wiki/Using-jc-With-Different-Shells).
|
||||
|
||||
## Compatibility
|
||||
Some parsers like `dig`, `xml`, `csv`, etc. will work on any platform. Other
|
||||
parsers that convert platform-specific output will generate a warning message if
|
||||
they are run on an unsupported platform. To see all parser information,
|
||||
including compatibility, run `jc -ap`.
|
||||
|
||||
You may still use a parser on an unsupported platform - for example, you may want
|
||||
to parse a file with linux `lsof` output on an macOS or Windows laptop. In that
|
||||
case you can suppress the warning message with the `-q` cli option or the
|
||||
You may still use a parser on an unsupported platform - for example, you may
|
||||
want to parse a file with linux `lsof` output on an macOS or Windows laptop. In
|
||||
that case you can suppress the warning message with the `-q` cli option or the
|
||||
`quiet=True` function parameter in `parse()`:
|
||||
|
||||
macOS:
|
||||
@@ -475,7 +497,8 @@ Tested on:
|
||||
## Contributions
|
||||
Feel free to add/improve code or parsers! You can use the
|
||||
[`jc/parsers/foo.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo.py)
|
||||
or [`jc/parsers/foo_s.py (streaming)`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo_s.py) parsers as a template and submit your parser with a pull request.
|
||||
or [`jc/parsers/foo_s.py (streaming)`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo_s.py) parsers as a template and submit your parser with a pull
|
||||
request.
|
||||
|
||||
Please see the [Contributing Guidelines](https://github.com/kellyjonbrazil/jc/blob/master/CONTRIBUTING.md) for more information.
|
||||
|
||||
|
||||
@@ -8,7 +8,12 @@ jc - JSON Convert `asciitable` parser
|
||||
This parser converts ASCII and Unicode text tables with single-line rows.
|
||||
|
||||
Column headers must be at least two spaces apart from each other and must
|
||||
be unique.
|
||||
be unique. For best results, column headers should be left-justified. If
|
||||
column separators are present, then non-left-justified headers will be fixed
|
||||
automatically.
|
||||
|
||||
Row separators are optional and are ignored. Each non-row-separator line is
|
||||
considered a separate row in the table.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -136,4 +141,4 @@ Returns:
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
|
||||
|
||||
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
||||
@@ -29,6 +29,12 @@ Headers (keys) are converted to snake-case and newlines between multi-line
|
||||
headers are joined with an underscore. All values are returned as strings,
|
||||
except empty strings, which are converted to None/null.
|
||||
|
||||
> Note: table column separator characters (e.g. `|`) cannot be present
|
||||
> inside the cell data. If detected, a warning message will be printed to
|
||||
> `STDERR` and the line will be skipped. The warning message can be
|
||||
> suppressed by using the `-q` command option or by setting `quiet=True` in
|
||||
> `parse()`.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ cat table.txt | jc --asciitable-m
|
||||
@@ -120,4 +126,4 @@ Returns:
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
|
||||
|
||||
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
||||
82
docs/parsers/chage.md
Normal file
82
docs/parsers/chage.md
Normal file
@@ -0,0 +1,82 @@
|
||||
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||
<a id="jc.parsers.chage"></a>
|
||||
|
||||
# jc.parsers.chage
|
||||
|
||||
jc - JSON Convert `chage --list` command output parser
|
||||
|
||||
Supports `chage -l <username>` or `chage --list <username>`
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ chage -l johndoe | jc --chage
|
||||
|
||||
or
|
||||
|
||||
$ jc chage -l johndoe
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('chage', chage_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"password_last_changed": string,
|
||||
"password_expires": string,
|
||||
"password_inactive": string,
|
||||
"account_expires": string,
|
||||
"min_days_between_password_change": integer,
|
||||
"max_days_between_password_change": integer,
|
||||
"warning_days_before_password_expires": integer
|
||||
}
|
||||
|
||||
Examples:
|
||||
|
||||
$ chage --list joeuser | jc --chage -p
|
||||
{
|
||||
"password_last_changed": "never",
|
||||
"password_expires": "never",
|
||||
"password_inactive": "never",
|
||||
"account_expires": "never",
|
||||
"min_days_between_password_change": 0,
|
||||
"max_days_between_password_change": 99999,
|
||||
"warning_days_before_password_expires": 7
|
||||
}
|
||||
|
||||
$ chage --list joeuser | jc --chage -p -r
|
||||
{
|
||||
"password_last_changed": "never",
|
||||
"password_expires": "never",
|
||||
"password_inactive": "never",
|
||||
"account_expires": "never",
|
||||
"min_days_between_password_change": "0",
|
||||
"max_days_between_password_change": "99999",
|
||||
"warning_days_before_password_expires": "7"
|
||||
}
|
||||
|
||||
<a id="jc.parsers.chage.parse"></a>
|
||||
|
||||
### parse
|
||||
|
||||
```python
|
||||
def parse(data: str, raw: bool = False, quiet: bool = False) -> Dict
|
||||
```
|
||||
|
||||
Main text parsing function
|
||||
|
||||
Parameters:
|
||||
|
||||
data: (string) text data to parse
|
||||
raw: (boolean) unprocessed output if True
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
@@ -5,15 +5,15 @@
|
||||
|
||||
jc - JSON Convert `csv` file streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
The `csv` streaming 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.
|
||||
|
||||
Note: The first 100 rows are read into memory to enable delimiter detection,
|
||||
then the rest of the rows are loaded lazily.
|
||||
> Note: The first 100 rows are read into memory to enable delimiter
|
||||
> detection, then the rest of the rows are loaded lazily.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -68,7 +68,7 @@ Examples:
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -79,13 +79,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
|
||||
|
||||
@@ -120,4 +120,4 @@ Returns:
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.10 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
||||
@@ -19,7 +19,7 @@ time of the system the parser is run on)
|
||||
|
||||
Usage (cli):
|
||||
|
||||
C:> dir | jc --dir
|
||||
C:\> dir | jc --dir
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -42,7 +42,7 @@ Schema:
|
||||
|
||||
Examples:
|
||||
|
||||
C:> dir | jc --dir -p
|
||||
C:\> dir | jc --dir -p
|
||||
[
|
||||
{
|
||||
"date": "03/24/2021",
|
||||
@@ -83,7 +83,7 @@ Examples:
|
||||
...
|
||||
]
|
||||
|
||||
C:> dir | jc --dir -p -r
|
||||
C:\> dir | jc --dir -p -r
|
||||
[
|
||||
{
|
||||
"date": "03/24/2021",
|
||||
|
||||
@@ -43,8 +43,8 @@ Schema:
|
||||
"author": string,
|
||||
"author_email": string,
|
||||
"date": string,
|
||||
"epoch": integer, [0]
|
||||
"epoch_utc": integer, [1]
|
||||
"epoch": integer, # [0]
|
||||
"epoch_utc": integer, # [1]
|
||||
"commit_by": string,
|
||||
"commit_by_email": string,
|
||||
"commit_by_date": string,
|
||||
@@ -172,4 +172,4 @@ Returns:
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
|
||||
|
||||
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
||||
111
docs/parsers/git_log_s.md
Normal file
111
docs/parsers/git_log_s.md
Normal file
@@ -0,0 +1,111 @@
|
||||
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||
<a id="jc.parsers.git_log_s"></a>
|
||||
|
||||
# jc.parsers.git\_log\_s
|
||||
|
||||
jc - JSON Convert `git log` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Can be used with the following format options:
|
||||
- `oneline`
|
||||
- `short`
|
||||
- `medium`
|
||||
- `full`
|
||||
- `fuller`
|
||||
|
||||
Additional options supported:
|
||||
- `--stat`
|
||||
- `--shortstat`
|
||||
|
||||
The `epoch` calculated timestamp field is naive. (i.e. based on the
|
||||
local time of the system the parser is run on)
|
||||
|
||||
The `epoch_utc` calculated timestamp field is timezone-aware and is
|
||||
only available if the timezone field is UTC.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ git log | jc --git-log-s
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
|
||||
result = jc.parse('git_log_s', git_log_command_output.splitlines())
|
||||
for item in result:
|
||||
# do something
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"commit": string,
|
||||
"author": string,
|
||||
"author_email": string,
|
||||
"date": string,
|
||||
"epoch": integer, # [0]
|
||||
"epoch_utc": integer, # [1]
|
||||
"commit_by": string,
|
||||
"commit_by_email": string,
|
||||
"commit_by_date": string,
|
||||
"message": string,
|
||||
"stats" : {
|
||||
"files_changed": integer,
|
||||
"insertions": integer,
|
||||
"deletions": integer,
|
||||
"files": [
|
||||
string
|
||||
]
|
||||
}
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
"success": boolean, # false if error parsing
|
||||
"error": string, # exists if "success" is false
|
||||
"line": string # exists if "success" is false
|
||||
}
|
||||
}
|
||||
|
||||
[0] naive timestamp if "date" field is parsable, else null
|
||||
[1] timezone aware timestamp availabe for UTC, else null
|
||||
|
||||
Examples:
|
||||
|
||||
$ git log | jc --git-log-s
|
||||
{"commit":"a730ae18c8e81c5261db132df73cd74f272a0a26","author":"Kelly...}
|
||||
{"commit":"930bf439c06c48a952baec05a9896c8d92b7693e","author":"Kelly...}
|
||||
...
|
||||
|
||||
<a id="jc.parsers.git_log_s.parse"></a>
|
||||
|
||||
### parse
|
||||
|
||||
```python
|
||||
@add_jc_meta
|
||||
def parse(data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
data: (iterable) line-based text data to parse
|
||||
(e.g. sys.stdin or str.splitlines())
|
||||
|
||||
raw: (boolean) unprocessed output if True
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
|
||||
Returns:
|
||||
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
|
||||
|
||||
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
jc - JSON Convert `ifconfig` command output parser
|
||||
|
||||
Note: No `ifconfig` options are supported.
|
||||
> Note: No `ifconfig` options are supported.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ Parses standard `INI` files and files containing simple key/value pairs.
|
||||
- If duplicate keys are found, only the last value will be used.
|
||||
|
||||
> Note: Values starting and ending with quotation marks will have the marks
|
||||
removed. If you would like to keep the quotation marks, use the `-r`
|
||||
command-line argument or the `raw=True` argument in `parse()`.
|
||||
> removed. If you would like to keep the quotation marks, use the `-r`
|
||||
> command-line argument or the `raw=True` argument in `parse()`.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -26,8 +26,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
ini or key/value document converted to a dictionary - see the
|
||||
configparser standard library documentation for more details.
|
||||
ini or key/value document converted to a dictionary - see the configparser
|
||||
standard library documentation for more details.
|
||||
|
||||
{
|
||||
"key1": string,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
jc - JSON Convert `iostat` command output parser
|
||||
|
||||
Note: `iostat` version 11 and higher include a JSON output option
|
||||
> Note: `iostat` version 11 and higher include a JSON output option
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
|
||||
jc - JSON Convert `iostat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Note: `iostat` version 11 and higher include a JSON output option
|
||||
> Note: `iostat` version 11 and higher include a JSON output option
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ iostat | jc --iostat-s
|
||||
|
||||
> Note: When piping `jc` converted `iostat` output to other processes it may
|
||||
appear the output is hanging due to the OS pipe buffers. This is because
|
||||
`iostat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
option to unbuffer the `jc` output if you would like immediate output. See
|
||||
the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> appear the output is hanging due to the OS pipe buffers. This is because
|
||||
> `iostat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
> option to unbuffer the `jc` output if you would like immediate output. See
|
||||
> the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -112,7 +112,7 @@ Examples:
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -123,13 +123,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
@@ -12,8 +12,8 @@ Supports files containing simple key/value pairs.
|
||||
- If duplicate keys are found, only the last value will be used.
|
||||
|
||||
> Note: Values starting and ending with quotation marks will have the marks
|
||||
removed. If you would like to keep the quotation marks, use the `-r`
|
||||
command-line argument or the `raw=True` argument in `parse()`.
|
||||
> removed. If you would like to keep the quotation marks, use the `-r`
|
||||
> command-line argument or the `raw=True` argument in `parse()`.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -26,8 +26,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
key/value document converted to a dictionary - see the
|
||||
configparser standard library documentation for more details.
|
||||
key/value document converted to a dictionary - see the configparser standard
|
||||
library documentation for more details.
|
||||
|
||||
{
|
||||
"key1": string,
|
||||
|
||||
@@ -9,11 +9,12 @@ Options supported:
|
||||
- `lbaR1`
|
||||
- `--time-style=full-iso`
|
||||
|
||||
Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly
|
||||
parse filenames that include newline characters. Since `ls` does not encode
|
||||
newlines in filenames when outputting to a pipe it will cause `jc` to see
|
||||
multiple files instead of a single file if `-1`, `-l`, or `-b` is not used.
|
||||
Alternatively, `vdir` can be used, which is the same as running `ls -lb`.
|
||||
> Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly
|
||||
> parse filenames that include newline characters. Since `ls` does not
|
||||
> encode newlines in filenames when outputting to a pipe it will cause `jc`
|
||||
> to see multiple files instead of a single file if `-1`, `-l`, or `-b` is
|
||||
> not used. Alternatively, `vdir` can be used, which is the same as running
|
||||
> `ls -lb`.
|
||||
|
||||
The `epoch` calculated timestamp field is naive. (i.e. based on the local
|
||||
time of the system the parser is run on)
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
jc - JSON Convert `ls` and `vdir` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Requires the `-l` option to be used on `ls`. If there are newline characters
|
||||
in the filename, then make sure to use the `-b` option on `ls`.
|
||||
@@ -81,7 +81,7 @@ Examples:
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -92,13 +92,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, aix, freebsd
|
||||
|
||||
@@ -22,9 +22,9 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Note: <item> object keynames are assigned directly from the lsusb
|
||||
output. If there are duplicate <item> names in a section, only the
|
||||
last one is converted.
|
||||
> Note: <item> object keynames are assigned directly from the lsusb
|
||||
> output. If there are duplicate <item> names in a section, only the
|
||||
> last one is converted.
|
||||
|
||||
[
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
jc - JSON Convert `mpstat` command output parser
|
||||
|
||||
Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
> Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
jc - JSON Convert `mpstat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
> Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -101,15 +101,13 @@ Examples:
|
||||
|
||||
```python
|
||||
@add_jc_meta
|
||||
def parse(
|
||||
data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]
|
||||
def parse(data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -120,13 +118,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
@@ -29,18 +29,18 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Because there are so many options, the schema is not strictly defined.
|
||||
Integer and Float value conversions are attempted and the original
|
||||
values are kept if they fail. If you don't want automatic conversion,
|
||||
then use the -r or raw=True option to disable it.
|
||||
Because there are so many options, the schema is not strictly defined.
|
||||
Integer and Float value conversions are attempted and the original
|
||||
values are kept if they fail. If you don't want automatic conversion,
|
||||
then use the `-r` or `raw=True` option to disable it.
|
||||
|
||||
The structure is flat, for the most part, but there are a couple of
|
||||
"well-known" keys that are further parsed into objects for convenience.
|
||||
These are documented below.
|
||||
The structure is flat, for the most part, but there are a couple of
|
||||
"well-known" keys that are further parsed into objects for convenience.
|
||||
These are documented below.
|
||||
|
||||
[
|
||||
{
|
||||
"<key>": string/integer/float, [0]
|
||||
"<key>": string/integer/float, # [0]
|
||||
"dhcp4_option_x": {
|
||||
"name": string,
|
||||
"value": string/integer/float,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
# jc.parsers.pidstat
|
||||
|
||||
jc - JSON Convert `pidstat` command output parser
|
||||
jc - JSON Convert `pidstat -h` command output parser
|
||||
|
||||
Must use the `-h` option in `pidstat`. All other `pidstat` options are
|
||||
supported in combination with `-h`.
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
# jc.parsers.pidstat\_s
|
||||
|
||||
jc - JSON Convert `pidstat` command output streaming parser
|
||||
jc - JSON Convert `pidstat -h` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Must use the `-h` option in `pidstat`. All other `pidstat` options are
|
||||
supported in combination with `-h`.
|
||||
@@ -16,11 +16,11 @@ Usage (cli):
|
||||
$ pidstat | jc --pidstat-s
|
||||
|
||||
> Note: When piping `jc` converted `pidstat` output to other processes it
|
||||
may appear the output is hanging due to the OS pipe buffers. This is
|
||||
because `pidstat` output is too small to quickly fill up the buffer. Use
|
||||
the `-u` option to unbuffer the `jc` output if you would like immediate
|
||||
output. See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> may appear the output is hanging due to the OS pipe buffers. This is
|
||||
> because `pidstat` output is too small to quickly fill up the buffer. Use
|
||||
> the `-u` option to unbuffer the `jc` output if you would like immediate
|
||||
> output. See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -83,15 +83,13 @@ Examples:
|
||||
|
||||
```python
|
||||
@add_jc_meta
|
||||
def parse(
|
||||
data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]
|
||||
def parse(data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -102,13 +100,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
@@ -9,8 +9,8 @@ Supports `ping` and `ping6` output.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
Note: Use the ping `-c` (count) option, otherwise data will not be
|
||||
piped to `jc`.
|
||||
> Note: Use the ping `-c` (count) option, otherwise data will not be
|
||||
> piped to `jc`.
|
||||
|
||||
$ ping -c 3 1.2.3.4 | jc --ping
|
||||
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
|
||||
jc - JSON Convert `ping` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Supports `ping` and `ping6` output.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ ping | jc --ping-s
|
||||
$ ping 1.2.3.4 | jc --ping-s
|
||||
|
||||
> Note: When piping `jc` converted `ping` output to other processes it may
|
||||
appear the output is hanging due to the OS pipe buffers. This is because
|
||||
`ping` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
option to unbuffer the `jc` output if you would like immediate output.
|
||||
See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> appear the output is hanging due to the OS pipe buffers. This is because
|
||||
> `ping` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
> option to unbuffer the `jc` output if you would like immediate output.
|
||||
> See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -88,7 +88,7 @@ Examples:
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -99,13 +99,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
@@ -70,7 +70,7 @@ Examples:
|
||||
### parse
|
||||
|
||||
```python
|
||||
def parse(data, raw=False, quiet=False)
|
||||
def parse(data: str, raw: bool = False, quiet: bool = False) -> List[Dict]
|
||||
```
|
||||
|
||||
Main text parsing function
|
||||
@@ -88,4 +88,4 @@ Returns:
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, cygwin, win32, aix, freebsd
|
||||
|
||||
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
Version 1.4 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
|
||||
@@ -22,20 +22,20 @@ Schema:
|
||||
|
||||
[
|
||||
{
|
||||
"destination": string,
|
||||
"gateway": string,
|
||||
"genmask": string,
|
||||
"flags": string,
|
||||
"destination": string,
|
||||
"gateway": string,
|
||||
"genmask": string,
|
||||
"flags": string,
|
||||
"flags_pretty": [
|
||||
string
|
||||
string
|
||||
]
|
||||
"metric": integer,
|
||||
"ref": integer,
|
||||
"use": integer,
|
||||
"mss": integer,
|
||||
"window": integer,
|
||||
"irtt": integer,
|
||||
"iface": string
|
||||
"metric": integer,
|
||||
"ref": integer,
|
||||
"use": integer,
|
||||
"mss": integer,
|
||||
"window": integer,
|
||||
"irtt": integer,
|
||||
"iface": string
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Works with `rpm -qi [package]` or `rpm -qia`.
|
||||
The `..._epoch` calculated timestamp fields are naive. (i.e. based on the
|
||||
local time of the system the parser is run on)
|
||||
|
||||
The `..._epoch_utc` calculated timestamp fields are timezone-aware and is
|
||||
The `..._epoch_utc` calculated timestamp fields are timezone-aware and are
|
||||
only available if the timezone field is UTC.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
jc - JSON Convert `rsync` command output parser
|
||||
|
||||
Supports the `-i` or `--itemize-changes` options with all levels of
|
||||
verbosity. This parser will process the STDOUT output or a log file
|
||||
verbosity. This parser will process the `STDOUT` output or a log file
|
||||
generated with the `--log-file` option.
|
||||
|
||||
Usage (cli):
|
||||
@@ -51,8 +51,8 @@ Schema:
|
||||
"time": string,
|
||||
"process": integer,
|
||||
"metadata": string,
|
||||
"update_type": string/null, [0]
|
||||
"file_type": string/null, [1]
|
||||
"update_type": string/null, # [0]
|
||||
"file_type": string/null, # [1]
|
||||
"checksum_or_value_different": bool/null,
|
||||
"size_different": bool/null,
|
||||
"modification_time_different": bool/null,
|
||||
@@ -61,7 +61,7 @@ Schema:
|
||||
"group_different": bool/null,
|
||||
"acl_different": bool/null,
|
||||
"extended_attribute_different": bool/null,
|
||||
"epoch": integer, [2]
|
||||
"epoch": integer, # [2]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
jc - JSON Convert `rsync` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Supports the `-i` or `--itemize-changes` options with all levels of
|
||||
verbosity. This parser will process the STDOUT output or a log file
|
||||
verbosity. This parser will process the `STDOUT` output or a log file
|
||||
generated with the `--log-file` option.
|
||||
|
||||
Usage (cli):
|
||||
@@ -49,8 +49,8 @@ Schema:
|
||||
"time": string,
|
||||
"process": integer,
|
||||
"metadata": string,
|
||||
"update_type": string/null, [0]
|
||||
"file_type": string/null, [1]
|
||||
"update_type": string/null, # [0]
|
||||
"file_type": string/null, # [1]
|
||||
"checksum_or_value_different": bool/null,
|
||||
"size_different": bool/null,
|
||||
"modification_time_different": bool/null,
|
||||
@@ -59,7 +59,7 @@ Schema:
|
||||
"group_different": bool/null,
|
||||
"acl_different": bool/null,
|
||||
"extended_attribute_different": bool/null,
|
||||
"epoch": integer, [2]
|
||||
"epoch": integer, # [2]
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
@@ -90,15 +90,13 @@ Examples:
|
||||
|
||||
```python
|
||||
@add_jc_meta
|
||||
def parse(
|
||||
data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]
|
||||
def parse(data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -109,13 +107,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
jc - JSON Convert `ss` command output parser
|
||||
|
||||
Extended information options like -e and -p are not supported and may cause
|
||||
parsing irregularities.
|
||||
Extended information options like `-e` and `-p` are not supported and may
|
||||
cause parsing irregularities.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -23,8 +23,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Information from https://www.cyberciti.biz/files/ss.html used to define
|
||||
field names
|
||||
Information from https://www.cyberciti.biz/files/ss.html used to define
|
||||
field names
|
||||
|
||||
[
|
||||
{
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
jc - JSON Convert `stat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
The `xxx_epoch` calculated timestamp fields are naive. (i.e. based on the
|
||||
local time of the system the parser is run on).
|
||||
@@ -86,7 +86,7 @@ Examples:
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -97,13 +97,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux, darwin, freebsd
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
jc - JSON Convert `sysctl -a` command output parser
|
||||
|
||||
Note: Since `sysctl` output is not easily parsable only a very simple
|
||||
key/value object will be output. An attempt is made to convert obvious
|
||||
integers and floats. If no conversion is desired, use the `-r`
|
||||
command-line argument or the `raw=True` argument in `parse()`.
|
||||
> Note: Since `sysctl` output is not easily parsable only a very simple
|
||||
> key/value object will be output. An attempt is made to convert obvious
|
||||
> integers and floats. If no conversion is desired, use the `-r`
|
||||
> command-line argument or the `raw=True` argument in `parse()`.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ used to redirect the output to a file that can be read by `jc`.
|
||||
Alternatively, the output from `/usr/bin/time` can be redirected to `STDOUT`
|
||||
so `jc` can receive it.
|
||||
|
||||
Note: `/usr/bin/time` is similar but different from the Bash builtin
|
||||
`time` command.
|
||||
> Note: `/usr/bin/time` is similar but different from the Bash builtin
|
||||
> `time` command.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -26,8 +26,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Source: https://www.freebsd.org/cgi/man.cgi?query=getrusage
|
||||
https://man7.org/linux/man-pages/man1/time.1.html
|
||||
Source: https://www.freebsd.org/cgi/man.cgi?query=getrusage,
|
||||
https://man7.org/linux/man-pages/man1/time.1.html
|
||||
|
||||
{
|
||||
"real_time": float,
|
||||
|
||||
339
docs/parsers/top.md
Normal file
339
docs/parsers/top.md
Normal file
@@ -0,0 +1,339 @@
|
||||
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||
<a id="jc.parsers.top"></a>
|
||||
|
||||
# jc.parsers.top
|
||||
|
||||
jc - JSON Convert `top -b` command output parser
|
||||
|
||||
Requires batch mode (`-b`). The `-n` option must also be used to limit
|
||||
the number of times `top` is run.
|
||||
|
||||
Warning messages will be printed to `STDERR` if truncated fields are
|
||||
detected. These warnings can be suppressed with the `-q` or `quiet=True`
|
||||
option.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ top -b -n 3 | jc --top
|
||||
|
||||
or
|
||||
|
||||
$ jc top -b -n 3
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('top', top_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
All `-` values are converted to `null`
|
||||
|
||||
[
|
||||
{
|
||||
"time": string,
|
||||
"uptime": integer,
|
||||
"users": integer,
|
||||
"load_1m": float,
|
||||
"load_5m": float,
|
||||
"load_15m": float,
|
||||
"tasks_total": integer,
|
||||
"tasks_running": integer,
|
||||
"tasks_sleeping": integer,
|
||||
"tasks_stopped": integer,
|
||||
"tasks_zombie": integer,
|
||||
"cpu_user": float,
|
||||
"cpu_sys": float,
|
||||
"cpu_nice": float,
|
||||
"cpu_idle": float,
|
||||
"cpu_wait": float,
|
||||
"cpu_hardware": float,
|
||||
"cpu_software": float,
|
||||
"cpu_steal": float,
|
||||
"mem_total": float, # [0]
|
||||
"mem_free": float, # [0]
|
||||
"mem_used": float, # [0]
|
||||
"mem_buff_cache": float, # [0]
|
||||
"swap_total": float, # [0]
|
||||
"swap_free": float, # [0]
|
||||
"swap_used": float, # [0]
|
||||
"mem_available": float, # [0]
|
||||
"processes": [
|
||||
{
|
||||
"pid": integer,
|
||||
"user": string,
|
||||
"priority": integer,
|
||||
"nice": integer,
|
||||
"virtual_mem": float, # [1]
|
||||
"resident_mem": float, # [1]
|
||||
"shared_mem": float, # [1]
|
||||
"status": string,
|
||||
"percent_cpu": float,
|
||||
"percent_mem": float,
|
||||
"time_hundredths": string,
|
||||
"command": string,
|
||||
"parent_pid": integer,
|
||||
"uid": integer,
|
||||
"real_uid": integer,
|
||||
"real_user": string,
|
||||
"saved_uid": integer,
|
||||
"saved_user": string,
|
||||
"gid": integer,
|
||||
"group": string,
|
||||
"pgrp": integer,
|
||||
"tty": string,
|
||||
"tty_process_gid": integer,
|
||||
"session_id": integer,
|
||||
"thread_count": integer,
|
||||
"last_used_processor": integer,
|
||||
"time": string,
|
||||
"swap": float, # [1]
|
||||
"code": float, # [1]
|
||||
"data": float, # [1]
|
||||
"major_page_fault_count": integer,
|
||||
"minor_page_fault_count": integer,
|
||||
"dirty_pages_count": integer,
|
||||
"sleeping_in_function": string,
|
||||
"flags": string,
|
||||
"cgroups": string,
|
||||
"supplementary_gids": [
|
||||
integer
|
||||
],
|
||||
"supplementary_groups": [
|
||||
string
|
||||
],
|
||||
"thread_gid": integer,
|
||||
"environment_variables": [
|
||||
string
|
||||
]
|
||||
"major_page_fault_count_delta": integer,
|
||||
"minor_page_fault_count_delta": integer,
|
||||
"used": float, # [1]
|
||||
"ipc_namespace_inode": integer,
|
||||
"mount_namespace_inode": integer,
|
||||
"net_namespace_inode": integer,
|
||||
"pid_namespace_inode": integer,
|
||||
"user_namespace_inode": integer,
|
||||
"nts_namespace_inode": integer,
|
||||
"control_group_name": string,
|
||||
"lxc_container_name": string,
|
||||
"numa_node": integer,
|
||||
"out_of_mem_adjustment": integer,
|
||||
"out_of_mem_score": integer,
|
||||
"resident_anon_mem": integer,
|
||||
"resident_file_backed_mem": integer,
|
||||
"resident_locked_mem": integer,
|
||||
"resident_shared_mem": integer
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
[0] Values are in the units output by `top`
|
||||
[1] Unit suffix stripped during float conversion
|
||||
|
||||
Examples:
|
||||
|
||||
$ top -b -n 3 | jc --top -p
|
||||
[
|
||||
{
|
||||
"time": "11:20:43",
|
||||
"uptime": 118,
|
||||
"users": 2,
|
||||
"load_1m": 0.0,
|
||||
"load_5m": 0.01,
|
||||
"load_15m": 0.05,
|
||||
"tasks_total": 108,
|
||||
"tasks_running": 2,
|
||||
"tasks_sleeping": 106,
|
||||
"tasks_stopped": 0,
|
||||
"tasks_zombie": 0,
|
||||
"cpu_user": 5.6,
|
||||
"cpu_sys": 11.1,
|
||||
"cpu_nice": 0.0,
|
||||
"cpu_idle": 83.3,
|
||||
"cpu_wait": 0.0,
|
||||
"cpu_hardware": 0.0,
|
||||
"cpu_software": 0.0,
|
||||
"cpu_steal": 0.0,
|
||||
"mem_total": 3.7,
|
||||
"mem_free": 3.3,
|
||||
"mem_used": 0.2,
|
||||
"mem_buff_cache": 0.2,
|
||||
"swap_total": 2.0,
|
||||
"swap_free": 2.0,
|
||||
"swap_used": 0.0,
|
||||
"mem_available": 3.3,
|
||||
"processes": [
|
||||
{
|
||||
"pid": 2225,
|
||||
"user": "kbrazil",
|
||||
"priority": 20,
|
||||
"nice": 0,
|
||||
"virtual_mem": 158.1,
|
||||
"resident_mem": 2.2,
|
||||
"shared_mem": 1.6,
|
||||
"status": "running",
|
||||
"percent_cpu": 12.5,
|
||||
"percent_mem": 0.1,
|
||||
"time_hundredths": "0:00.02",
|
||||
"command": "top",
|
||||
"parent_pid": 1884,
|
||||
"uid": 1000,
|
||||
"real_uid": 1000,
|
||||
"real_user": "kbrazil",
|
||||
"saved_uid": 1000,
|
||||
"saved_user": "kbrazil",
|
||||
"gid": 1000,
|
||||
"group": "kbrazil",
|
||||
"pgrp": 2225,
|
||||
"tty": "pts/0",
|
||||
"tty_process_gid": 2225,
|
||||
"session_id": 1884,
|
||||
"thread_count": 1,
|
||||
"last_used_processor": 0,
|
||||
"time": "0:00",
|
||||
"swap": 0.0,
|
||||
"code": 0.1,
|
||||
"data": 1.0,
|
||||
"major_page_fault_count": 0,
|
||||
"minor_page_fault_count": 736,
|
||||
"dirty_pages_count": 0,
|
||||
"sleeping_in_function": null,
|
||||
"flags": "..4.2...",
|
||||
"cgroups": "1:name=systemd:/user.slice/user-1000.+",
|
||||
"supplementary_gids": [
|
||||
10,
|
||||
1000
|
||||
],
|
||||
"supplementary_groups": [
|
||||
"wheel",
|
||||
"kbrazil"
|
||||
],
|
||||
"thread_gid": 2225,
|
||||
"environment_variables": [
|
||||
"XDG_SESSION_ID=2",
|
||||
"HOSTNAME=localhost"
|
||||
],
|
||||
"major_page_fault_count_delta": 0,
|
||||
"minor_page_fault_count_delta": 4,
|
||||
"used": 2.2,
|
||||
"ipc_namespace_inode": 4026531839,
|
||||
"mount_namespace_inode": 4026531840,
|
||||
"net_namespace_inode": 4026531956,
|
||||
"pid_namespace_inode": 4026531836,
|
||||
"user_namespace_inode": 4026531837,
|
||||
"nts_namespace_inode": 4026531838
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
$ top -b -n 3 | jc --top -p -r
|
||||
[
|
||||
{
|
||||
"time": "11:20:43",
|
||||
"uptime": "1:18",
|
||||
"users": "2",
|
||||
"load_1m": "0.00",
|
||||
"load_5m": "0.01",
|
||||
"load_15m": "0.05",
|
||||
"tasks_total": "108",
|
||||
"tasks_running": "2",
|
||||
"tasks_sleeping": "106",
|
||||
"tasks_stopped": "0",
|
||||
"tasks_zombie": "0",
|
||||
"cpu_user": "5.6",
|
||||
"cpu_sys": "11.1",
|
||||
"cpu_nice": "0.0",
|
||||
"cpu_idle": "83.3",
|
||||
"cpu_wait": "0.0",
|
||||
"cpu_hardware": "0.0",
|
||||
"cpu_software": "0.0",
|
||||
"cpu_steal": "0.0",
|
||||
"swap_total": "2.0",
|
||||
"swap_free": "2.0",
|
||||
"swap_used": "0.0",
|
||||
"mem_available": "3.3",
|
||||
"processes": [
|
||||
{
|
||||
"PID": "2225",
|
||||
"USER": "kbrazil",
|
||||
"PR": "20",
|
||||
"NI": "0",
|
||||
"VIRT": "158.1m",
|
||||
"RES": "2.2m",
|
||||
"SHR": "1.6m",
|
||||
"S": "R",
|
||||
"%CPU": "12.5",
|
||||
"%MEM": "0.1",
|
||||
"TIME+": "0:00.02",
|
||||
"COMMAND": "top",
|
||||
"PPID": "1884",
|
||||
"UID": "1000",
|
||||
"RUID": "1000",
|
||||
"RUSER": "kbrazil",
|
||||
"SUID": "1000",
|
||||
"SUSER": "kbrazil",
|
||||
"GID": "1000",
|
||||
"GROUP": "kbrazil",
|
||||
"PGRP": "2225",
|
||||
"TTY": "pts/0",
|
||||
"TPGID": "2225",
|
||||
"SID": "1884",
|
||||
"nTH": "1",
|
||||
"P": "0",
|
||||
"TIME": "0:00",
|
||||
"SWAP": "0.0m",
|
||||
"CODE": "0.1m",
|
||||
"DATA": "1.0m",
|
||||
"nMaj": "0",
|
||||
"nMin": "736",
|
||||
"nDRT": "0",
|
||||
"WCHAN": "-",
|
||||
"Flags": "..4.2...",
|
||||
"CGROUPS": "1:name=systemd:/user.slice/user-1000.+",
|
||||
"SUPGIDS": "10,1000",
|
||||
"SUPGRPS": "wheel,kbrazil",
|
||||
"TGID": "2225",
|
||||
"ENVIRON": "XDG_SESSION_ID=2 HOSTNAME=localhost S+",
|
||||
"vMj": "0",
|
||||
"vMn": "4",
|
||||
"USED": "2.2m",
|
||||
"nsIPC": "4026531839",
|
||||
"nsMNT": "4026531840",
|
||||
"nsNET": "4026531956",
|
||||
"nsPID": "4026531836",
|
||||
"nsUSER": "4026531837",
|
||||
"nsUTS": "4026531838"
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
<a id="jc.parsers.top.parse"></a>
|
||||
|
||||
### parse
|
||||
|
||||
```python
|
||||
def parse(data: str, raw: bool = False, quiet: bool = False) -> List[Dict]
|
||||
```
|
||||
|
||||
Main text parsing function
|
||||
|
||||
Parameters:
|
||||
|
||||
data: (string) text data to parse
|
||||
raw: (boolean) unprocessed output if True
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
|
||||
Returns:
|
||||
|
||||
List of Dictionaries. Raw or processed structured data.
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
180
docs/parsers/top_s.md
Normal file
180
docs/parsers/top_s.md
Normal file
@@ -0,0 +1,180 @@
|
||||
[Home](https://kellyjonbrazil.github.io/jc/)
|
||||
<a id="jc.parsers.top_s"></a>
|
||||
|
||||
# jc.parsers.top\_s
|
||||
|
||||
jc - JSON Convert `top -b` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Requires batch mode (`-b`).
|
||||
|
||||
Warning messages will be printed to `STDERR` if truncated fields are
|
||||
detected. These warnings can be suppressed with the `-q` or `quiet=True`
|
||||
option.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ top -b | jc --top-s
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
|
||||
result = jc.parse('top_s', top_command_output.splitlines())
|
||||
for item in result:
|
||||
# do something
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"time": string,
|
||||
"uptime": integer,
|
||||
"users": integer,
|
||||
"load_1m": float,
|
||||
"load_5m": float,
|
||||
"load_15m": float,
|
||||
"tasks_total": integer,
|
||||
"tasks_running": integer,
|
||||
"tasks_sleeping": integer,
|
||||
"tasks_stopped": integer,
|
||||
"tasks_zombie": integer,
|
||||
"cpu_user": float,
|
||||
"cpu_sys": float,
|
||||
"cpu_nice": float,
|
||||
"cpu_idle": float,
|
||||
"cpu_wait": float,
|
||||
"cpu_hardware": float,
|
||||
"cpu_software": float,
|
||||
"cpu_steal": float,
|
||||
"mem_total": float, # [0]
|
||||
"mem_free": float, # [0]
|
||||
"mem_used": float, # [0]
|
||||
"mem_buff_cache": float, # [0]
|
||||
"swap_total": float, # [0]
|
||||
"swap_free": float, # [0]
|
||||
"swap_used": float, # [0]
|
||||
"mem_available": float, # [0]
|
||||
"processes": [
|
||||
{
|
||||
"pid": integer,
|
||||
"user": string,
|
||||
"priority": integer,
|
||||
"nice": integer,
|
||||
"virtual_mem": float, # [1]
|
||||
"resident_mem": float, # [1]
|
||||
"shared_mem": float, # [1]
|
||||
"status": string,
|
||||
"percent_cpu": float,
|
||||
"percent_mem": float,
|
||||
"time_hundredths": string,
|
||||
"command": string,
|
||||
"parent_pid": integer,
|
||||
"uid": integer,
|
||||
"real_uid": integer,
|
||||
"real_user": string,
|
||||
"saved_uid": integer,
|
||||
"saved_user": string,
|
||||
"gid": integer,
|
||||
"group": string,
|
||||
"pgrp": integer,
|
||||
"tty": string,
|
||||
"tty_process_gid": integer,
|
||||
"session_id": integer,
|
||||
"thread_count": integer,
|
||||
"last_used_processor": integer,
|
||||
"time": string,
|
||||
"swap": float, # [1]
|
||||
"code": float, # [1]
|
||||
"data": float, # [1]
|
||||
"major_page_fault_count": integer,
|
||||
"minor_page_fault_count": integer,
|
||||
"dirty_pages_count": integer,
|
||||
"sleeping_in_function": string,
|
||||
"flags": string,
|
||||
"cgroups": string,
|
||||
"supplementary_gids": [
|
||||
integer
|
||||
],
|
||||
"supplementary_groups": [
|
||||
string
|
||||
],
|
||||
"thread_gid": integer,
|
||||
"environment_variables": [
|
||||
string
|
||||
]
|
||||
"major_page_fault_count_delta": integer,
|
||||
"minor_page_fault_count_delta": integer,
|
||||
"used": float, # [1]
|
||||
"ipc_namespace_inode": integer,
|
||||
"mount_namespace_inode": integer,
|
||||
"net_namespace_inode": integer,
|
||||
"pid_namespace_inode": integer,
|
||||
"user_namespace_inode": integer,
|
||||
"nts_namespace_inode": integer,
|
||||
"control_group_name": string,
|
||||
"lxc_container_name": string,
|
||||
"numa_node": integer,
|
||||
"out_of_mem_adjustment": integer,
|
||||
"out_of_mem_score": integer,
|
||||
"resident_anon_mem": integer,
|
||||
"resident_file_backed_mem": integer,
|
||||
"resident_locked_mem": integer,
|
||||
"resident_shared_mem": integer
|
||||
}
|
||||
],
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
"success": boolean, # false if error parsing
|
||||
"error": string, # exists if "success" is false
|
||||
"line": string # exists if "success" is false
|
||||
}
|
||||
}
|
||||
|
||||
[0] Values are in the units output by `top`
|
||||
[1] Unit suffix stripped during float conversion
|
||||
|
||||
Examples:
|
||||
|
||||
$ top -b | jc --top-s
|
||||
{"time":"11:24:50","uptime":2,"users":2,"load_1m":0.23,"load_5m":...}
|
||||
...
|
||||
|
||||
$ top -b | jc --top-s -r
|
||||
{"time":"11:24:50","uptime":"2 min","users":"2","load_1m":"0.23","lo...}
|
||||
...
|
||||
|
||||
<a id="jc.parsers.top_s.parse"></a>
|
||||
|
||||
### parse
|
||||
|
||||
```python
|
||||
@add_jc_meta
|
||||
def parse(data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False) -> Union[Iterable[Dict], tuple]
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
data: (iterable) line-based text data to parse
|
||||
(e.g. sys.stdin or str.splitlines())
|
||||
|
||||
raw: (boolean) unprocessed output if True
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
|
||||
Returns:
|
||||
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
|
||||
@@ -7,12 +7,12 @@ jc - JSON Convert `traceroute` command output parser
|
||||
|
||||
Supports `traceroute` and `traceroute6` output.
|
||||
|
||||
Note: On some operating systems you will need to redirect `STDERR` to
|
||||
`STDOUT` for destination info since the header line is sent to
|
||||
`STDERR`. A warning message will be printed to `STDERR` if the
|
||||
header row is not found.
|
||||
|
||||
e.g. `$ traceroute 8.8.8.8 2>&1 | jc --traceroute`
|
||||
> Note: On some operating systems you will need to redirect `STDERR` to
|
||||
> `STDOUT` for destination info since the header line is sent to
|
||||
> `STDERR`. A warning message will be printed to `STDERR` if the
|
||||
> header row is not found.
|
||||
>
|
||||
> e.g. `$ traceroute 8.8.8.8 2>&1 | jc --traceroute`
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
jc - JSON Convert `uname -a` command output parser
|
||||
|
||||
Note: Must use `uname -a`
|
||||
> Note: Must use `uname -a`
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
jc - JSON Convert `vmstat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Options supported: `-a`, `-w`, `-d`, `-t`
|
||||
|
||||
@@ -21,11 +21,11 @@ Usage (cli):
|
||||
$ vmstat | jc --vmstat-s
|
||||
|
||||
> Note: When piping `jc` converted `vmstat` output to other processes it may
|
||||
appear the output is hanging due to the OS pipe buffers. This is because
|
||||
`vmstat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
option to unbuffer the `jc` output if you would like immediate output. See
|
||||
the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> appear the output is hanging due to the OS pipe buffers. This is because
|
||||
> `vmstat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
> option to unbuffer the `jc` output if you would like immediate output. See
|
||||
> the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -75,9 +75,9 @@ Schema:
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
"success": boolean, # [2]
|
||||
"error": string, # [3]
|
||||
"line": string # [3]
|
||||
"success": boolean, # [2]
|
||||
"error": string, # [3]
|
||||
"line": string # [3]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ Examples:
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
|
||||
```
|
||||
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -116,13 +116,9 @@ Parameters:
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
|
||||
### Parser Information
|
||||
Compatibility: linux
|
||||
|
||||
@@ -16,8 +16,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
XML Document converted to a Dictionary
|
||||
See https://github.com/martinblech/xmltodict for details
|
||||
XML Document converted to a Dictionary. See https://github.com/martinblech/xmltodict
|
||||
for details.
|
||||
|
||||
{
|
||||
"key1": string/object,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
jc - JSON Convert `YAML` file parser
|
||||
|
||||
Note: datetime objects will be converted to strings.
|
||||
> Note: `datetime` objects will be converted to strings.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -5,10 +5,7 @@
|
||||
|
||||
jc - JSON Convert `zipinfo` command output parser
|
||||
|
||||
Options supported:
|
||||
- none
|
||||
|
||||
Note: The default listing format.
|
||||
> Note: No `zipinfo` options are supported.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -26,11 +26,12 @@ https://github.com/kellyjonbrazil/jc/tree/master/docs
|
||||
|
||||
### Specific Version
|
||||
|
||||
Replace `<full_version_number>` - e.g. `1.17.7`:
|
||||
|
||||
`https://github.com/kellyjonbrazil/jc/tree/v<full_version_number>/docs`
|
||||
|
||||
Specific versions can also be selected by tag in the branch dropdown menu.
|
||||
> Replace `<full_version_number>` - e.g. `1.18.0`:
|
||||
|
||||
Specific versions can also be selected by tag in the branch Github dropdown
|
||||
menu.
|
||||
|
||||
## Usage Example
|
||||
|
||||
@@ -93,14 +94,14 @@ its module name.
|
||||
|
||||
### parser_mod_list
|
||||
|
||||
parser_mod_list() -> list
|
||||
parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of all available parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`.
|
||||
|
||||
### plugin_parser_mod_list
|
||||
|
||||
plugin_parser_mod_list() -> list
|
||||
plugin_parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of plugin parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
|
||||
@@ -108,7 +109,7 @@ Get a list of plugin parser module names to be used in
|
||||
|
||||
### standard_parser_mod_list
|
||||
|
||||
standard_parser_mod_list() -> list
|
||||
standard_parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of standard parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
|
||||
@@ -116,7 +117,7 @@ Get a list of standard parser module names to be used in
|
||||
|
||||
### streaming_parser_mod_list
|
||||
|
||||
streaming_parser_mod_list() -> list
|
||||
streaming_parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of streaming parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* [jc.utils](#jc.utils)
|
||||
* [warning\_message](#jc.utils.warning_message)
|
||||
* [error\_message](#jc.utils.error_message)
|
||||
* [is\_compatible](#jc.utils.is_compatible)
|
||||
* [compatibility](#jc.utils.compatibility)
|
||||
* [has\_data](#jc.utils.has_data)
|
||||
* [convert\_to\_int](#jc.utils.convert_to_int)
|
||||
@@ -26,8 +27,8 @@ jc - JSON Convert utils
|
||||
def warning_message(message_lines: List[str]) -> None
|
||||
```
|
||||
|
||||
Prints warning message for non-fatal issues. The first line is
|
||||
prepended with 'jc: Warning - ' and subsequent lines are indented.
|
||||
Prints warning message to `STDERR` for non-fatal issues. The first line
|
||||
is prepended with 'jc: Warning - ' and subsequent lines are indented.
|
||||
Wraps text as needed based on the terminal width.
|
||||
|
||||
Parameters:
|
||||
@@ -46,7 +47,7 @@ Returns:
|
||||
def error_message(message_lines: List[str]) -> None
|
||||
```
|
||||
|
||||
Prints an error message for fatal issues. The first line is
|
||||
Prints an error message to `STDERR` for fatal issues. The first line is
|
||||
prepended with 'jc: Error - ' and subsequent lines are indented.
|
||||
Wraps text as needed based on the terminal width.
|
||||
|
||||
@@ -58,6 +59,16 @@ Returns:
|
||||
|
||||
None - just prints output to STDERR
|
||||
|
||||
<a id="jc.utils.is_compatible"></a>
|
||||
|
||||
### is\_compatible
|
||||
|
||||
```python
|
||||
def is_compatible(compatible: List) -> bool
|
||||
```
|
||||
|
||||
Returns True if the parser is compatible with the running OS platform.
|
||||
|
||||
<a id="jc.utils.compatibility"></a>
|
||||
|
||||
### compatibility
|
||||
@@ -68,8 +79,8 @@ def compatibility(mod_name: str,
|
||||
quiet: bool = False) -> None
|
||||
```
|
||||
|
||||
Checks for the parser's compatibility with the running OS
|
||||
platform.
|
||||
Checks for the parser's compatibility with the running OS platform and
|
||||
prints a warning message to `STDERR` if not compatible and quiet=False.
|
||||
|
||||
Parameters:
|
||||
|
||||
|
||||
@@ -22,11 +22,12 @@ https://github.com/kellyjonbrazil/jc/tree/master/docs
|
||||
|
||||
### Specific Version
|
||||
|
||||
Replace `<full_version_number>` - e.g. `1.17.7`:
|
||||
|
||||
`https://github.com/kellyjonbrazil/jc/tree/v<full_version_number>/docs`
|
||||
|
||||
Specific versions can also be selected by tag in the branch dropdown menu.
|
||||
> Replace `<full_version_number>` - e.g. `1.18.0`:
|
||||
|
||||
Specific versions can also be selected by tag in the branch Github dropdown
|
||||
menu.
|
||||
|
||||
## Usage Example
|
||||
|
||||
@@ -89,14 +90,14 @@ its module name.
|
||||
|
||||
### parser_mod_list
|
||||
|
||||
parser_mod_list() -> list
|
||||
parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of all available parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`.
|
||||
|
||||
### plugin_parser_mod_list
|
||||
|
||||
plugin_parser_mod_list() -> list
|
||||
plugin_parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of plugin parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
|
||||
@@ -104,7 +105,7 @@ Get a list of plugin parser module names to be used in
|
||||
|
||||
### standard_parser_mod_list
|
||||
|
||||
standard_parser_mod_list() -> list
|
||||
standard_parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of standard parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
|
||||
@@ -112,7 +113,7 @@ Get a list of standard parser module names to be used in
|
||||
|
||||
### streaming_parser_mod_list
|
||||
|
||||
streaming_parser_mod_list() -> list
|
||||
streaming_parser_mod_list() -> list[str]
|
||||
|
||||
Get a list of streaming parser module names to be used in
|
||||
`parse()`, `parser_info()`, and `get_help()`. This list is a subset of
|
||||
|
||||
159
jc/cli.py
159
jc/cli.py
@@ -2,15 +2,16 @@
|
||||
JC cli module
|
||||
"""
|
||||
|
||||
import io
|
||||
import sys
|
||||
import os
|
||||
import textwrap
|
||||
import signal
|
||||
import shlex
|
||||
import subprocess
|
||||
import json
|
||||
from .lib import (__version__, parser_info, all_parser_info, parsers,
|
||||
_get_parser, _parser_is_streaming)
|
||||
_get_parser, _parser_is_streaming, standard_parser_mod_list,
|
||||
plugin_parser_mod_list, streaming_parser_mod_list)
|
||||
from . import utils
|
||||
from . import tracebackplus
|
||||
from .exceptions import LibraryNotInstalled, ParseError
|
||||
@@ -21,13 +22,12 @@ try:
|
||||
from pygments import highlight
|
||||
from pygments.style import Style
|
||||
from pygments.token import (Name, Number, String, Keyword)
|
||||
from pygments.lexers import JsonLexer
|
||||
from pygments.lexers.data import JsonLexer, YamlLexer
|
||||
from pygments.formatters import Terminal256Formatter
|
||||
PYGMENTS_INSTALLED = True
|
||||
except Exception:
|
||||
PYGMENTS_INSTALLED = False
|
||||
|
||||
|
||||
JC_ERROR_EXIT = 100
|
||||
|
||||
|
||||
@@ -84,26 +84,6 @@ if PYGMENTS_INSTALLED:
|
||||
}
|
||||
|
||||
|
||||
def safe_print_json(string, pretty=None, env_colors=None, mono=None,
|
||||
piped_out=None, flush=None):
|
||||
"""Safely prints JSON output in both UTF-8 and ASCII systems"""
|
||||
try:
|
||||
print(json_out(string,
|
||||
pretty=pretty,
|
||||
env_colors=env_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_out),
|
||||
flush=flush)
|
||||
except UnicodeEncodeError:
|
||||
print(json_out(string,
|
||||
pretty=pretty,
|
||||
env_colors=env_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_out,
|
||||
ascii_only=True),
|
||||
flush=flush)
|
||||
|
||||
|
||||
def set_env_colors(env_colors=None):
|
||||
"""
|
||||
Return a dictionary to be used in Pygments custom style class.
|
||||
@@ -154,7 +134,7 @@ def set_env_colors(env_colors=None):
|
||||
|
||||
def piped_output(force_color):
|
||||
"""
|
||||
Return False if stdout is a TTY. True if output is being piped to
|
||||
Return False if `STDOUT` is a TTY. True if output is being piped to
|
||||
another program and foce_color is True. This allows forcing of ANSI
|
||||
color codes even when using pipes.
|
||||
"""
|
||||
@@ -200,6 +180,9 @@ def about_jc():
|
||||
'python_version': '.'.join((str(sys.version_info.major), str(sys.version_info.minor), str(sys.version_info.micro))),
|
||||
'python_path': sys.executable,
|
||||
'parser_count': len(all_parser_info()),
|
||||
'standard_parser_count': len(standard_parser_mod_list()),
|
||||
'streaming_parser_count': len(streaming_parser_mod_list()),
|
||||
'plugin_parser_count': len(plugin_parser_mod_list()),
|
||||
'parsers': all_parser_info()
|
||||
}
|
||||
|
||||
@@ -230,6 +213,7 @@ def helptext():
|
||||
-r raw JSON output
|
||||
-u unbuffer output
|
||||
-v version info
|
||||
-y YAML output
|
||||
|
||||
Examples:
|
||||
Standard Syntax:
|
||||
@@ -283,11 +267,52 @@ def versiontext():
|
||||
return textwrap.dedent(versiontext_string)
|
||||
|
||||
|
||||
def yaml_out(data, pretty=False, env_colors=None, mono=False, piped_out=False, ascii_only=False):
|
||||
"""
|
||||
Return a YAML formatted string. String may include color codes. If the
|
||||
YAML library is not installed, output will fall back to JSON with a
|
||||
warning message to STDERR"""
|
||||
# make ruamel.yaml import optional
|
||||
try:
|
||||
from ruamel.yaml import YAML
|
||||
YAML_INSTALLED = True
|
||||
except Exception:
|
||||
YAML_INSTALLED = False
|
||||
|
||||
if YAML_INSTALLED:
|
||||
y_string_buf = io.BytesIO()
|
||||
# monkey patch to disable plugins since we don't use them and in
|
||||
# ruamel.yaml versions prior to 0.17.0 the use of __file__ in the
|
||||
# plugin code is incompatible with the pyoxidizer packager
|
||||
YAML.official_plug_ins = lambda a: []
|
||||
yaml=YAML()
|
||||
yaml.default_flow_style = False
|
||||
yaml.explicit_start = True
|
||||
yaml.allow_unicode = not ascii_only
|
||||
yaml.encoding = 'utf-8'
|
||||
yaml.dump(data, y_string_buf)
|
||||
y_string = y_string_buf.getvalue().decode('utf-8')[:-1]
|
||||
|
||||
if not mono and not piped_out:
|
||||
# set colors
|
||||
class JcStyle(Style):
|
||||
styles = set_env_colors(env_colors)
|
||||
|
||||
return str(highlight(y_string, YamlLexer(), Terminal256Formatter(style=JcStyle))[0:-1])
|
||||
|
||||
return y_string
|
||||
|
||||
utils.warning_message(['YAML Library not installed. Reverting to JSON output.'])
|
||||
return json_out(data, pretty=pretty, env_colors=env_colors, mono=mono, piped_out=piped_out, ascii_only=ascii_only)
|
||||
|
||||
|
||||
def json_out(data, pretty=False, env_colors=None, mono=False, piped_out=False, ascii_only=False):
|
||||
"""
|
||||
Return a JSON formatted string. String may include color codes or be
|
||||
pretty printed.
|
||||
"""
|
||||
import json
|
||||
|
||||
separators = (',', ':')
|
||||
indent = None
|
||||
|
||||
@@ -307,6 +332,44 @@ def json_out(data, pretty=False, env_colors=None, mono=False, piped_out=False, a
|
||||
return j_string
|
||||
|
||||
|
||||
def safe_print_out(list_or_dict, pretty=None, env_colors=None, mono=None,
|
||||
piped_out=None, flush=None, yaml=None):
|
||||
"""Safely prints JSON or YAML output in both UTF-8 and ASCII systems"""
|
||||
if yaml:
|
||||
try:
|
||||
print(yaml_out(list_or_dict,
|
||||
pretty=pretty,
|
||||
env_colors=env_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_out),
|
||||
flush=flush)
|
||||
except UnicodeEncodeError:
|
||||
print(yaml_out(list_or_dict,
|
||||
pretty=pretty,
|
||||
env_colors=env_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_out,
|
||||
ascii_only=True),
|
||||
flush=flush)
|
||||
|
||||
else:
|
||||
try:
|
||||
print(json_out(list_or_dict,
|
||||
pretty=pretty,
|
||||
env_colors=env_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_out),
|
||||
flush=flush)
|
||||
except UnicodeEncodeError:
|
||||
print(json_out(list_or_dict,
|
||||
pretty=pretty,
|
||||
env_colors=env_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_out,
|
||||
ascii_only=True),
|
||||
flush=flush)
|
||||
|
||||
|
||||
def magic_parser(args):
|
||||
"""
|
||||
Parse command arguments for magic syntax: jc -p ls -al
|
||||
@@ -435,6 +498,7 @@ def main():
|
||||
raw = 'r' in options
|
||||
unbuffer = 'u' in options
|
||||
version_info = 'v' in options
|
||||
yaml_out = 'y' in options
|
||||
|
||||
if verbose_debug:
|
||||
tracebackplus.enable(context=11)
|
||||
@@ -443,11 +507,12 @@ def main():
|
||||
mono = True
|
||||
|
||||
if about:
|
||||
safe_print_json(about_jc(),
|
||||
pretty=pretty,
|
||||
env_colors=jc_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_output(force_color))
|
||||
safe_print_out(about_jc(),
|
||||
pretty=pretty,
|
||||
env_colors=jc_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_output(force_color),
|
||||
yaml=yaml_out)
|
||||
sys.exit(0)
|
||||
|
||||
if help_me:
|
||||
@@ -534,12 +599,13 @@ def main():
|
||||
quiet=quiet,
|
||||
ignore_exceptions=ignore_exceptions)
|
||||
for line in result:
|
||||
safe_print_json(line,
|
||||
pretty=pretty,
|
||||
env_colors=jc_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_output(force_color),
|
||||
flush=unbuffer)
|
||||
safe_print_out(line,
|
||||
pretty=pretty,
|
||||
env_colors=jc_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_output(force_color),
|
||||
flush=unbuffer,
|
||||
yaml=yaml_out)
|
||||
|
||||
sys.exit(combined_exit_code(magic_exit_code, 0))
|
||||
|
||||
@@ -550,12 +616,13 @@ def main():
|
||||
raw=raw,
|
||||
quiet=quiet)
|
||||
|
||||
safe_print_json(result,
|
||||
pretty=pretty,
|
||||
env_colors=jc_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_output(force_color),
|
||||
flush=unbuffer)
|
||||
safe_print_out(result,
|
||||
pretty=pretty,
|
||||
env_colors=jc_colors,
|
||||
mono=mono,
|
||||
piped_out=piped_output(force_color),
|
||||
flush=unbuffer,
|
||||
yaml=yaml_out)
|
||||
|
||||
sys.exit(combined_exit_code(magic_exit_code, 0))
|
||||
|
||||
@@ -570,14 +637,6 @@ def main():
|
||||
])
|
||||
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
|
||||
|
||||
except json.JSONDecodeError:
|
||||
if debug:
|
||||
raise
|
||||
|
||||
utils.error_message(['There was an issue generating the JSON output.',
|
||||
'For details use the -d or -dd option.'])
|
||||
sys.exit(combined_exit_code(magic_exit_code, JC_ERROR_EXIT))
|
||||
|
||||
except Exception:
|
||||
if debug:
|
||||
raise
|
||||
|
||||
@@ -6,7 +6,7 @@ import importlib
|
||||
from typing import Dict, List, Iterable, Union, Iterator
|
||||
from jc import appdirs
|
||||
|
||||
__version__ = '1.18.8'
|
||||
__version__ = '1.20.0'
|
||||
|
||||
parsers = [
|
||||
'acpi',
|
||||
@@ -16,6 +16,7 @@ parsers = [
|
||||
'asciitable',
|
||||
'asciitable-m',
|
||||
'blkid',
|
||||
'chage',
|
||||
'cksum',
|
||||
'crontab',
|
||||
'crontab-u',
|
||||
@@ -34,6 +35,7 @@ parsers = [
|
||||
'free',
|
||||
'fstab',
|
||||
'git-log',
|
||||
'git-log-s',
|
||||
'group',
|
||||
'gshadow',
|
||||
'hash',
|
||||
@@ -89,6 +91,8 @@ parsers = [
|
||||
'systeminfo',
|
||||
'time',
|
||||
'timedatectl',
|
||||
'top',
|
||||
'top-s',
|
||||
'tracepath',
|
||||
'traceroute',
|
||||
'ufw',
|
||||
|
||||
@@ -3,7 +3,12 @@
|
||||
This parser converts ASCII and Unicode text tables with single-line rows.
|
||||
|
||||
Column headers must be at least two spaces apart from each other and must
|
||||
be unique.
|
||||
be unique. For best results, column headers should be left-justified. If
|
||||
column separators are present, then non-left-justified headers will be fixed
|
||||
automatically.
|
||||
|
||||
Row separators are optional and are ignored. Each non-row-separator line is
|
||||
considered a separate row in the table.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -117,7 +122,7 @@ from jc.parsers.universal import sparse_table_parse
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
version = '1.1'
|
||||
description = 'ASCII and Unicode table parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -222,18 +227,20 @@ def _is_separator(line: str) -> bool:
|
||||
|
||||
def _snake_case(line: str) -> str:
|
||||
"""
|
||||
replace spaces between words and special characters with an underscore
|
||||
and set to lowercase
|
||||
Replace spaces between words and special characters with an underscore
|
||||
and set to lowercase. Ignore the replacement char (�) used for header
|
||||
padding.
|
||||
"""
|
||||
line = re.sub(r'[^a-zA-Z0-9 ]', '_', line)
|
||||
return re.sub(r'\b \b', '_', line).lower()
|
||||
line = re.sub(r'[^a-zA-Z0-9� ]', '_', line) # special characters
|
||||
line = re.sub(r'\b \b', '_', line).lower() # spaces betwee words
|
||||
return line
|
||||
|
||||
|
||||
def _normalize_rows(table: str) -> List[str]:
|
||||
"""
|
||||
returns a List of row strings. Header is snake-cased
|
||||
"""
|
||||
result = []
|
||||
result: List[str] = []
|
||||
for line in table.splitlines():
|
||||
# skip blank lines
|
||||
if not line.strip():
|
||||
@@ -243,7 +250,36 @@ def _normalize_rows(table: str) -> List[str]:
|
||||
if _is_separator(line):
|
||||
continue
|
||||
|
||||
# data row - remove column separators
|
||||
# header or data row found - remove column separators
|
||||
if not result: # this is the header row
|
||||
# normalize the separator
|
||||
line = line.replace('│', '|')\
|
||||
.replace('┃', '|')\
|
||||
.replace('┆', '|')\
|
||||
.replace('┇', '|')\
|
||||
.replace('┊', '|')\
|
||||
.replace('┋', '|')\
|
||||
.replace('╎', '|')\
|
||||
.replace('╏', '|')\
|
||||
.replace('║', '|')
|
||||
|
||||
# find the number of chars to pad in front of headers that are too
|
||||
# far away from the separator. Replace spaces with unicode char: �
|
||||
# we will remove this char from headers after sparse_table_parse
|
||||
problem_header_pattern = re.compile(r'(?:\| )( +)([^|]+)')
|
||||
problem_headers = problem_header_pattern.findall(line)
|
||||
if problem_headers:
|
||||
for p_header in problem_headers:
|
||||
old_header = p_header[0] + p_header[1]
|
||||
sub_chars = '�' * len(p_header[0])
|
||||
new_header = sub_chars + p_header[1]
|
||||
line = line.replace(old_header, new_header)
|
||||
|
||||
line = line.replace('|', ' ')
|
||||
result.append(_snake_case(line))
|
||||
continue
|
||||
|
||||
# this is a data row
|
||||
line = line.replace('|', ' ')\
|
||||
.replace('│', ' ')\
|
||||
.replace('┃', ' ')\
|
||||
@@ -256,7 +292,6 @@ def _normalize_rows(table: str) -> List[str]:
|
||||
.replace('║', ' ')
|
||||
result.append(line)
|
||||
|
||||
result[0] = _snake_case(result[0])
|
||||
return result
|
||||
|
||||
|
||||
@@ -266,7 +301,8 @@ def _fixup_headers(table: List[Dict]) -> List[Dict]:
|
||||
for row in table:
|
||||
new_row = row.copy()
|
||||
for k in row:
|
||||
k_new = k
|
||||
# remove replacement character
|
||||
k_new = k.replace('�', '')
|
||||
# remove consecutive underscores
|
||||
k_new = re.sub(r'__+', '_', k_new)
|
||||
# remove trailing underscores
|
||||
|
||||
@@ -24,6 +24,12 @@ Headers (keys) are converted to snake-case and newlines between multi-line
|
||||
headers are joined with an underscore. All values are returned as strings,
|
||||
except empty strings, which are converted to None/null.
|
||||
|
||||
> Note: table column separator characters (e.g. `|`) cannot be present
|
||||
> inside the cell data. If detected, a warning message will be printed to
|
||||
> `STDERR` and the line will be skipped. The warning message can be
|
||||
> suppressed by using the `-q` command option or by setting `quiet=True` in
|
||||
> `parse()`.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ cat table.txt | jc --asciitable-m
|
||||
@@ -101,7 +107,7 @@ from jc.exceptions import ParseError
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
version = '1.1'
|
||||
description = 'multi-line ASCII and Unicode table parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -377,20 +383,27 @@ def _collapse_headers(table: List[List[str]]) -> List[str]:
|
||||
return result
|
||||
|
||||
|
||||
def _collapse_data(table: List[List[List[str]]]) -> List[List[str]]:
|
||||
def _collapse_data(table: List[List[List[str]]], quiet=False) -> List[List[str]]:
|
||||
"""combine data rows to return a simple list of lists"""
|
||||
result: List[List[str]] = []
|
||||
|
||||
for row in table:
|
||||
new_row: List[str] = []
|
||||
for line in row:
|
||||
if new_row:
|
||||
for i, item in enumerate(line):
|
||||
new_row[i] = (new_row[i] + '\n' + item).strip()
|
||||
else:
|
||||
new_row = line
|
||||
for index, row in enumerate(table):
|
||||
try:
|
||||
new_row: List[str] = []
|
||||
for line in row:
|
||||
if new_row:
|
||||
for i, item in enumerate(line):
|
||||
new_row[i] = (new_row[i] + '\n' + item).strip()
|
||||
else:
|
||||
new_row = line
|
||||
|
||||
result.append(new_row)
|
||||
result.append(new_row)
|
||||
except IndexError:
|
||||
if not quiet:
|
||||
row_string = '\n'.join([' | '.join(l) for l in row])
|
||||
jc.utils.warning_message(
|
||||
[f'Possible table separator character found in row {index}: {row_string}. Skipping.']
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
@@ -409,14 +422,14 @@ def _create_table_dict(header: List[str], data: List[List[str]]) -> List[Dict[st
|
||||
return table_list_dict
|
||||
|
||||
|
||||
def _parse_pretty(string: str) -> List[Dict[str, Optional[str]]]:
|
||||
def _parse_pretty(string: str, quiet: bool =False) -> List[Dict[str, Optional[str]]]:
|
||||
string_lines: List[str] = string.splitlines()
|
||||
clean: List[Tuple[int, List[str]]] = _normalize_rows(string_lines)
|
||||
raw_headers: List[List[str]] = _get_headers(clean)
|
||||
raw_data: List[List[List[str]]] = _get_data(clean)
|
||||
|
||||
new_headers: List[str] = _collapse_headers(raw_headers)
|
||||
new_data: List[List[str]] = _collapse_data(raw_data)
|
||||
new_data: List[List[str]] = _collapse_data(raw_data, quiet)
|
||||
final_table: List[Dict[str, Optional[str]]] = _create_table_dict(new_headers, new_data)
|
||||
|
||||
return final_table
|
||||
@@ -452,7 +465,7 @@ def parse(
|
||||
table_type = _table_sniff(data)
|
||||
|
||||
if table_type == 'pretty':
|
||||
raw_output = _parse_pretty(data)
|
||||
raw_output = _parse_pretty(data, quiet)
|
||||
elif table_type == 'markdown':
|
||||
raise ParseError('Only "pretty" tables supported with multiline. "markdown" table detected. Please try the "asciitable" parser.')
|
||||
else:
|
||||
|
||||
151
jc/parsers/chage.py
Normal file
151
jc/parsers/chage.py
Normal file
@@ -0,0 +1,151 @@
|
||||
"""jc - JSON Convert `chage --list` command output parser
|
||||
|
||||
Supports `chage -l <username>` or `chage --list <username>`
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ chage -l johndoe | jc --chage
|
||||
|
||||
or
|
||||
|
||||
$ jc chage -l johndoe
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('chage', chage_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"password_last_changed": string,
|
||||
"password_expires": string,
|
||||
"password_inactive": string,
|
||||
"account_expires": string,
|
||||
"min_days_between_password_change": integer,
|
||||
"max_days_between_password_change": integer,
|
||||
"warning_days_before_password_expires": integer
|
||||
}
|
||||
|
||||
Examples:
|
||||
|
||||
$ chage --list joeuser | jc --chage -p
|
||||
{
|
||||
"password_last_changed": "never",
|
||||
"password_expires": "never",
|
||||
"password_inactive": "never",
|
||||
"account_expires": "never",
|
||||
"min_days_between_password_change": 0,
|
||||
"max_days_between_password_change": 99999,
|
||||
"warning_days_before_password_expires": 7
|
||||
}
|
||||
|
||||
$ chage --list joeuser | jc --chage -p -r
|
||||
{
|
||||
"password_last_changed": "never",
|
||||
"password_expires": "never",
|
||||
"password_inactive": "never",
|
||||
"account_expires": "never",
|
||||
"min_days_between_password_change": "0",
|
||||
"max_days_between_password_change": "99999",
|
||||
"warning_days_before_password_expires": "7"
|
||||
}
|
||||
"""
|
||||
from typing import List, Dict
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
description = '`chage --list` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux']
|
||||
magic_commands = ['chage --list', 'chage -l']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _process(proc_data: Dict) -> Dict:
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (Dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Structured to conform to the schema.
|
||||
"""
|
||||
int_list = ['min_days_between_password_change', 'max_days_between_password_change',
|
||||
'warning_days_before_password_expires']
|
||||
|
||||
for key in proc_data:
|
||||
if key in int_list:
|
||||
proc_data[key] = jc.utils.convert_to_int(proc_data[key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
def parse(
|
||||
data: str,
|
||||
raw: bool = False,
|
||||
quiet: bool = False
|
||||
) -> Dict:
|
||||
"""
|
||||
Main text parsing function
|
||||
|
||||
Parameters:
|
||||
|
||||
data: (string) text data to parse
|
||||
raw: (boolean) unprocessed output if True
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
jc.utils.input_type_check(data)
|
||||
|
||||
raw_output: Dict = {}
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
|
||||
for line in filter(None, data.splitlines()):
|
||||
key, val = line.split(':', maxsplit=1)
|
||||
key = key.strip()
|
||||
val = val.strip()
|
||||
|
||||
if key == 'Last password change':
|
||||
raw_output['password_last_changed'] = val
|
||||
continue
|
||||
|
||||
if key == 'Password expires':
|
||||
raw_output['password_expires'] = val
|
||||
continue
|
||||
|
||||
if key == 'Password inactive':
|
||||
raw_output['password_inactive'] = val
|
||||
continue
|
||||
|
||||
if key == 'Account expires':
|
||||
raw_output['account_expires'] = val
|
||||
continue
|
||||
|
||||
if key == 'Minimum number of days between password change':
|
||||
raw_output['min_days_between_password_change'] = val
|
||||
continue
|
||||
|
||||
if key == 'Maximum number of days between password change':
|
||||
raw_output['max_days_between_password_change'] = val
|
||||
continue
|
||||
|
||||
if key == 'Number of days of warning before password expires':
|
||||
raw_output['warning_days_before_password_expires'] = val
|
||||
continue
|
||||
|
||||
return raw_output if raw else _process(raw_output)
|
||||
@@ -1,14 +1,14 @@
|
||||
"""jc - JSON Convert `csv` file streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
The `csv` streaming 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.
|
||||
|
||||
Note: The first 100 rows are read into memory to enable delimiter detection,
|
||||
then the rest of the rows are loaded lazily.
|
||||
> Note: The first 100 rows are read into memory to enable delimiter
|
||||
> detection, then the rest of the rows are loaded lazily.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -95,7 +95,7 @@ def _process(proc_data):
|
||||
@add_jc_meta
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -106,13 +106,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -99,7 +99,7 @@ import jc.parsers.universal
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.9'
|
||||
version = '1.10'
|
||||
description = '`df` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -208,7 +208,9 @@ def parse(data, raw=False, quiet=False):
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
jc.utils.input_type_check(data)
|
||||
|
||||
cleandata = data.splitlines()
|
||||
# remove blank lines
|
||||
cleandata = list(filter(None, data.splitlines()))
|
||||
|
||||
fix_data = []
|
||||
raw_output = []
|
||||
filesystem_map = {}
|
||||
|
||||
@@ -14,7 +14,7 @@ time of the system the parser is run on)
|
||||
|
||||
Usage (cli):
|
||||
|
||||
C:> dir | jc --dir
|
||||
C:\> dir | jc --dir
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -37,7 +37,7 @@ Schema:
|
||||
|
||||
Examples:
|
||||
|
||||
C:> dir | jc --dir -p
|
||||
C:\> dir | jc --dir -p
|
||||
[
|
||||
{
|
||||
"date": "03/24/2021",
|
||||
@@ -78,7 +78,7 @@ Examples:
|
||||
...
|
||||
]
|
||||
|
||||
C:> dir | jc --dir -p -r
|
||||
C:\> dir | jc --dir -p -r
|
||||
[
|
||||
{
|
||||
"date": "03/24/2021",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `foo` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
<<Short foo description and caveats>>
|
||||
|
||||
@@ -40,7 +40,7 @@ Examples:
|
||||
{example output}
|
||||
...
|
||||
"""
|
||||
from typing import Dict, Iterable, Generator, Union
|
||||
from typing import Dict, Iterable, Union
|
||||
import jc.utils
|
||||
from jc.streaming import (
|
||||
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
|
||||
@@ -90,9 +90,9 @@ def parse(
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]:
|
||||
) -> Union[Iterable[Dict], tuple]:
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -103,13 +103,10 @@ def parse(
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -38,8 +38,8 @@ Schema:
|
||||
"author": string,
|
||||
"author_email": string,
|
||||
"date": string,
|
||||
"epoch": integer, [0]
|
||||
"epoch_utc": integer, [1]
|
||||
"epoch": integer, # [0]
|
||||
"epoch_utc": integer, # [1]
|
||||
"commit_by": string,
|
||||
"commit_by_email": string,
|
||||
"commit_by_date": string,
|
||||
@@ -148,12 +148,12 @@ import re
|
||||
from typing import List, Dict
|
||||
import jc.utils
|
||||
|
||||
hash_pattern = re.compile(r'([0-9]|[a-f])+')
|
||||
hash_pattern = re.compile(r'(?:[0-9]|[a-f]){40}')
|
||||
changes_pattern = re.compile(r'\s(?P<files>\d+)\s+(files? changed),\s+(?P<insertions>\d+)\s(insertions?\(\+\))?(,\s+)?(?P<deletions>\d+)?(\s+deletions?\(\-\))?')
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
version = '1.1'
|
||||
description = '`git log` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -234,7 +234,7 @@ def parse(
|
||||
line_list = line.split(maxsplit=1)
|
||||
|
||||
# oneline style
|
||||
if line_list and _is_commit_hash(line_list[0]):
|
||||
if not line.startswith(' ') and line_list and _is_commit_hash(line_list[0]):
|
||||
if output_line:
|
||||
if file_list:
|
||||
output_line['stats']['files'] = file_list
|
||||
|
||||
282
jc/parsers/git_log_s.py
Normal file
282
jc/parsers/git_log_s.py
Normal file
@@ -0,0 +1,282 @@
|
||||
"""jc - JSON Convert `git log` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Can be used with the following format options:
|
||||
- `oneline`
|
||||
- `short`
|
||||
- `medium`
|
||||
- `full`
|
||||
- `fuller`
|
||||
|
||||
Additional options supported:
|
||||
- `--stat`
|
||||
- `--shortstat`
|
||||
|
||||
The `epoch` calculated timestamp field is naive. (i.e. based on the
|
||||
local time of the system the parser is run on)
|
||||
|
||||
The `epoch_utc` calculated timestamp field is timezone-aware and is
|
||||
only available if the timezone field is UTC.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ git log | jc --git-log-s
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
|
||||
result = jc.parse('git_log_s', git_log_command_output.splitlines())
|
||||
for item in result:
|
||||
# do something
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"commit": string,
|
||||
"author": string,
|
||||
"author_email": string,
|
||||
"date": string,
|
||||
"epoch": integer, # [0]
|
||||
"epoch_utc": integer, # [1]
|
||||
"commit_by": string,
|
||||
"commit_by_email": string,
|
||||
"commit_by_date": string,
|
||||
"message": string,
|
||||
"stats" : {
|
||||
"files_changed": integer,
|
||||
"insertions": integer,
|
||||
"deletions": integer,
|
||||
"files": [
|
||||
string
|
||||
]
|
||||
}
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
"success": boolean, # false if error parsing
|
||||
"error": string, # exists if "success" is false
|
||||
"line": string # exists if "success" is false
|
||||
}
|
||||
}
|
||||
|
||||
[0] naive timestamp if "date" field is parsable, else null
|
||||
[1] timezone aware timestamp availabe for UTC, else null
|
||||
|
||||
Examples:
|
||||
|
||||
$ git log | jc --git-log-s
|
||||
{"commit":"a730ae18c8e81c5261db132df73cd74f272a0a26","author":"Kelly...}
|
||||
{"commit":"930bf439c06c48a952baec05a9896c8d92b7693e","author":"Kelly...}
|
||||
...
|
||||
"""
|
||||
import re
|
||||
from typing import List, Dict, Iterable, Union
|
||||
import jc.utils
|
||||
from jc.streaming import (
|
||||
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
|
||||
)
|
||||
from jc.exceptions import ParseError
|
||||
|
||||
|
||||
hash_pattern = re.compile(r'(?:[0-9]|[a-f]){40}')
|
||||
changes_pattern = re.compile(r'\s(?P<files>\d+)\s+(files? changed),\s+(?P<insertions>\d+)\s(insertions?\(\+\))?(,\s+)?(?P<deletions>\d+)?(\s+deletions?\(\-\))?')
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.1'
|
||||
description = '`git log` command streaming parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
|
||||
streaming = True
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _process(proc_data: Dict) -> Dict:
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (Dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Structured data to conform to the schema.
|
||||
"""
|
||||
int_list = ['files_changed', 'insertions', 'deletions']
|
||||
|
||||
if 'date' in proc_data:
|
||||
ts = jc.utils.timestamp(proc_data['date'], format_hint=(1100,))
|
||||
proc_data['epoch'] = ts.naive
|
||||
proc_data['epoch_utc'] = ts.utc
|
||||
|
||||
if 'stats' in proc_data:
|
||||
for key in proc_data['stats']:
|
||||
if key in int_list:
|
||||
proc_data['stats'][key] = jc.utils.convert_to_int(proc_data['stats'][key])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
def _is_commit_hash(hash_string: str) -> bool:
|
||||
# 0c55240e9da30ac4293dc324f1094de2abd3da91
|
||||
if len(hash_string) != 40:
|
||||
return False
|
||||
|
||||
if hash_pattern.match(hash_string):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@add_jc_meta
|
||||
def parse(
|
||||
data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Iterable[Dict], tuple]:
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
data: (iterable) line-based text data to parse
|
||||
(e.g. sys.stdin or str.splitlines())
|
||||
|
||||
raw: (boolean) unprocessed output if True
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
|
||||
Returns:
|
||||
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
output_line: Dict = {}
|
||||
message_lines: List[str] = []
|
||||
file_list: List[str] = []
|
||||
|
||||
for line in data:
|
||||
try:
|
||||
streaming_line_input_type_check(line)
|
||||
|
||||
if line == '' or line == '\n':
|
||||
continue
|
||||
|
||||
line_list = line.rstrip().split(maxsplit=1)
|
||||
|
||||
# oneline style
|
||||
if not line.startswith(' ') and line_list and _is_commit_hash(line_list[0]):
|
||||
if output_line:
|
||||
if file_list:
|
||||
output_line['stats']['files'] = file_list
|
||||
|
||||
yield output_line if raw else _process(output_line)
|
||||
|
||||
output_line = {}
|
||||
message_lines = []
|
||||
file_list = []
|
||||
output_line = {
|
||||
'commit': line_list[0],
|
||||
'message': line_list[1]
|
||||
}
|
||||
continue
|
||||
|
||||
# all other styles
|
||||
if line.startswith('commit '):
|
||||
if output_line:
|
||||
if message_lines:
|
||||
output_line['message'] = '\n'.join(message_lines)
|
||||
|
||||
if file_list:
|
||||
output_line['stats']['files'] = file_list
|
||||
|
||||
yield output_line if raw else _process(output_line)
|
||||
|
||||
output_line = {}
|
||||
message_lines = []
|
||||
file_list = []
|
||||
output_line['commit'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('Merge: '):
|
||||
output_line['merge'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('Author: '):
|
||||
values = line_list[1].rsplit(maxsplit=1)
|
||||
output_line['author'] = values[0]
|
||||
output_line['author_email'] = values[1].strip('<').strip('>')
|
||||
continue
|
||||
|
||||
if line.startswith('Date: '):
|
||||
output_line['date'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('AuthorDate: '):
|
||||
output_line['date'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('CommitDate: '):
|
||||
output_line['commit_by_date'] = line_list[1]
|
||||
continue
|
||||
|
||||
if line.startswith('Commit: '):
|
||||
values = line_list[1].rsplit(maxsplit=1)
|
||||
output_line['commit_by'] = values[0]
|
||||
output_line['commit_by_email'] = values[1].strip('<').strip('>')
|
||||
continue
|
||||
|
||||
if line.startswith(' '):
|
||||
message_lines.append(line.strip())
|
||||
continue
|
||||
|
||||
if line.startswith(' ') and 'changed, ' not in line:
|
||||
# this is a file name
|
||||
file_name = line.split('|')[0].strip()
|
||||
file_list.append(file_name)
|
||||
continue
|
||||
|
||||
if line.startswith(' ') and 'changed, ' in line:
|
||||
# this is the stat summary
|
||||
changes = changes_pattern.match(line)
|
||||
if changes:
|
||||
files = changes['files']
|
||||
insertions = changes['insertions']
|
||||
deletions = changes['deletions']
|
||||
|
||||
output_line['stats'] = {
|
||||
'files_changed': files or '0',
|
||||
'insertions': insertions or '0',
|
||||
'deletions': deletions or '0'
|
||||
}
|
||||
continue
|
||||
|
||||
raise ParseError('Not git_log_s data')
|
||||
|
||||
except Exception as e:
|
||||
yield raise_or_yield(ignore_exceptions, e, line)
|
||||
|
||||
try:
|
||||
if output_line:
|
||||
if message_lines:
|
||||
output_line['message'] = '\n'.join(message_lines)
|
||||
|
||||
if file_list:
|
||||
output_line['stats']['files'] = file_list
|
||||
|
||||
yield output_line if raw else _process(output_line)
|
||||
|
||||
except Exception as e:
|
||||
yield raise_or_yield(ignore_exceptions, e, line)
|
||||
@@ -1,6 +1,6 @@
|
||||
"""jc - JSON Convert `ifconfig` command output parser
|
||||
|
||||
Note: No `ifconfig` options are supported.
|
||||
> Note: No `ifconfig` options are supported.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ Parses standard `INI` files and files containing simple key/value pairs.
|
||||
- If duplicate keys are found, only the last value will be used.
|
||||
|
||||
> Note: Values starting and ending with quotation marks will have the marks
|
||||
removed. If you would like to keep the quotation marks, use the `-r`
|
||||
command-line argument or the `raw=True` argument in `parse()`.
|
||||
> removed. If you would like to keep the quotation marks, use the `-r`
|
||||
> command-line argument or the `raw=True` argument in `parse()`.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -21,8 +21,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
ini or key/value document converted to a dictionary - see the
|
||||
configparser standard library documentation for more details.
|
||||
ini or key/value document converted to a dictionary - see the configparser
|
||||
standard library documentation for more details.
|
||||
|
||||
{
|
||||
"key1": string,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""jc - JSON Convert `iostat` command output parser
|
||||
|
||||
Note: `iostat` version 11 and higher include a JSON output option
|
||||
> Note: `iostat` version 11 and higher include a JSON output option
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
"""jc - JSON Convert `iostat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Note: `iostat` version 11 and higher include a JSON output option
|
||||
> Note: `iostat` version 11 and higher include a JSON output option
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ iostat | jc --iostat-s
|
||||
|
||||
> Note: When piping `jc` converted `iostat` output to other processes it may
|
||||
appear the output is hanging due to the OS pipe buffers. This is because
|
||||
`iostat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
option to unbuffer the `jc` output if you would like immediate output. See
|
||||
the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> appear the output is hanging due to the OS pipe buffers. This is because
|
||||
> `iostat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
> option to unbuffer the `jc` output if you would like immediate output. See
|
||||
> the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -163,7 +163,7 @@ def _create_obj_list(section_list, section_name):
|
||||
@add_jc_meta
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -174,13 +174,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -7,8 +7,8 @@ Supports files containing simple key/value pairs.
|
||||
- If duplicate keys are found, only the last value will be used.
|
||||
|
||||
> Note: Values starting and ending with quotation marks will have the marks
|
||||
removed. If you would like to keep the quotation marks, use the `-r`
|
||||
command-line argument or the `raw=True` argument in `parse()`.
|
||||
> removed. If you would like to keep the quotation marks, use the `-r`
|
||||
> command-line argument or the `raw=True` argument in `parse()`.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -21,8 +21,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
key/value document converted to a dictionary - see the
|
||||
configparser standard library documentation for more details.
|
||||
key/value document converted to a dictionary - see the configparser standard
|
||||
library documentation for more details.
|
||||
|
||||
{
|
||||
"key1": string,
|
||||
|
||||
@@ -4,11 +4,12 @@ Options supported:
|
||||
- `lbaR1`
|
||||
- `--time-style=full-iso`
|
||||
|
||||
Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly
|
||||
parse filenames that include newline characters. Since `ls` does not encode
|
||||
newlines in filenames when outputting to a pipe it will cause `jc` to see
|
||||
multiple files instead of a single file if `-1`, `-l`, or `-b` is not used.
|
||||
Alternatively, `vdir` can be used, which is the same as running `ls -lb`.
|
||||
> Note: The `-1`, `-l`, or `-b` option of `ls` should be used to correctly
|
||||
> parse filenames that include newline characters. Since `ls` does not
|
||||
> encode newlines in filenames when outputting to a pipe it will cause `jc`
|
||||
> to see multiple files instead of a single file if `-1`, `-l`, or `-b` is
|
||||
> not used. Alternatively, `vdir` can be used, which is the same as running
|
||||
> `ls -lb`.
|
||||
|
||||
The `epoch` calculated timestamp field is naive. (i.e. based on the local
|
||||
time of the system the parser is run on)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `ls` and `vdir` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Requires the `-l` option to be used on `ls`. If there are newline characters
|
||||
in the filename, then make sure to use the `-b` option on `ls`.
|
||||
@@ -118,7 +118,7 @@ def _process(proc_data):
|
||||
@add_jc_meta
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -129,13 +129,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -17,9 +17,9 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Note: <item> object keynames are assigned directly from the lsusb
|
||||
output. If there are duplicate <item> names in a section, only the
|
||||
last one is converted.
|
||||
> Note: <item> object keynames are assigned directly from the lsusb
|
||||
> output. If there are duplicate <item> names in a section, only the
|
||||
> last one is converted.
|
||||
|
||||
[
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""jc - JSON Convert `mpstat` command output parser
|
||||
|
||||
Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
> Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"""jc - JSON Convert `mpstat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
> Note: Latest versions of `mpstat` support JSON output (v11.5.1+)
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -90,7 +90,7 @@ Examples:
|
||||
{"cpu":"all","intr_s":"37.61","type":"interrupts","time":"03:15:06 PM"}
|
||||
...
|
||||
"""
|
||||
from typing import Dict, Iterable, Generator, Union
|
||||
from typing import Dict, Iterable, Union
|
||||
import jc.utils
|
||||
from jc.parsers.universal import simple_table_parse
|
||||
from jc.streaming import (
|
||||
@@ -145,9 +145,9 @@ def parse(
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]:
|
||||
) -> Union[Iterable[Dict], tuple]:
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -158,13 +158,9 @@ def parse(
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -24,18 +24,18 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Because there are so many options, the schema is not strictly defined.
|
||||
Integer and Float value conversions are attempted and the original
|
||||
values are kept if they fail. If you don't want automatic conversion,
|
||||
then use the -r or raw=True option to disable it.
|
||||
Because there are so many options, the schema is not strictly defined.
|
||||
Integer and Float value conversions are attempted and the original
|
||||
values are kept if they fail. If you don't want automatic conversion,
|
||||
then use the `-r` or `raw=True` option to disable it.
|
||||
|
||||
The structure is flat, for the most part, but there are a couple of
|
||||
"well-known" keys that are further parsed into objects for convenience.
|
||||
These are documented below.
|
||||
The structure is flat, for the most part, but there are a couple of
|
||||
"well-known" keys that are further parsed into objects for convenience.
|
||||
These are documented below.
|
||||
|
||||
[
|
||||
{
|
||||
"<key>": string/integer/float, [0]
|
||||
"<key>": string/integer/float, # [0]
|
||||
"dhcp4_option_x": {
|
||||
"name": string,
|
||||
"value": string/integer/float,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""jc - JSON Convert `pidstat` command output parser
|
||||
"""jc - JSON Convert `pidstat -h` command output parser
|
||||
|
||||
Must use the `-h` option in `pidstat`. All other `pidstat` options are
|
||||
supported in combination with `-h`.
|
||||
@@ -129,7 +129,7 @@ from jc.exceptions import ParseError
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
description = '`pidstat` command parser'
|
||||
description = '`pidstat -h` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux']
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `pidstat` command output streaming parser
|
||||
"""jc - JSON Convert `pidstat -h` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Must use the `-h` option in `pidstat`. All other `pidstat` options are
|
||||
supported in combination with `-h`.
|
||||
@@ -11,11 +11,11 @@ Usage (cli):
|
||||
$ pidstat | jc --pidstat-s
|
||||
|
||||
> Note: When piping `jc` converted `pidstat` output to other processes it
|
||||
may appear the output is hanging due to the OS pipe buffers. This is
|
||||
because `pidstat` output is too small to quickly fill up the buffer. Use
|
||||
the `-u` option to unbuffer the `jc` output if you would like immediate
|
||||
output. See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> may appear the output is hanging due to the OS pipe buffers. This is
|
||||
> because `pidstat` output is too small to quickly fill up the buffer. Use
|
||||
> the `-u` option to unbuffer the `jc` output if you would like immediate
|
||||
> output. See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -72,7 +72,7 @@ Examples:
|
||||
{"time":"1646859134","uid":"0","pid":"9","percent_usr":"0.00","perc...}
|
||||
...
|
||||
"""
|
||||
from typing import Dict, Iterable, Generator, Union
|
||||
from typing import Dict, Iterable, Union
|
||||
import jc.utils
|
||||
from jc.streaming import (
|
||||
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
|
||||
@@ -84,7 +84,7 @@ from jc.exceptions import ParseError
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
description = '`pidstat` command streaming parser'
|
||||
description = '`pidstat -h` command streaming parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux']
|
||||
@@ -126,9 +126,9 @@ def parse(
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]:
|
||||
) -> Union[Iterable[Dict], tuple]:
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -139,13 +139,9 @@ def parse(
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -4,8 +4,8 @@ Supports `ping` and `ping6` output.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
Note: Use the ping `-c` (count) option, otherwise data will not be
|
||||
piped to `jc`.
|
||||
> Note: Use the ping `-c` (count) option, otherwise data will not be
|
||||
> piped to `jc`.
|
||||
|
||||
$ ping -c 3 1.2.3.4 | jc --ping
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
"""jc - JSON Convert `ping` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Supports `ping` and `ping6` output.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ ping | jc --ping-s
|
||||
$ ping 1.2.3.4 | jc --ping-s
|
||||
|
||||
> Note: When piping `jc` converted `ping` output to other processes it may
|
||||
appear the output is hanging due to the OS pipe buffers. This is because
|
||||
`ping` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
option to unbuffer the `jc` output if you would like immediate output.
|
||||
See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> appear the output is hanging due to the OS pipe buffers. This is because
|
||||
> `ping` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
> option to unbuffer the `jc` output if you would like immediate output.
|
||||
> See the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -465,7 +465,7 @@ def _linux_parse(line, s):
|
||||
@add_jc_meta
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -476,13 +476,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -60,12 +60,13 @@ Examples:
|
||||
}
|
||||
]
|
||||
"""
|
||||
from typing import List, Dict, Optional
|
||||
import jc.utils
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.3'
|
||||
version = '1.4'
|
||||
description = '`pip show` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
@@ -76,7 +77,7 @@ class info():
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _process(proc_data):
|
||||
def _process(proc_data: List[Dict]) -> List[Dict]:
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
@@ -92,7 +93,11 @@ def _process(proc_data):
|
||||
return proc_data
|
||||
|
||||
|
||||
def parse(data, raw=False, quiet=False):
|
||||
def parse(
|
||||
data: str,
|
||||
raw: bool = False,
|
||||
quiet: bool = False
|
||||
) -> List[Dict]:
|
||||
"""
|
||||
Main text parsing function
|
||||
|
||||
@@ -109,8 +114,10 @@ def parse(data, raw=False, quiet=False):
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
jc.utils.input_type_check(data)
|
||||
|
||||
raw_output = []
|
||||
package = {}
|
||||
raw_output: List = []
|
||||
package: Dict = {}
|
||||
last_key: str = ''
|
||||
last_key_data: List = []
|
||||
|
||||
# Clear any blank lines
|
||||
cleandata = list(filter(None, data.splitlines()))
|
||||
@@ -119,21 +126,38 @@ def parse(data, raw=False, quiet=False):
|
||||
|
||||
for row in cleandata:
|
||||
if row.startswith('---'):
|
||||
if last_key_data:
|
||||
package[last_key] = package[last_key] + '\n' + '\n'.join(last_key_data)
|
||||
|
||||
raw_output.append(package)
|
||||
package = {}
|
||||
last_key = ''
|
||||
last_key_data = []
|
||||
continue
|
||||
|
||||
item_key = row.split(': ', maxsplit=1)[0].lower().replace('-', '_')
|
||||
item_value = row.split(': ', maxsplit=1)[1]
|
||||
if not row.startswith(' '):
|
||||
item_key = row.split(': ', maxsplit=1)[0].lower().replace('-', '_')
|
||||
item_value: Optional[str] = row.split(': ', maxsplit=1)[1]
|
||||
|
||||
if item_value == '':
|
||||
item_value = None
|
||||
if item_value == '':
|
||||
item_value = None
|
||||
|
||||
package.update({item_key: item_value})
|
||||
if last_key_data and last_key != item_key:
|
||||
package[last_key] = package[last_key] + '\n' + '\n'.join(last_key_data)
|
||||
last_key_data = []
|
||||
|
||||
raw_output.append(package)
|
||||
package[item_key] = item_value
|
||||
last_key = item_key
|
||||
continue
|
||||
|
||||
if raw:
|
||||
return raw_output
|
||||
else:
|
||||
return _process(raw_output)
|
||||
if row.startswith(' '):
|
||||
last_key_data.append(row.strip())
|
||||
continue
|
||||
|
||||
if package:
|
||||
if last_key_data:
|
||||
package[last_key] = package[last_key] + '\n' + '\n'.join(last_key_data)
|
||||
|
||||
raw_output.append(package)
|
||||
|
||||
return raw_output if raw else _process(raw_output)
|
||||
|
||||
@@ -17,20 +17,20 @@ Schema:
|
||||
|
||||
[
|
||||
{
|
||||
"destination": string,
|
||||
"gateway": string,
|
||||
"genmask": string,
|
||||
"flags": string,
|
||||
"destination": string,
|
||||
"gateway": string,
|
||||
"genmask": string,
|
||||
"flags": string,
|
||||
"flags_pretty": [
|
||||
string
|
||||
string
|
||||
]
|
||||
"metric": integer,
|
||||
"ref": integer,
|
||||
"use": integer,
|
||||
"mss": integer,
|
||||
"window": integer,
|
||||
"irtt": integer,
|
||||
"iface": string
|
||||
"metric": integer,
|
||||
"ref": integer,
|
||||
"use": integer,
|
||||
"mss": integer,
|
||||
"window": integer,
|
||||
"irtt": integer,
|
||||
"iface": string
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Works with `rpm -qi [package]` or `rpm -qia`.
|
||||
The `..._epoch` calculated timestamp fields are naive. (i.e. based on the
|
||||
local time of the system the parser is run on)
|
||||
|
||||
The `..._epoch_utc` calculated timestamp fields are timezone-aware and is
|
||||
The `..._epoch_utc` calculated timestamp fields are timezone-aware and are
|
||||
only available if the timezone field is UTC.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `rsync` command output parser
|
||||
|
||||
Supports the `-i` or `--itemize-changes` options with all levels of
|
||||
verbosity. This parser will process the STDOUT output or a log file
|
||||
verbosity. This parser will process the `STDOUT` output or a log file
|
||||
generated with the `--log-file` option.
|
||||
|
||||
Usage (cli):
|
||||
@@ -46,8 +46,8 @@ Schema:
|
||||
"time": string,
|
||||
"process": integer,
|
||||
"metadata": string,
|
||||
"update_type": string/null, [0]
|
||||
"file_type": string/null, [1]
|
||||
"update_type": string/null, # [0]
|
||||
"file_type": string/null, # [1]
|
||||
"checksum_or_value_different": bool/null,
|
||||
"size_different": bool/null,
|
||||
"modification_time_different": bool/null,
|
||||
@@ -56,7 +56,7 @@ Schema:
|
||||
"group_different": bool/null,
|
||||
"acl_different": bool/null,
|
||||
"extended_attribute_different": bool/null,
|
||||
"epoch": integer, [2]
|
||||
"epoch": integer, # [2]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"""jc - JSON Convert `rsync` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Supports the `-i` or `--itemize-changes` options with all levels of
|
||||
verbosity. This parser will process the STDOUT output or a log file
|
||||
verbosity. This parser will process the `STDOUT` output or a log file
|
||||
generated with the `--log-file` option.
|
||||
|
||||
Usage (cli):
|
||||
@@ -44,8 +44,8 @@ Schema:
|
||||
"time": string,
|
||||
"process": integer,
|
||||
"metadata": string,
|
||||
"update_type": string/null, [0]
|
||||
"file_type": string/null, [1]
|
||||
"update_type": string/null, # [0]
|
||||
"file_type": string/null, # [1]
|
||||
"checksum_or_value_different": bool/null,
|
||||
"size_different": bool/null,
|
||||
"modification_time_different": bool/null,
|
||||
@@ -54,7 +54,7 @@ Schema:
|
||||
"group_different": bool/null,
|
||||
"acl_different": bool/null,
|
||||
"extended_attribute_different": bool/null,
|
||||
"epoch": integer, [2]
|
||||
"epoch": integer, # [2]
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
@@ -80,7 +80,7 @@ Examples:
|
||||
...
|
||||
"""
|
||||
import re
|
||||
from typing import Dict, Iterable, Generator, Union
|
||||
from typing import Dict, Iterable, Union
|
||||
import jc.utils
|
||||
from jc.streaming import (
|
||||
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
|
||||
@@ -139,9 +139,9 @@ def parse(
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Generator[Dict, None, None], tuple]:
|
||||
) -> Union[Iterable[Dict], tuple]:
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -152,13 +152,9 @@ def parse(
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `ss` command output parser
|
||||
|
||||
Extended information options like -e and -p are not supported and may cause
|
||||
parsing irregularities.
|
||||
Extended information options like `-e` and `-p` are not supported and may
|
||||
cause parsing irregularities.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -18,8 +18,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Information from https://www.cyberciti.biz/files/ss.html used to define
|
||||
field names
|
||||
Information from https://www.cyberciti.biz/files/ss.html used to define
|
||||
field names
|
||||
|
||||
[
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `stat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
The `xxx_epoch` calculated timestamp fields are naive. (i.e. based on the
|
||||
local time of the system the parser is run on).
|
||||
@@ -127,7 +127,7 @@ def _process(proc_data):
|
||||
@add_jc_meta
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -138,13 +138,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"""jc - JSON Convert `sysctl -a` command output parser
|
||||
|
||||
Note: Since `sysctl` output is not easily parsable only a very simple
|
||||
key/value object will be output. An attempt is made to convert obvious
|
||||
integers and floats. If no conversion is desired, use the `-r`
|
||||
command-line argument or the `raw=True` argument in `parse()`.
|
||||
> Note: Since `sysctl` output is not easily parsable only a very simple
|
||||
> key/value object will be output. An attempt is made to convert obvious
|
||||
> integers and floats. If no conversion is desired, use the `-r`
|
||||
> command-line argument or the `raw=True` argument in `parse()`.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ used to redirect the output to a file that can be read by `jc`.
|
||||
Alternatively, the output from `/usr/bin/time` can be redirected to `STDOUT`
|
||||
so `jc` can receive it.
|
||||
|
||||
Note: `/usr/bin/time` is similar but different from the Bash builtin
|
||||
`time` command.
|
||||
> Note: `/usr/bin/time` is similar but different from the Bash builtin
|
||||
> `time` command.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
@@ -21,8 +21,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
Source: https://www.freebsd.org/cgi/man.cgi?query=getrusage
|
||||
https://man7.org/linux/man-pages/man1/time.1.html
|
||||
Source: https://www.freebsd.org/cgi/man.cgi?query=getrusage,
|
||||
https://man7.org/linux/man-pages/man1/time.1.html
|
||||
|
||||
{
|
||||
"real_time": float,
|
||||
|
||||
640
jc/parsers/top.py
Normal file
640
jc/parsers/top.py
Normal file
@@ -0,0 +1,640 @@
|
||||
"""jc - JSON Convert `top -b` command output parser
|
||||
|
||||
Requires batch mode (`-b`). The `-n` option must also be used to limit
|
||||
the number of times `top` is run.
|
||||
|
||||
Warning messages will be printed to `STDERR` if truncated fields are
|
||||
detected. These warnings can be suppressed with the `-q` or `quiet=True`
|
||||
option.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ top -b -n 3 | jc --top
|
||||
|
||||
or
|
||||
|
||||
$ jc top -b -n 3
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
result = jc.parse('top', top_command_output)
|
||||
|
||||
Schema:
|
||||
|
||||
All `-` values are converted to `null`
|
||||
|
||||
[
|
||||
{
|
||||
"time": string,
|
||||
"uptime": integer,
|
||||
"users": integer,
|
||||
"load_1m": float,
|
||||
"load_5m": float,
|
||||
"load_15m": float,
|
||||
"tasks_total": integer,
|
||||
"tasks_running": integer,
|
||||
"tasks_sleeping": integer,
|
||||
"tasks_stopped": integer,
|
||||
"tasks_zombie": integer,
|
||||
"cpu_user": float,
|
||||
"cpu_sys": float,
|
||||
"cpu_nice": float,
|
||||
"cpu_idle": float,
|
||||
"cpu_wait": float,
|
||||
"cpu_hardware": float,
|
||||
"cpu_software": float,
|
||||
"cpu_steal": float,
|
||||
"mem_total": float, # [0]
|
||||
"mem_free": float, # [0]
|
||||
"mem_used": float, # [0]
|
||||
"mem_buff_cache": float, # [0]
|
||||
"swap_total": float, # [0]
|
||||
"swap_free": float, # [0]
|
||||
"swap_used": float, # [0]
|
||||
"mem_available": float, # [0]
|
||||
"processes": [
|
||||
{
|
||||
"pid": integer,
|
||||
"user": string,
|
||||
"priority": integer,
|
||||
"nice": integer,
|
||||
"virtual_mem": float, # [1]
|
||||
"resident_mem": float, # [1]
|
||||
"shared_mem": float, # [1]
|
||||
"status": string,
|
||||
"percent_cpu": float,
|
||||
"percent_mem": float,
|
||||
"time_hundredths": string,
|
||||
"command": string,
|
||||
"parent_pid": integer,
|
||||
"uid": integer,
|
||||
"real_uid": integer,
|
||||
"real_user": string,
|
||||
"saved_uid": integer,
|
||||
"saved_user": string,
|
||||
"gid": integer,
|
||||
"group": string,
|
||||
"pgrp": integer,
|
||||
"tty": string,
|
||||
"tty_process_gid": integer,
|
||||
"session_id": integer,
|
||||
"thread_count": integer,
|
||||
"last_used_processor": integer,
|
||||
"time": string,
|
||||
"swap": float, # [1]
|
||||
"code": float, # [1]
|
||||
"data": float, # [1]
|
||||
"major_page_fault_count": integer,
|
||||
"minor_page_fault_count": integer,
|
||||
"dirty_pages_count": integer,
|
||||
"sleeping_in_function": string,
|
||||
"flags": string,
|
||||
"cgroups": string,
|
||||
"supplementary_gids": [
|
||||
integer
|
||||
],
|
||||
"supplementary_groups": [
|
||||
string
|
||||
],
|
||||
"thread_gid": integer,
|
||||
"environment_variables": [
|
||||
string
|
||||
]
|
||||
"major_page_fault_count_delta": integer,
|
||||
"minor_page_fault_count_delta": integer,
|
||||
"used": float, # [1]
|
||||
"ipc_namespace_inode": integer,
|
||||
"mount_namespace_inode": integer,
|
||||
"net_namespace_inode": integer,
|
||||
"pid_namespace_inode": integer,
|
||||
"user_namespace_inode": integer,
|
||||
"nts_namespace_inode": integer,
|
||||
"control_group_name": string,
|
||||
"lxc_container_name": string,
|
||||
"numa_node": integer,
|
||||
"out_of_mem_adjustment": integer,
|
||||
"out_of_mem_score": integer,
|
||||
"resident_anon_mem": integer,
|
||||
"resident_file_backed_mem": integer,
|
||||
"resident_locked_mem": integer,
|
||||
"resident_shared_mem": integer
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
[0] Values are in the units output by `top`
|
||||
[1] Unit suffix stripped during float conversion
|
||||
|
||||
Examples:
|
||||
|
||||
$ top -b -n 3 | jc --top -p
|
||||
[
|
||||
{
|
||||
"time": "11:20:43",
|
||||
"uptime": 118,
|
||||
"users": 2,
|
||||
"load_1m": 0.0,
|
||||
"load_5m": 0.01,
|
||||
"load_15m": 0.05,
|
||||
"tasks_total": 108,
|
||||
"tasks_running": 2,
|
||||
"tasks_sleeping": 106,
|
||||
"tasks_stopped": 0,
|
||||
"tasks_zombie": 0,
|
||||
"cpu_user": 5.6,
|
||||
"cpu_sys": 11.1,
|
||||
"cpu_nice": 0.0,
|
||||
"cpu_idle": 83.3,
|
||||
"cpu_wait": 0.0,
|
||||
"cpu_hardware": 0.0,
|
||||
"cpu_software": 0.0,
|
||||
"cpu_steal": 0.0,
|
||||
"mem_total": 3.7,
|
||||
"mem_free": 3.3,
|
||||
"mem_used": 0.2,
|
||||
"mem_buff_cache": 0.2,
|
||||
"swap_total": 2.0,
|
||||
"swap_free": 2.0,
|
||||
"swap_used": 0.0,
|
||||
"mem_available": 3.3,
|
||||
"processes": [
|
||||
{
|
||||
"pid": 2225,
|
||||
"user": "kbrazil",
|
||||
"priority": 20,
|
||||
"nice": 0,
|
||||
"virtual_mem": 158.1,
|
||||
"resident_mem": 2.2,
|
||||
"shared_mem": 1.6,
|
||||
"status": "running",
|
||||
"percent_cpu": 12.5,
|
||||
"percent_mem": 0.1,
|
||||
"time_hundredths": "0:00.02",
|
||||
"command": "top",
|
||||
"parent_pid": 1884,
|
||||
"uid": 1000,
|
||||
"real_uid": 1000,
|
||||
"real_user": "kbrazil",
|
||||
"saved_uid": 1000,
|
||||
"saved_user": "kbrazil",
|
||||
"gid": 1000,
|
||||
"group": "kbrazil",
|
||||
"pgrp": 2225,
|
||||
"tty": "pts/0",
|
||||
"tty_process_gid": 2225,
|
||||
"session_id": 1884,
|
||||
"thread_count": 1,
|
||||
"last_used_processor": 0,
|
||||
"time": "0:00",
|
||||
"swap": 0.0,
|
||||
"code": 0.1,
|
||||
"data": 1.0,
|
||||
"major_page_fault_count": 0,
|
||||
"minor_page_fault_count": 736,
|
||||
"dirty_pages_count": 0,
|
||||
"sleeping_in_function": null,
|
||||
"flags": "..4.2...",
|
||||
"cgroups": "1:name=systemd:/user.slice/user-1000.+",
|
||||
"supplementary_gids": [
|
||||
10,
|
||||
1000
|
||||
],
|
||||
"supplementary_groups": [
|
||||
"wheel",
|
||||
"kbrazil"
|
||||
],
|
||||
"thread_gid": 2225,
|
||||
"environment_variables": [
|
||||
"XDG_SESSION_ID=2",
|
||||
"HOSTNAME=localhost"
|
||||
],
|
||||
"major_page_fault_count_delta": 0,
|
||||
"minor_page_fault_count_delta": 4,
|
||||
"used": 2.2,
|
||||
"ipc_namespace_inode": 4026531839,
|
||||
"mount_namespace_inode": 4026531840,
|
||||
"net_namespace_inode": 4026531956,
|
||||
"pid_namespace_inode": 4026531836,
|
||||
"user_namespace_inode": 4026531837,
|
||||
"nts_namespace_inode": 4026531838
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
$ top -b -n 3 | jc --top -p -r
|
||||
[
|
||||
{
|
||||
"time": "11:20:43",
|
||||
"uptime": "1:18",
|
||||
"users": "2",
|
||||
"load_1m": "0.00",
|
||||
"load_5m": "0.01",
|
||||
"load_15m": "0.05",
|
||||
"tasks_total": "108",
|
||||
"tasks_running": "2",
|
||||
"tasks_sleeping": "106",
|
||||
"tasks_stopped": "0",
|
||||
"tasks_zombie": "0",
|
||||
"cpu_user": "5.6",
|
||||
"cpu_sys": "11.1",
|
||||
"cpu_nice": "0.0",
|
||||
"cpu_idle": "83.3",
|
||||
"cpu_wait": "0.0",
|
||||
"cpu_hardware": "0.0",
|
||||
"cpu_software": "0.0",
|
||||
"cpu_steal": "0.0",
|
||||
"swap_total": "2.0",
|
||||
"swap_free": "2.0",
|
||||
"swap_used": "0.0",
|
||||
"mem_available": "3.3",
|
||||
"processes": [
|
||||
{
|
||||
"PID": "2225",
|
||||
"USER": "kbrazil",
|
||||
"PR": "20",
|
||||
"NI": "0",
|
||||
"VIRT": "158.1m",
|
||||
"RES": "2.2m",
|
||||
"SHR": "1.6m",
|
||||
"S": "R",
|
||||
"%CPU": "12.5",
|
||||
"%MEM": "0.1",
|
||||
"TIME+": "0:00.02",
|
||||
"COMMAND": "top",
|
||||
"PPID": "1884",
|
||||
"UID": "1000",
|
||||
"RUID": "1000",
|
||||
"RUSER": "kbrazil",
|
||||
"SUID": "1000",
|
||||
"SUSER": "kbrazil",
|
||||
"GID": "1000",
|
||||
"GROUP": "kbrazil",
|
||||
"PGRP": "2225",
|
||||
"TTY": "pts/0",
|
||||
"TPGID": "2225",
|
||||
"SID": "1884",
|
||||
"nTH": "1",
|
||||
"P": "0",
|
||||
"TIME": "0:00",
|
||||
"SWAP": "0.0m",
|
||||
"CODE": "0.1m",
|
||||
"DATA": "1.0m",
|
||||
"nMaj": "0",
|
||||
"nMin": "736",
|
||||
"nDRT": "0",
|
||||
"WCHAN": "-",
|
||||
"Flags": "..4.2...",
|
||||
"CGROUPS": "1:name=systemd:/user.slice/user-1000.+",
|
||||
"SUPGIDS": "10,1000",
|
||||
"SUPGRPS": "wheel,kbrazil",
|
||||
"TGID": "2225",
|
||||
"ENVIRON": "XDG_SESSION_ID=2 HOSTNAME=localhost S+",
|
||||
"vMj": "0",
|
||||
"vMn": "4",
|
||||
"USED": "2.2m",
|
||||
"nsIPC": "4026531839",
|
||||
"nsMNT": "4026531840",
|
||||
"nsNET": "4026531956",
|
||||
"nsPID": "4026531836",
|
||||
"nsUSER": "4026531837",
|
||||
"nsUTS": "4026531838"
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
]
|
||||
"""
|
||||
from typing import List, Dict
|
||||
import jc.utils
|
||||
from jc.parsers.uptime import parse as parse_uptime
|
||||
from jc.parsers.universal import sparse_table_parse as parse_table
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
description = '`top -b` command parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux']
|
||||
magic_commands = ['top -b']
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _safe_split(string: str, path: str, delim: str = ' ', quiet=False) -> List[str]:
|
||||
split_string = string.split(delim)
|
||||
split_string = [x for x in split_string if not x.endswith('+')]
|
||||
|
||||
if string.endswith('+') and not quiet:
|
||||
jc.utils.warning_message([f'{path} list was truncated by top'])
|
||||
|
||||
return split_string
|
||||
|
||||
|
||||
def _process(proc_data: List[Dict], quiet=False) -> List[Dict]:
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (List of Dictionaries) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
List of Dictionaries. Structured to conform to the schema.
|
||||
"""
|
||||
key_map: Dict = {
|
||||
'%CPU': 'percent_cpu',
|
||||
'%MEM': 'percent_mem',
|
||||
'CGNAME': 'control_group_name',
|
||||
'CGROUPS': 'cgroups',
|
||||
'CODE': 'code',
|
||||
'COMMAND': 'command',
|
||||
'DATA': 'data',
|
||||
'ENVIRON': 'environment_variables',
|
||||
'Flags': 'flags',
|
||||
'GID': 'gid',
|
||||
'GROUP': 'group',
|
||||
'LXC': 'lxc_container_name',
|
||||
'NI': 'nice',
|
||||
'NU': 'numa_node',
|
||||
'OOMa': 'out_of_mem_adjustment',
|
||||
'OOMs': 'out_of_mem_score',
|
||||
'P': 'last_used_processor',
|
||||
'PGRP': 'pgrp',
|
||||
'PID': 'pid',
|
||||
'PPID': 'parent_pid',
|
||||
'PR': 'priority',
|
||||
'RES': 'resident_mem',
|
||||
'RSan': 'resident_anon_mem',
|
||||
'RSfd': 'resident_file_backed_mem',
|
||||
'RSlk': 'resident_locked_mem',
|
||||
'RSsh': 'resident_shared_mem',
|
||||
'RUID': 'real_uid',
|
||||
'RUSER': 'real_user',
|
||||
'S': 'status',
|
||||
'SHR': 'shared_mem',
|
||||
'SID': 'session_id',
|
||||
'SUID': 'saved_uid',
|
||||
'SUPGIDS': 'supplementary_gids',
|
||||
'SUPGRPS': 'supplementary_groups',
|
||||
'SUSER': 'saved_user',
|
||||
'SWAP': 'swap',
|
||||
'TGID': 'thread_gid',
|
||||
'TIME': 'time',
|
||||
'TIME+': 'time_hundredths',
|
||||
'TPGID': 'tty_process_gid',
|
||||
'TTY': 'tty',
|
||||
'UID': 'uid',
|
||||
'USED': 'used',
|
||||
'USER': 'user',
|
||||
'VIRT': 'virtual_mem',
|
||||
'WCHAN': 'sleeping_in_function',
|
||||
'nDRT': 'dirty_pages_count',
|
||||
'nMaj': 'major_page_fault_count',
|
||||
'nMin': 'minor_page_fault_count',
|
||||
'nTH': 'thread_count',
|
||||
'nsIPC': 'ipc_namespace_inode',
|
||||
'nsMNT': 'mount_namespace_inode',
|
||||
'nsNET': 'net_namespace_inode',
|
||||
'nsPID': 'pid_namespace_inode',
|
||||
'nsUSER': 'user_namespace_inode',
|
||||
'nsUTS': 'nts_namespace_inode',
|
||||
'vMj': 'major_page_fault_count_delta',
|
||||
'vMn': 'minor_page_fault_count_delta'
|
||||
}
|
||||
|
||||
status_map: Dict = {
|
||||
'D': 'uninterruptible sleep',
|
||||
'I': 'idle',
|
||||
'R': 'running',
|
||||
'S': 'sleeping',
|
||||
'T': 'stopped by job control signal',
|
||||
't': 'stopped by debugger during trace',
|
||||
'Z': 'zombie'
|
||||
}
|
||||
|
||||
int_list: List = [
|
||||
'uptime', 'users', 'tasks_total', 'tasks_running', 'tasks_sleeping', 'tasks_stopped',
|
||||
'tasks_zombie', 'pid', 'priority', 'nice', 'parent_pid', 'uid', 'real_uid', 'saved_uid',
|
||||
'gid', 'pgrp', 'tty_process_gid', 'session_id', 'thread_count', 'last_used_processor',
|
||||
'major_page_fault_count', 'minor_page_fault_count', 'dirty_pages_count', 'thread_gid',
|
||||
'major_page_fault_count_delta', 'minor_page_fault_count_delta', 'ipc_namespace_inode',
|
||||
'mount_namespace_inode', 'net_namespace_inode', 'pid_namespace_inode',
|
||||
'user_namespace_inode', 'nts_namespace_inode', 'numa_node', 'out_of_mem_adjustment',
|
||||
'out_of_mem_score', 'resident_anon_mem', 'resident_file_backed_mem', 'resident_locked_mem',
|
||||
'resident_shared_mem'
|
||||
]
|
||||
|
||||
float_list: List = [
|
||||
'load_1m', 'load_5m', 'load_15m', 'cpu_user', 'cpu_sys', 'cpu_nice', 'cpu_idle', 'cpu_wait',
|
||||
'cpu_hardware', 'cpu_software', 'cpu_steal', 'percent_cpu', 'percent_mem', 'mem_total',
|
||||
'mem_free', 'mem_used', 'mem_buff_cache', 'swap_total', 'swap_free', 'swap_used',
|
||||
'mem_available', 'virtual_mem', 'resident_mem', 'shared_mem', 'swap', 'code', 'data', 'used'
|
||||
]
|
||||
|
||||
for idx, item in enumerate(proc_data):
|
||||
for key in item:
|
||||
# root truncation warnings
|
||||
if isinstance(item[key], str) and item[key].endswith('+') and not quiet:
|
||||
jc.utils.warning_message([f'item[{idx}]["{key}"] was truncated by top'])
|
||||
|
||||
# root int and float conversions
|
||||
if key in int_list:
|
||||
item[key] = jc.utils.convert_to_int(item[key])
|
||||
|
||||
if key in float_list:
|
||||
item[key] = jc.utils.convert_to_float(item[key])
|
||||
|
||||
for p_idx, proc in enumerate(item['processes']):
|
||||
# rename processes keys to conform to schema
|
||||
proc_copy = proc.copy()
|
||||
for old_key in proc_copy.keys():
|
||||
if old_key in proc:
|
||||
proc[key_map[old_key]] = proc.pop(old_key)
|
||||
else:
|
||||
jc.utils.warning_message([f'Unknown field detected at item[{idx}]["processes"]: {old_key}'])
|
||||
|
||||
# cleanup values
|
||||
for key in proc.keys():
|
||||
|
||||
# set dashes to nulls
|
||||
if proc[key] == '-':
|
||||
proc[key] = None
|
||||
|
||||
# because of ambiguous column spacing (right-justified numbers
|
||||
# with left-justified dashes for null values) there are some hanging
|
||||
# dashes that need to be cleaned up in some values. Seems the correct
|
||||
# values are kept in the assigned columns, so this should not affect
|
||||
# data integrity.
|
||||
if proc[key] and proc[key].endswith(' -'):
|
||||
new_val = proc[key][::-1]
|
||||
new_val = new_val.replace('- ', '')
|
||||
new_val = new_val[::-1]
|
||||
proc[key] = new_val
|
||||
|
||||
# do int/float conversions for the process objects
|
||||
if proc[key]:
|
||||
if key in int_list:
|
||||
proc[key] = jc.utils.convert_to_int(proc[key])
|
||||
|
||||
if key in float_list:
|
||||
proc[key] = jc.utils.convert_to_float(proc[key])
|
||||
|
||||
# set status string
|
||||
if proc.get('status'):
|
||||
proc['status'] = status_map[proc['status']]
|
||||
|
||||
# split supplementary_gids to a list of integers
|
||||
if proc.get('supplementary_gids'):
|
||||
proc['supplementary_gids'] = _safe_split(
|
||||
proc['supplementary_gids'],
|
||||
f'item[{idx}]["processes"][{p_idx}]["supplementary_gids"]',
|
||||
',', quiet=quiet
|
||||
)
|
||||
|
||||
proc['supplementary_gids'] = [jc.utils.convert_to_int(x) for x in proc['supplementary_gids']]
|
||||
|
||||
# split supplementary_groups to a list of strings
|
||||
if proc.get('supplementary_groups'):
|
||||
proc['supplementary_groups'] = _safe_split(
|
||||
proc['supplementary_groups'],
|
||||
f'item[{idx}]["processes"][{p_idx}]["supplementary_groups"]',
|
||||
',', quiet=quiet
|
||||
)
|
||||
|
||||
# split environment_variables to a list of strings
|
||||
if proc.get('environment_variables'):
|
||||
proc['environment_variables'] = _safe_split(
|
||||
proc['environment_variables'],
|
||||
f'item[{idx}]["processes"][{p_idx}]["environment_variables"]',
|
||||
quiet=quiet
|
||||
)
|
||||
|
||||
for key in proc.keys():
|
||||
# print final warnings for truncated string values
|
||||
if isinstance(proc[key], str) and proc[key].endswith('+') and not quiet:
|
||||
jc.utils.warning_message([f'item[{idx}]["processes"][{p_idx}]["{key}"] was truncated by top'])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
def parse(
|
||||
data: str,
|
||||
raw: bool = False,
|
||||
quiet: bool = False
|
||||
) -> List[Dict]:
|
||||
"""
|
||||
Main text parsing function
|
||||
|
||||
Parameters:
|
||||
|
||||
data: (string) text data to parse
|
||||
raw: (boolean) unprocessed output if True
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
|
||||
Returns:
|
||||
|
||||
List of Dictionaries. Raw or processed structured data.
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
jc.utils.input_type_check(data)
|
||||
|
||||
raw_output: List = []
|
||||
item_obj: Dict = {}
|
||||
process_table = False
|
||||
process_list: List = []
|
||||
|
||||
if jc.utils.has_data(data):
|
||||
|
||||
for line in data.splitlines():
|
||||
if line.startswith('top - '):
|
||||
if item_obj:
|
||||
if process_list:
|
||||
item_obj['processes'] = parse_table(process_list)
|
||||
raw_output.append(item_obj)
|
||||
process_table = False
|
||||
process_list = []
|
||||
item_obj = {}
|
||||
|
||||
uptime_str = line[6:]
|
||||
item_obj.update(parse_uptime(uptime_str, raw=True))
|
||||
continue
|
||||
|
||||
if line.startswith('Tasks:'):
|
||||
# Tasks: 112 total, 1 running, 111 sleeping, 0 stopped, 0 zombie
|
||||
line_list = line.split()
|
||||
item_obj.update(
|
||||
{
|
||||
'tasks_total': line_list[1],
|
||||
'tasks_running': line_list[3],
|
||||
'tasks_sleeping': line_list[5],
|
||||
'tasks_stopped': line_list[7],
|
||||
'tasks_zombie': line_list[9]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line.startswith('%Cpu(s):'):
|
||||
# %Cpu(s): 5.9 us, 5.9 sy, 0.0 ni, 88.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
line_list = line.split()
|
||||
item_obj.update(
|
||||
{
|
||||
'cpu_user': line_list[1],
|
||||
'cpu_sys': line_list[3],
|
||||
'cpu_nice': line_list[5],
|
||||
'cpu_idle': line_list[7],
|
||||
'cpu_wait': line_list[9],
|
||||
'cpu_hardware': line_list[11],
|
||||
'cpu_software': line_list[13],
|
||||
'cpu_steal': line_list[15]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line[1:].startswith('iB Mem :'):
|
||||
# KiB Mem : 3861332 total, 3446476 free, 216940 used, 197916 buff/cache
|
||||
line_list = line.split()
|
||||
item_obj.update(
|
||||
{
|
||||
'mem_total': line_list[3],
|
||||
'mem_free': line_list[5],
|
||||
'mem_used': line_list[7],
|
||||
'mem_buff_cache': line_list[9]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line[1:].startswith('iB Swap:'):
|
||||
# KiB Swap: 2097148 total, 2097148 free, 0 used. 3419356 avail Mem
|
||||
line_list = line.split()
|
||||
item_obj.update(
|
||||
{
|
||||
'swap_total': line_list[2],
|
||||
'swap_free': line_list[4],
|
||||
'swap_used': line_list[6],
|
||||
'mem_available': line_list[8]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if not process_table and line == '':
|
||||
process_table = True
|
||||
continue
|
||||
|
||||
if process_table and not line == '':
|
||||
process_list.append(line)
|
||||
continue
|
||||
|
||||
if item_obj:
|
||||
if process_list:
|
||||
item_obj['processes'] = parse_table(process_list)
|
||||
raw_output.append(item_obj)
|
||||
|
||||
return raw_output if raw else _process(raw_output, quiet=quiet)
|
||||
490
jc/parsers/top_s.py
Normal file
490
jc/parsers/top_s.py
Normal file
@@ -0,0 +1,490 @@
|
||||
"""jc - JSON Convert `top -b` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Requires batch mode (`-b`).
|
||||
|
||||
Warning messages will be printed to `STDERR` if truncated fields are
|
||||
detected. These warnings can be suppressed with the `-q` or `quiet=True`
|
||||
option.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
$ top -b | jc --top-s
|
||||
|
||||
Usage (module):
|
||||
|
||||
import jc
|
||||
|
||||
result = jc.parse('top_s', top_command_output.splitlines())
|
||||
for item in result:
|
||||
# do something
|
||||
|
||||
Schema:
|
||||
|
||||
{
|
||||
"time": string,
|
||||
"uptime": integer,
|
||||
"users": integer,
|
||||
"load_1m": float,
|
||||
"load_5m": float,
|
||||
"load_15m": float,
|
||||
"tasks_total": integer,
|
||||
"tasks_running": integer,
|
||||
"tasks_sleeping": integer,
|
||||
"tasks_stopped": integer,
|
||||
"tasks_zombie": integer,
|
||||
"cpu_user": float,
|
||||
"cpu_sys": float,
|
||||
"cpu_nice": float,
|
||||
"cpu_idle": float,
|
||||
"cpu_wait": float,
|
||||
"cpu_hardware": float,
|
||||
"cpu_software": float,
|
||||
"cpu_steal": float,
|
||||
"mem_total": float, # [0]
|
||||
"mem_free": float, # [0]
|
||||
"mem_used": float, # [0]
|
||||
"mem_buff_cache": float, # [0]
|
||||
"swap_total": float, # [0]
|
||||
"swap_free": float, # [0]
|
||||
"swap_used": float, # [0]
|
||||
"mem_available": float, # [0]
|
||||
"processes": [
|
||||
{
|
||||
"pid": integer,
|
||||
"user": string,
|
||||
"priority": integer,
|
||||
"nice": integer,
|
||||
"virtual_mem": float, # [1]
|
||||
"resident_mem": float, # [1]
|
||||
"shared_mem": float, # [1]
|
||||
"status": string,
|
||||
"percent_cpu": float,
|
||||
"percent_mem": float,
|
||||
"time_hundredths": string,
|
||||
"command": string,
|
||||
"parent_pid": integer,
|
||||
"uid": integer,
|
||||
"real_uid": integer,
|
||||
"real_user": string,
|
||||
"saved_uid": integer,
|
||||
"saved_user": string,
|
||||
"gid": integer,
|
||||
"group": string,
|
||||
"pgrp": integer,
|
||||
"tty": string,
|
||||
"tty_process_gid": integer,
|
||||
"session_id": integer,
|
||||
"thread_count": integer,
|
||||
"last_used_processor": integer,
|
||||
"time": string,
|
||||
"swap": float, # [1]
|
||||
"code": float, # [1]
|
||||
"data": float, # [1]
|
||||
"major_page_fault_count": integer,
|
||||
"minor_page_fault_count": integer,
|
||||
"dirty_pages_count": integer,
|
||||
"sleeping_in_function": string,
|
||||
"flags": string,
|
||||
"cgroups": string,
|
||||
"supplementary_gids": [
|
||||
integer
|
||||
],
|
||||
"supplementary_groups": [
|
||||
string
|
||||
],
|
||||
"thread_gid": integer,
|
||||
"environment_variables": [
|
||||
string
|
||||
]
|
||||
"major_page_fault_count_delta": integer,
|
||||
"minor_page_fault_count_delta": integer,
|
||||
"used": float, # [1]
|
||||
"ipc_namespace_inode": integer,
|
||||
"mount_namespace_inode": integer,
|
||||
"net_namespace_inode": integer,
|
||||
"pid_namespace_inode": integer,
|
||||
"user_namespace_inode": integer,
|
||||
"nts_namespace_inode": integer,
|
||||
"control_group_name": string,
|
||||
"lxc_container_name": string,
|
||||
"numa_node": integer,
|
||||
"out_of_mem_adjustment": integer,
|
||||
"out_of_mem_score": integer,
|
||||
"resident_anon_mem": integer,
|
||||
"resident_file_backed_mem": integer,
|
||||
"resident_locked_mem": integer,
|
||||
"resident_shared_mem": integer
|
||||
}
|
||||
],
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
"success": boolean, # false if error parsing
|
||||
"error": string, # exists if "success" is false
|
||||
"line": string # exists if "success" is false
|
||||
}
|
||||
}
|
||||
|
||||
[0] Values are in the units output by `top`
|
||||
[1] Unit suffix stripped during float conversion
|
||||
|
||||
Examples:
|
||||
|
||||
$ top -b | jc --top-s
|
||||
{"time":"11:24:50","uptime":2,"users":2,"load_1m":0.23,"load_5m":...}
|
||||
...
|
||||
|
||||
$ top -b | jc --top-s -r
|
||||
{"time":"11:24:50","uptime":"2 min","users":"2","load_1m":"0.23","lo...}
|
||||
...
|
||||
"""
|
||||
from typing import List, Dict, Iterable, Union
|
||||
import jc.utils
|
||||
from jc.streaming import (
|
||||
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
|
||||
)
|
||||
from jc.exceptions import ParseError
|
||||
from jc.parsers.uptime import parse as parse_uptime
|
||||
from jc.parsers.universal import sparse_table_parse as parse_table
|
||||
|
||||
|
||||
class info():
|
||||
"""Provides parser metadata (version, author, etc.)"""
|
||||
version = '1.0'
|
||||
description = '`top -b` command streaming parser'
|
||||
author = 'Kelly Brazil'
|
||||
author_email = 'kellyjonbrazil@gmail.com'
|
||||
compatible = ['linux']
|
||||
streaming = True
|
||||
|
||||
|
||||
__version__ = info.version
|
||||
|
||||
|
||||
def _safe_split(string: str, path: str, delim: str = ' ', quiet=False) -> List[str]:
|
||||
split_string = string.split(delim)
|
||||
split_string = [x for x in split_string if not x.endswith('+')]
|
||||
|
||||
if string.endswith('+') and not quiet:
|
||||
jc.utils.warning_message([f'{path} list was truncated by top'])
|
||||
|
||||
return split_string
|
||||
|
||||
|
||||
def _process(proc_data: Dict, idx=0, quiet=False) -> Dict:
|
||||
"""
|
||||
Final processing to conform to the schema.
|
||||
|
||||
Parameters:
|
||||
|
||||
proc_data: (Dictionary) raw structured data to process
|
||||
|
||||
Returns:
|
||||
|
||||
Dictionary. Structured data to conform to the schema.
|
||||
"""
|
||||
key_map: Dict = {
|
||||
'%CPU': 'percent_cpu',
|
||||
'%MEM': 'percent_mem',
|
||||
'CGNAME': 'control_group_name',
|
||||
'CGROUPS': 'cgroups',
|
||||
'CODE': 'code',
|
||||
'COMMAND': 'command',
|
||||
'DATA': 'data',
|
||||
'ENVIRON': 'environment_variables',
|
||||
'Flags': 'flags',
|
||||
'GID': 'gid',
|
||||
'GROUP': 'group',
|
||||
'LXC': 'lxc_container_name',
|
||||
'NI': 'nice',
|
||||
'NU': 'numa_node',
|
||||
'OOMa': 'out_of_mem_adjustment',
|
||||
'OOMs': 'out_of_mem_score',
|
||||
'P': 'last_used_processor',
|
||||
'PGRP': 'pgrp',
|
||||
'PID': 'pid',
|
||||
'PPID': 'parent_pid',
|
||||
'PR': 'priority',
|
||||
'RES': 'resident_mem',
|
||||
'RSan': 'resident_anon_mem',
|
||||
'RSfd': 'resident_file_backed_mem',
|
||||
'RSlk': 'resident_locked_mem',
|
||||
'RSsh': 'resident_shared_mem',
|
||||
'RUID': 'real_uid',
|
||||
'RUSER': 'real_user',
|
||||
'S': 'status',
|
||||
'SHR': 'shared_mem',
|
||||
'SID': 'session_id',
|
||||
'SUID': 'saved_uid',
|
||||
'SUPGIDS': 'supplementary_gids',
|
||||
'SUPGRPS': 'supplementary_groups',
|
||||
'SUSER': 'saved_user',
|
||||
'SWAP': 'swap',
|
||||
'TGID': 'thread_gid',
|
||||
'TIME': 'time',
|
||||
'TIME+': 'time_hundredths',
|
||||
'TPGID': 'tty_process_gid',
|
||||
'TTY': 'tty',
|
||||
'UID': 'uid',
|
||||
'USED': 'used',
|
||||
'USER': 'user',
|
||||
'VIRT': 'virtual_mem',
|
||||
'WCHAN': 'sleeping_in_function',
|
||||
'nDRT': 'dirty_pages_count',
|
||||
'nMaj': 'major_page_fault_count',
|
||||
'nMin': 'minor_page_fault_count',
|
||||
'nTH': 'thread_count',
|
||||
'nsIPC': 'ipc_namespace_inode',
|
||||
'nsMNT': 'mount_namespace_inode',
|
||||
'nsNET': 'net_namespace_inode',
|
||||
'nsPID': 'pid_namespace_inode',
|
||||
'nsUSER': 'user_namespace_inode',
|
||||
'nsUTS': 'nts_namespace_inode',
|
||||
'vMj': 'major_page_fault_count_delta',
|
||||
'vMn': 'minor_page_fault_count_delta'
|
||||
}
|
||||
|
||||
status_map: Dict = {
|
||||
'D': 'uninterruptible sleep',
|
||||
'I': 'idle',
|
||||
'R': 'running',
|
||||
'S': 'sleeping',
|
||||
'T': 'stopped by job control signal',
|
||||
't': 'stopped by debugger during trace',
|
||||
'Z': 'zombie'
|
||||
}
|
||||
|
||||
int_list: List = [
|
||||
'uptime', 'users', 'tasks_total', 'tasks_running', 'tasks_sleeping', 'tasks_stopped',
|
||||
'tasks_zombie', 'pid', 'priority', 'nice', 'parent_pid', 'uid', 'real_uid', 'saved_uid',
|
||||
'gid', 'pgrp', 'tty_process_gid', 'session_id', 'thread_count', 'last_used_processor',
|
||||
'major_page_fault_count', 'minor_page_fault_count', 'dirty_pages_count', 'thread_gid',
|
||||
'major_page_fault_count_delta', 'minor_page_fault_count_delta', 'ipc_namespace_inode',
|
||||
'mount_namespace_inode', 'net_namespace_inode', 'pid_namespace_inode',
|
||||
'user_namespace_inode', 'nts_namespace_inode', 'numa_node', 'out_of_mem_adjustment',
|
||||
'out_of_mem_score', 'resident_anon_mem', 'resident_file_backed_mem', 'resident_locked_mem',
|
||||
'resident_shared_mem'
|
||||
]
|
||||
|
||||
float_list: List = [
|
||||
'load_1m', 'load_5m', 'load_15m', 'cpu_user', 'cpu_sys', 'cpu_nice', 'cpu_idle', 'cpu_wait',
|
||||
'cpu_hardware', 'cpu_software', 'cpu_steal', 'percent_cpu', 'percent_mem', 'mem_total',
|
||||
'mem_free', 'mem_used', 'mem_buff_cache', 'swap_total', 'swap_free', 'swap_used',
|
||||
'mem_available', 'virtual_mem', 'resident_mem', 'shared_mem', 'swap', 'code', 'data', 'used'
|
||||
]
|
||||
|
||||
for key in proc_data:
|
||||
# root truncation warnings
|
||||
if isinstance(proc_data[key], str) and proc_data[key].endswith('+') and not quiet:
|
||||
jc.utils.warning_message([f'item[{idx}]["{key}"] was truncated by top'])
|
||||
|
||||
# root int and float conversions
|
||||
if key in int_list:
|
||||
proc_data[key] = jc.utils.convert_to_int(proc_data[key])
|
||||
|
||||
if key in float_list:
|
||||
proc_data[key] = jc.utils.convert_to_float(proc_data[key])
|
||||
|
||||
for p_idx, proc in enumerate(proc_data['processes']):
|
||||
# rename processes keys to conform to schema
|
||||
proc_copy = proc.copy()
|
||||
for old_key in proc_copy.keys():
|
||||
if old_key in proc:
|
||||
proc[key_map[old_key]] = proc.pop(old_key)
|
||||
else:
|
||||
jc.utils.warning_message([f'Unknown field detected at item[{idx}]["processes"]: {old_key}'])
|
||||
|
||||
# cleanup values
|
||||
for key in proc.keys():
|
||||
|
||||
# set dashes to nulls
|
||||
if proc[key] == '-':
|
||||
proc[key] = None
|
||||
|
||||
# because of ambiguous column spacing (right-justified numbers
|
||||
# with left-justified dashes for null values) there are some hanging
|
||||
# dashes that need to be cleaned up in some values. Seems the correct
|
||||
# values are kept in the assigned columns, so this should not affect
|
||||
# data integrity.
|
||||
if proc[key] and proc[key].endswith(' -'):
|
||||
new_val = proc[key][::-1]
|
||||
new_val = new_val.replace('- ', '')
|
||||
new_val = new_val[::-1]
|
||||
proc[key] = new_val
|
||||
|
||||
# do int/float conversions for the process objects
|
||||
if proc[key]:
|
||||
if key in int_list:
|
||||
proc[key] = jc.utils.convert_to_int(proc[key])
|
||||
|
||||
if key in float_list:
|
||||
proc[key] = jc.utils.convert_to_float(proc[key])
|
||||
|
||||
# set status string
|
||||
if proc.get('status'):
|
||||
proc['status'] = status_map[proc['status']]
|
||||
|
||||
# split supplementary_gids to a list of integers
|
||||
if proc.get('supplementary_gids'):
|
||||
proc['supplementary_gids'] = _safe_split(
|
||||
proc['supplementary_gids'],
|
||||
f'item[{idx}]["processes"][{p_idx}]["supplementary_gids"]',
|
||||
',', quiet=quiet
|
||||
)
|
||||
|
||||
proc['supplementary_gids'] = [jc.utils.convert_to_int(x) for x in proc['supplementary_gids']]
|
||||
|
||||
# split supplementary_groups to a list of strings
|
||||
if proc.get('supplementary_groups'):
|
||||
proc['supplementary_groups'] = _safe_split(
|
||||
proc['supplementary_groups'],
|
||||
f'item[{idx}]["processes"][{p_idx}]["supplementary_groups"]',
|
||||
',', quiet=quiet
|
||||
)
|
||||
|
||||
# split environment_variables to a list of strings
|
||||
if proc.get('environment_variables'):
|
||||
proc['environment_variables'] = _safe_split(
|
||||
proc['environment_variables'],
|
||||
f'item[{idx}]["processes"][{p_idx}]["environment_variables"]',
|
||||
quiet=quiet
|
||||
)
|
||||
|
||||
for key in proc.keys():
|
||||
# print final warnings for truncated string values
|
||||
if isinstance(proc[key], str) and proc[key].endswith('+') and not quiet:
|
||||
jc.utils.warning_message([f'item[{idx}]["processes"][{p_idx}]["{key}"] was truncated by top'])
|
||||
|
||||
return proc_data
|
||||
|
||||
|
||||
@add_jc_meta
|
||||
def parse(
|
||||
data: Iterable[str],
|
||||
raw: bool = False,
|
||||
quiet: bool = False,
|
||||
ignore_exceptions: bool = False
|
||||
) -> Union[Iterable[Dict], tuple]:
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
data: (iterable) line-based text data to parse
|
||||
(e.g. sys.stdin or str.splitlines())
|
||||
|
||||
raw: (boolean) unprocessed output if True
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
|
||||
Returns:
|
||||
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
output_line: Dict = {}
|
||||
process_table = False
|
||||
process_list: List = []
|
||||
idx = 0
|
||||
|
||||
for line in data:
|
||||
try:
|
||||
streaming_line_input_type_check(line)
|
||||
|
||||
if line.startswith('top - '):
|
||||
if output_line:
|
||||
if process_list:
|
||||
output_line['processes'] = parse_table(process_list)
|
||||
yield output_line if raw else _process(output_line, idx=idx, quiet=quiet)
|
||||
process_table = False
|
||||
process_list = []
|
||||
output_line = {}
|
||||
idx += 1
|
||||
|
||||
uptime_str = line[6:]
|
||||
output_line.update(parse_uptime(uptime_str, raw=True))
|
||||
continue
|
||||
|
||||
if line.startswith('Tasks:'):
|
||||
# Tasks: 112 total, 1 running, 111 sleeping, 0 stopped, 0 zombie
|
||||
line_list = line.split()
|
||||
output_line.update(
|
||||
{
|
||||
'tasks_total': line_list[1],
|
||||
'tasks_running': line_list[3],
|
||||
'tasks_sleeping': line_list[5],
|
||||
'tasks_stopped': line_list[7],
|
||||
'tasks_zombie': line_list[9]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line.startswith('%Cpu(s):'):
|
||||
# %Cpu(s): 5.9 us, 5.9 sy, 0.0 ni, 88.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
line_list = line.split()
|
||||
output_line.update(
|
||||
{
|
||||
'cpu_user': line_list[1],
|
||||
'cpu_sys': line_list[3],
|
||||
'cpu_nice': line_list[5],
|
||||
'cpu_idle': line_list[7],
|
||||
'cpu_wait': line_list[9],
|
||||
'cpu_hardware': line_list[11],
|
||||
'cpu_software': line_list[13],
|
||||
'cpu_steal': line_list[15]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line[1:].startswith('iB Mem :'):
|
||||
# KiB Mem : 3861332 total, 3446476 free, 216940 used, 197916 buff/cache
|
||||
line_list = line.split()
|
||||
output_line.update(
|
||||
{
|
||||
'mem_total': line_list[3],
|
||||
'mem_free': line_list[5],
|
||||
'mem_used': line_list[7],
|
||||
'mem_buff_cache': line_list[9]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if line[1:].startswith('iB Swap:'):
|
||||
# KiB Swap: 2097148 total, 2097148 free, 0 used. 3419356 avail Mem
|
||||
line_list = line.split()
|
||||
output_line.update(
|
||||
{
|
||||
'swap_total': line_list[2],
|
||||
'swap_free': line_list[4],
|
||||
'swap_used': line_list[6],
|
||||
'mem_available': line_list[8]
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
if not process_table and line.rstrip() == '':
|
||||
process_table = True
|
||||
continue
|
||||
|
||||
if process_table and not line.rstrip() == '':
|
||||
process_list.append(line.rstrip())
|
||||
continue
|
||||
|
||||
if process_table and line.rstrip() == '':
|
||||
continue
|
||||
|
||||
raise ParseError('Not top data')
|
||||
|
||||
except Exception as e:
|
||||
yield raise_or_yield(ignore_exceptions, e, line)
|
||||
|
||||
if output_line:
|
||||
if process_list:
|
||||
output_line['processes'] = parse_table(process_list)
|
||||
yield output_line if raw else _process(output_line, idx=idx, quiet=quiet)
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
Supports `traceroute` and `traceroute6` output.
|
||||
|
||||
Note: On some operating systems you will need to redirect `STDERR` to
|
||||
`STDOUT` for destination info since the header line is sent to
|
||||
`STDERR`. A warning message will be printed to `STDERR` if the
|
||||
header row is not found.
|
||||
|
||||
e.g. `$ traceroute 8.8.8.8 2>&1 | jc --traceroute`
|
||||
> Note: On some operating systems you will need to redirect `STDERR` to
|
||||
> `STDOUT` for destination info since the header line is sent to
|
||||
> `STDERR`. A warning message will be printed to `STDERR` if the
|
||||
> header row is not found.
|
||||
>
|
||||
> e.g. `$ traceroute 8.8.8.8 2>&1 | jc --traceroute`
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""jc - JSON Convert `uname -a` command output parser
|
||||
|
||||
Note: Must use `uname -a`
|
||||
> Note: Must use `uname -a`
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""jc - JSON Convert `vmstat` command output streaming parser
|
||||
|
||||
> This streaming parser outputs JSON Lines (cli) or returns a Generator
|
||||
iterator of Dictionaries (module)
|
||||
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
|
||||
> Dictionaries (module)
|
||||
|
||||
Options supported: `-a`, `-w`, `-d`, `-t`
|
||||
|
||||
@@ -16,11 +16,11 @@ Usage (cli):
|
||||
$ vmstat | jc --vmstat-s
|
||||
|
||||
> Note: When piping `jc` converted `vmstat` output to other processes it may
|
||||
appear the output is hanging due to the OS pipe buffers. This is because
|
||||
`vmstat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
option to unbuffer the `jc` output if you would like immediate output. See
|
||||
the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
for more information.
|
||||
> appear the output is hanging due to the OS pipe buffers. This is because
|
||||
> `vmstat` output is too small to quickly fill up the buffer. Use the `-u`
|
||||
> option to unbuffer the `jc` output if you would like immediate output. See
|
||||
> the [readme](https://github.com/kellyjonbrazil/jc/tree/master#unbuffering-output)
|
||||
> for more information.
|
||||
|
||||
Usage (module):
|
||||
|
||||
@@ -70,9 +70,9 @@ Schema:
|
||||
|
||||
# below object only exists if using -qq or ignore_exceptions=True
|
||||
"_jc_meta": {
|
||||
"success": boolean, # [2]
|
||||
"error": string, # [3]
|
||||
"line": string # [3]
|
||||
"success": boolean, # [2]
|
||||
"error": string, # [3]
|
||||
"line": string # [3]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ def _process(proc_data):
|
||||
@add_jc_meta
|
||||
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
"""
|
||||
Main text parsing generator function. Returns an iterator object.
|
||||
Main text parsing generator function. Returns an iterable object.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -158,13 +158,9 @@ def parse(data, raw=False, quiet=False, ignore_exceptions=False):
|
||||
quiet: (boolean) suppress warning messages if True
|
||||
ignore_exceptions: (boolean) ignore parsing exceptions if True
|
||||
|
||||
Yields:
|
||||
|
||||
Dictionary. Raw or processed structured data.
|
||||
|
||||
Returns:
|
||||
|
||||
Iterator object (generator)
|
||||
Iterable of Dictionaries
|
||||
"""
|
||||
jc.utils.compatibility(__name__, info.compatible, quiet)
|
||||
streaming_input_type_check(data)
|
||||
|
||||
@@ -11,8 +11,8 @@ Usage (module):
|
||||
|
||||
Schema:
|
||||
|
||||
XML Document converted to a Dictionary
|
||||
See https://github.com/martinblech/xmltodict for details
|
||||
XML Document converted to a Dictionary. See https://github.com/martinblech/xmltodict
|
||||
for details.
|
||||
|
||||
{
|
||||
"key1": string/object,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""jc - JSON Convert `YAML` file parser
|
||||
|
||||
Note: datetime objects will be converted to strings.
|
||||
> Note: `datetime` objects will be converted to strings.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
"""jc - JSON Convert `zipinfo` command output parser
|
||||
|
||||
Options supported:
|
||||
- none
|
||||
|
||||
Note: The default listing format.
|
||||
> Note: No `zipinfo` options are supported.
|
||||
|
||||
Usage (cli):
|
||||
|
||||
|
||||
46
jc/utils.py
46
jc/utils.py
@@ -31,8 +31,8 @@ def _safe_print(string: str, sep=' ', end='\n', file=sys.stdout, flush=False) ->
|
||||
|
||||
def warning_message(message_lines: List[str]) -> None:
|
||||
"""
|
||||
Prints warning message for non-fatal issues. The first line is
|
||||
prepended with 'jc: Warning - ' and subsequent lines are indented.
|
||||
Prints warning message to `STDERR` for non-fatal issues. The first line
|
||||
is prepended with 'jc: Warning - ' and subsequent lines are indented.
|
||||
Wraps text as needed based on the terminal width.
|
||||
|
||||
Parameters:
|
||||
@@ -67,7 +67,7 @@ def warning_message(message_lines: List[str]) -> None:
|
||||
|
||||
def error_message(message_lines: List[str]) -> None:
|
||||
"""
|
||||
Prints an error message for fatal issues. The first line is
|
||||
Prints an error message to `STDERR` for fatal issues. The first line is
|
||||
prepended with 'jc: Error - ' and subsequent lines are indented.
|
||||
Wraps text as needed based on the terminal width.
|
||||
|
||||
@@ -97,10 +97,24 @@ def error_message(message_lines: List[str]) -> None:
|
||||
_safe_print(message, file=sys.stderr)
|
||||
|
||||
|
||||
def is_compatible(compatible: List) -> bool:
|
||||
"""
|
||||
Returns True if the parser is compatible with the running OS platform.
|
||||
"""
|
||||
platform_found = False
|
||||
|
||||
for platform in compatible:
|
||||
if sys.platform.startswith(platform):
|
||||
platform_found = True
|
||||
break
|
||||
|
||||
return platform_found
|
||||
|
||||
|
||||
def compatibility(mod_name: str, compatible: List, quiet: bool = False) -> None:
|
||||
"""
|
||||
Checks for the parser's compatibility with the running OS
|
||||
platform.
|
||||
Checks for the parser's compatibility with the running OS platform and
|
||||
prints a warning message to `STDERR` if not compatible and quiet=False.
|
||||
|
||||
Parameters:
|
||||
|
||||
@@ -116,21 +130,13 @@ def compatibility(mod_name: str, compatible: List, quiet: bool = False) -> None:
|
||||
|
||||
None - just prints output to STDERR
|
||||
"""
|
||||
if not quiet:
|
||||
platform_found = False
|
||||
|
||||
for platform in compatible:
|
||||
if sys.platform.startswith(platform):
|
||||
platform_found = True
|
||||
break
|
||||
|
||||
if not platform_found:
|
||||
mod = mod_name.split('.')[-1]
|
||||
compat_list = ', '.join(compatible)
|
||||
warning_message([
|
||||
f'{mod} parser is not compatible with your OS ({sys.platform}).',
|
||||
f'Compatible platforms: {compat_list}'
|
||||
])
|
||||
if not quiet and not is_compatible(compatible):
|
||||
mod = mod_name.split('.')[-1]
|
||||
compat_list = ', '.join(compatible)
|
||||
warning_message([
|
||||
f'{mod} parser is not compatible with your OS ({sys.platform}).',
|
||||
f'Compatible platforms: {compat_list}'
|
||||
])
|
||||
|
||||
|
||||
def has_data(data: str) -> bool:
|
||||
|
||||
58
man/jc.1
58
man/jc.1
@@ -1,15 +1,15 @@
|
||||
.TH jc 1 2022-04-27 1.18.8 "JSON Convert"
|
||||
.TH jc 1 2022-05-31 1.20.0 "JSON Convert"
|
||||
.SH NAME
|
||||
jc \- JSONifies the output of many CLI tools and file-types
|
||||
\fBjc\fP \- JSON Convert JSONifies the output of many CLI tools and file-types
|
||||
.SH SYNOPSIS
|
||||
COMMAND | jc PARSER [OPTIONS]
|
||||
|
||||
or "Magic" syntax:
|
||||
|
||||
jc [OPTIONS] COMMAND
|
||||
\fBjc\fP [OPTIONS] COMMAND
|
||||
|
||||
.SH DESCRIPTION
|
||||
jc JSONifies the output of many CLI tools and file-types for easier parsing in scripts. jc accepts piped input from \fBSTDIN\fP and outputs a JSON representation of the previous command's output to \fBSTDOUT\fP. Alternatively, the "Magic" syntax can be used by prepending jc to the command to be converted. Options can be passed to jc immediately before the command is given. (Note: "Magic" syntax does not support shell builtins or command aliases)
|
||||
\fBjc\fP JSONifies the output of many CLI tools and file-types for easier parsing in scripts. \fBjc\fP accepts piped input from \fBSTDIN\fP and outputs a JSON representation of the previous command's output to \fBSTDOUT\fP. Alternatively, the "Magic" syntax can be used by prepending \fBjc\fP to the command to be converted. Options can be passed to \fBjc\fP immediately before the command is given. (Note: "Magic" syntax does not support shell builtins or command aliases)
|
||||
|
||||
.SH OPTIONS
|
||||
.B
|
||||
@@ -52,6 +52,11 @@ multi-line ASCII and Unicode table parser
|
||||
\fB--blkid\fP
|
||||
`blkid` command parser
|
||||
|
||||
.TP
|
||||
.B
|
||||
\fB--chage\fP
|
||||
`chage --list` command parser
|
||||
|
||||
.TP
|
||||
.B
|
||||
\fB--cksum\fP
|
||||
@@ -142,6 +147,11 @@ CSV file streaming parser
|
||||
\fB--git-log\fP
|
||||
`git log` command parser
|
||||
|
||||
.TP
|
||||
.B
|
||||
\fB--git-log-s\fP
|
||||
`git log` command streaming parser
|
||||
|
||||
.TP
|
||||
.B
|
||||
\fB--group\fP
|
||||
@@ -300,12 +310,12 @@ Key/Value file parser
|
||||
.TP
|
||||
.B
|
||||
\fB--pidstat\fP
|
||||
`pidstat` command parser
|
||||
`pidstat -h` command parser
|
||||
|
||||
.TP
|
||||
.B
|
||||
\fB--pidstat-s\fP
|
||||
`pidstat` command streaming parser
|
||||
`pidstat -h` command streaming parser
|
||||
|
||||
.TP
|
||||
.B
|
||||
@@ -417,6 +427,16 @@ Key/Value file parser
|
||||
\fB--timedatectl\fP
|
||||
`timedatectl status` command parser
|
||||
|
||||
.TP
|
||||
.B
|
||||
\fB--top\fP
|
||||
`top -b` command parser
|
||||
|
||||
.TP
|
||||
.B
|
||||
\fB--top-s\fP
|
||||
`top -b` command streaming parser
|
||||
|
||||
.TP
|
||||
.B
|
||||
\fB--tracepath\fP
|
||||
@@ -517,7 +537,7 @@ Options:
|
||||
.TP
|
||||
.B
|
||||
\fB-a\fP
|
||||
about jc (JSON output)
|
||||
about \fBjc\fP (JSON or YAML output)
|
||||
.TP
|
||||
.B
|
||||
\fB-C\fP
|
||||
@@ -554,9 +574,13 @@ unbuffer output (useful for slow streaming data with streaming parsers)
|
||||
.B
|
||||
\fB-v\fP
|
||||
version information
|
||||
.TP
|
||||
.B
|
||||
\fB-y\fP
|
||||
YAML output
|
||||
|
||||
.SH EXIT CODES
|
||||
Any fatal errors within jc will generate an exit code of \fB100\fP, otherwise the exit code will be \fB0\fP. When using the "Magic" syntax (e.g. \fBjc ifconfig eth0\fP), jc will store the exit code of the program being parsed and add it to the jc exit code. This way it is easier to determine if an error was from the parsed program or jc.
|
||||
Any fatal errors within \fBjc\fP will generate an exit code of \fB100\fP, otherwise the exit code will be \fB0\fP. When using the "Magic" syntax (e.g. \fBjc ifconfig eth0\fP), \fBjc\fP will store the exit code of the program being parsed and add it to the \fBjc\fP exit code. This way it is easier to determine if an error was from the parsed program or \fBjc\fP.
|
||||
|
||||
Consider the following examples using \fBifconfig\fP:
|
||||
|
||||
@@ -592,10 +616,10 @@ JC_COLORS=default,default,default,default
|
||||
|
||||
\fBDisable Color Output\fP
|
||||
|
||||
You can set the \fBNO_COLOR\fB environment variable to any value to disable color output in \fBjc\fP. Note that using the \fB-C\fP option to force color output will override both the \fBNO_COLOR\fP environment variable and the \fB-m\fP option.
|
||||
You can set the \fBNO_COLOR\fP environment variable to any value to disable color output in \fBjc\fP. Note that using the \fB-C\fP option to force color output will override both the \fBNO_COLOR\fP environment variable and the \fB-m\fP option.
|
||||
|
||||
.SH STREAMING PARSERS
|
||||
Most parsers load all of the data from \fBSTDIN\fP, parse it, then output the entire JSON document serially. There are some streaming parsers (e.g. \fBls-s\fP and \fBping-s\fP) that immediately start processing and outputing the data line-by-line as JSON Lines (aka NDJSON) while it is being received from \fBSTDIN\fP. This can significantly reduce the amount of memory required to parse large amounts of command output (e.g. \fBls -lR /\fP) and can sometimes process the data more quickly. Streaming parsers have slightly different behavior than standard parsers as outlined below.
|
||||
Most parsers load all of the data from \fBSTDIN\fP, parse it, then output the entire JSON document serially. There are some streaming parsers (e.g. \fBls-s\fP, \fBping-s\fP, etc.) that immediately start processing and outputing the data line-by-line as JSON Lines (aka NDJSON) while it is being received from \fBSTDIN\fP. This can significantly reduce the amount of memory required to parse large amounts of command output (e.g. \fBls -lR /\fP) and can sometimes process the data more quickly. Streaming parsers have slightly different behavior than standard parsers as outlined below.
|
||||
|
||||
.RS
|
||||
Note: Streaming parsers cannot be used with the "magic" syntax
|
||||
@@ -667,14 +691,16 @@ Custom local parser plugins may be placed in a \fBjc/jcparsers\fP folder in your
|
||||
.fi
|
||||
.RE
|
||||
|
||||
Local parser plugins are standard python module files. Use the \fBjc/parsers/foo.py\fP parser as a template and simply place a \fB.py\fP file in the \fBjcparsers\fP subfolder.
|
||||
Local parser plugins are standard python module files. Use the \fBjc/parsers/foo.py\fP or \fBjc/parsers/foo_s.py\fP (streaming) parser as a template and simply place a \fB.py\fP file in the \fBjcparsers\fP subfolder.
|
||||
|
||||
Local plugin filenames must be valid python module names, therefore must consist entirely of alphanumerics and start with a letter. Local plugins may override default plugins.
|
||||
Local plugin filenames must be valid python module names and therefore must start with a letter and consist entirely of alphanumerics and underscores. Local plugins may override default parsers.
|
||||
|
||||
Note: The application data directory follows the XDG Base Directory Specification
|
||||
|
||||
.SH CAVEATS
|
||||
\fBLocale:\fP For best results set the \fBLANG\fP locale environment variable to \fBC\fP or \fBen_US.UTF-8\fP. For example, either by setting directly on the command-line:
|
||||
\fBLocale\fP
|
||||
|
||||
For best results set the \fBLANG\fP locale environment variable to \fBC\fP or \fBen_US.UTF-8\fP. For example, either by setting directly on the command-line:
|
||||
|
||||
.RS
|
||||
$ LANG=C date | jc \fB--date\fP
|
||||
@@ -686,9 +712,11 @@ or by exporting to the environment before running commands:
|
||||
$ export LANG=C
|
||||
.RE
|
||||
|
||||
On some older systems UTF-8 output will be downgraded to ASCII with `\\u` escape sequences if the \fBC\fP locale does not support UTF-8 encoding.
|
||||
On some older systems UTF-8 output will be downgraded to ASCII with \fB\\u\fP escape sequences if the \fBC\fP locale does not support UTF-8 encoding.
|
||||
|
||||
\fBTimezones:\fP Some parsers have calculated epoch timestamp fields added to the output. Unless a timestamp field name has a \fB_utc\fP suffix it is considered naive. (i.e. based on the local timezone of the system the \fBjc\fP parser was run on).
|
||||
\fBTimezones\fP
|
||||
|
||||
Some parsers have calculated epoch timestamp fields added to the output. Unless a timestamp field name has a \fB_utc\fP suffix it is considered naive. (i.e. based on the local timezone of the system the \fBjc\fP parser was run on).
|
||||
|
||||
If a UTC timezone can be detected in the text of the command output, the timestamp will be timezone aware and have a \fB_utc\fP suffix on the key name. (e.g. \fBepoch_utc\fP) No other timezones are supported for aware timestamps.
|
||||
|
||||
|
||||
4
setup.py
4
setup.py
@@ -5,7 +5,7 @@ with open('README.md', 'r') as f:
|
||||
|
||||
setuptools.setup(
|
||||
name='jc',
|
||||
version='1.18.8',
|
||||
version='1.20.0',
|
||||
author='Kelly Brazil',
|
||||
author_email='kellyjonbrazil@gmail.com',
|
||||
description='Converts the output of popular command-line tools and file-types to JSON.',
|
||||
@@ -17,7 +17,7 @@ setuptools.setup(
|
||||
license='MIT',
|
||||
long_description=long_description,
|
||||
long_description_content_type='text/markdown',
|
||||
python_requires='>=3.7',
|
||||
python_requires='>=3.6',
|
||||
url='https://github.com/kellyjonbrazil/jc',
|
||||
packages=setuptools.find_packages(exclude=['*.tests', '*.tests.*', 'tests.*', 'tests']),
|
||||
entry_points={
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
.TH jc 1 {{ today }} {{ jc.version}} "JSON Convert"
|
||||
.SH NAME
|
||||
jc \- JSONifies the output of many CLI tools and file-types
|
||||
\fBjc\fP \- JSON Convert JSONifies the output of many CLI tools and file-types
|
||||
.SH SYNOPSIS
|
||||
COMMAND | jc PARSER [OPTIONS]
|
||||
|
||||
or "Magic" syntax:
|
||||
|
||||
jc [OPTIONS] COMMAND
|
||||
\fBjc\fP [OPTIONS] COMMAND
|
||||
|
||||
.SH DESCRIPTION
|
||||
jc JSONifies the output of many CLI tools and file-types for easier parsing in scripts. jc accepts piped input from \fBSTDIN\fP and outputs a JSON representation of the previous command's output to \fBSTDOUT\fP. Alternatively, the "Magic" syntax can be used by prepending jc to the command to be converted. Options can be passed to jc immediately before the command is given. (Note: "Magic" syntax does not support shell builtins or command aliases)
|
||||
\fBjc\fP JSONifies the output of many CLI tools and file-types for easier parsing in scripts. \fBjc\fP accepts piped input from \fBSTDIN\fP and outputs a JSON representation of the previous command's output to \fBSTDOUT\fP. Alternatively, the "Magic" syntax can be used by prepending \fBjc\fP to the command to be converted. Options can be passed to \fBjc\fP immediately before the command is given. (Note: "Magic" syntax does not support shell builtins or command aliases)
|
||||
|
||||
.SH OPTIONS
|
||||
.B
|
||||
@@ -32,7 +32,7 @@ Options:
|
||||
.TP
|
||||
.B
|
||||
\fB-a\fP
|
||||
about jc (JSON output)
|
||||
about \fBjc\fP (JSON or YAML output)
|
||||
.TP
|
||||
.B
|
||||
\fB-C\fP
|
||||
@@ -69,9 +69,13 @@ unbuffer output (useful for slow streaming data with streaming parsers)
|
||||
.B
|
||||
\fB-v\fP
|
||||
version information
|
||||
.TP
|
||||
.B
|
||||
\fB-y\fP
|
||||
YAML output
|
||||
|
||||
.SH EXIT CODES
|
||||
Any fatal errors within jc will generate an exit code of \fB100\fP, otherwise the exit code will be \fB0\fP. When using the "Magic" syntax (e.g. \fBjc ifconfig eth0\fP), jc will store the exit code of the program being parsed and add it to the jc exit code. This way it is easier to determine if an error was from the parsed program or jc.
|
||||
Any fatal errors within \fBjc\fP will generate an exit code of \fB100\fP, otherwise the exit code will be \fB0\fP. When using the "Magic" syntax (e.g. \fBjc ifconfig eth0\fP), \fBjc\fP will store the exit code of the program being parsed and add it to the \fBjc\fP exit code. This way it is easier to determine if an error was from the parsed program or \fBjc\fP.
|
||||
|
||||
Consider the following examples using \fBifconfig\fP:
|
||||
|
||||
@@ -107,10 +111,10 @@ JC_COLORS=default,default,default,default
|
||||
|
||||
\fBDisable Color Output\fP
|
||||
|
||||
You can set the \fBNO_COLOR\fB environment variable to any value to disable color output in \fBjc\fP. Note that using the \fB-C\fP option to force color output will override both the \fBNO_COLOR\fP environment variable and the \fB-m\fP option.
|
||||
You can set the \fBNO_COLOR\fP environment variable to any value to disable color output in \fBjc\fP. Note that using the \fB-C\fP option to force color output will override both the \fBNO_COLOR\fP environment variable and the \fB-m\fP option.
|
||||
|
||||
.SH STREAMING PARSERS
|
||||
Most parsers load all of the data from \fBSTDIN\fP, parse it, then output the entire JSON document serially. There are some streaming parsers (e.g. \fBls-s\fP and \fBping-s\fP) that immediately start processing and outputing the data line-by-line as JSON Lines (aka NDJSON) while it is being received from \fBSTDIN\fP. This can significantly reduce the amount of memory required to parse large amounts of command output (e.g. \fBls -lR /\fP) and can sometimes process the data more quickly. Streaming parsers have slightly different behavior than standard parsers as outlined below.
|
||||
Most parsers load all of the data from \fBSTDIN\fP, parse it, then output the entire JSON document serially. There are some streaming parsers (e.g. \fBls-s\fP, \fBping-s\fP, etc.) that immediately start processing and outputing the data line-by-line as JSON Lines (aka NDJSON) while it is being received from \fBSTDIN\fP. This can significantly reduce the amount of memory required to parse large amounts of command output (e.g. \fBls -lR /\fP) and can sometimes process the data more quickly. Streaming parsers have slightly different behavior than standard parsers as outlined below.
|
||||
|
||||
.RS
|
||||
Note: Streaming parsers cannot be used with the "magic" syntax
|
||||
@@ -182,14 +186,16 @@ Custom local parser plugins may be placed in a \fBjc/jcparsers\fP folder in your
|
||||
.fi
|
||||
.RE
|
||||
|
||||
Local parser plugins are standard python module files. Use the \fBjc/parsers/foo.py\fP parser as a template and simply place a \fB.py\fP file in the \fBjcparsers\fP subfolder.
|
||||
Local parser plugins are standard python module files. Use the \fBjc/parsers/foo.py\fP or \fBjc/parsers/foo_s.py\fP (streaming) parser as a template and simply place a \fB.py\fP file in the \fBjcparsers\fP subfolder.
|
||||
|
||||
Local plugin filenames must be valid python module names, therefore must consist entirely of alphanumerics and start with a letter. Local plugins may override default plugins.
|
||||
Local plugin filenames must be valid python module names and therefore must start with a letter and consist entirely of alphanumerics and underscores. Local plugins may override default parsers.
|
||||
|
||||
Note: The application data directory follows the XDG Base Directory Specification
|
||||
|
||||
.SH CAVEATS
|
||||
\fBLocale:\fP For best results set the \fBLANG\fP locale environment variable to \fBC\fP or \fBen_US.UTF-8\fP. For example, either by setting directly on the command-line:
|
||||
\fBLocale\fP
|
||||
|
||||
For best results set the \fBLANG\fP locale environment variable to \fBC\fP or \fBen_US.UTF-8\fP. For example, either by setting directly on the command-line:
|
||||
|
||||
.RS
|
||||
$ LANG=C date | jc \fB--date\fP
|
||||
@@ -201,9 +207,11 @@ or by exporting to the environment before running commands:
|
||||
$ export LANG=C
|
||||
.RE
|
||||
|
||||
On some older systems UTF-8 output will be downgraded to ASCII with `\\u` escape sequences if the \fBC\fP locale does not support UTF-8 encoding.
|
||||
On some older systems UTF-8 output will be downgraded to ASCII with \fB\\u\fP escape sequences if the \fBC\fP locale does not support UTF-8 encoding.
|
||||
|
||||
\fBTimezones:\fP Some parsers have calculated epoch timestamp fields added to the output. Unless a timestamp field name has a \fB_utc\fP suffix it is considered naive. (i.e. based on the local timezone of the system the \fBjc\fP parser was run on).
|
||||
\fBTimezones\fP
|
||||
|
||||
Some parsers have calculated epoch timestamp fields added to the output. Unless a timestamp field name has a \fB_utc\fP suffix it is considered naive. (i.e. based on the local timezone of the system the \fBjc\fP parser was run on).
|
||||
|
||||
If a UTC timezone can be detected in the text of the command output, the timestamp will be timezone aware and have a \fB_utc\fP suffix on the key name. (e.g. \fBepoch_utc\fP) No other timezones are supported for aware timestamps.
|
||||
|
||||
|
||||
@@ -111,13 +111,13 @@ pip3 install jc
|
||||
| Debian/Ubuntu linux | `apt-get install jc` |
|
||||
| Fedora linux | `dnf install jc` |
|
||||
| openSUSE linux | `zypper install jc` |
|
||||
| Archlinux User Repositories (AUR) | `paru -S jc` or `aura -A jc` or `yay -S jc` |
|
||||
| Archlinux Community Repository | `paru -S jc` or `aura -S jc` or `yay -S jc` |
|
||||
| NixOS linux | `nix-env -iA nixpkgs.jc` or `nix-env -iA nixos.jc` |
|
||||
| Guix System linux | `guix install jc` |
|
||||
| Gentoo Linux | `emerge dev-python/jc` |
|
||||
| macOS | `brew install jc` |
|
||||
| FreeBSD | `portsnap fetch update && cd /usr/ports/textproc/py-jc && make install clean` |
|
||||
| Ansible filter plugin | `ansible-galaxy collection install community.general` |
|
||||
| Gentoo Linux | `emerge dev-python/jc` |
|
||||
|
||||
> For more OS Packages, see https://repology.org/project/jc/versions.
|
||||
|
||||
@@ -143,12 +143,14 @@ The JSON output can be compact (default) or pretty formatted with the `-p`
|
||||
option.
|
||||
|
||||
### Parsers
|
||||
{% for parser in jc.parsers %}
|
||||
- `{{ parser.argument }}` enables the {{ parser.description }} ([documentation](https://kellyjonbrazil.github.io/jc/docs/parsers/{{ parser.name }})){% endfor %}
|
||||
|
||||
| Argument | Command or Filetype | Documentation |
|
||||
|-------------------|---------------------------------------------------------|-------------------------------------------------------------------------|{% for parser in jc.parsers %}
|
||||
| `{{ "{:>15}".format(parser.argument) }}` | {{ "{:<55}".format(parser.description) }} | {{ "{:<70}".format("[📃](https://kellyjonbrazil.github.io/jc/docs/parsers/" + parser.name + ")") }} |{% endfor %}
|
||||
|
||||
### Options
|
||||
- `-a` about `jc`. Prints information about `jc` and the parsers (in JSON, of
|
||||
course!)
|
||||
- `-a` about `jc`. Prints information about `jc` and the parsers (in JSON or
|
||||
YAML, of course!)
|
||||
- `-C` force color output even when using pipes (overrides `-m` and the
|
||||
`NO_COLOR` env variable)
|
||||
- `-d` debug mode. Prints trace messages if parsing issues are encountered (use
|
||||
@@ -162,6 +164,7 @@ option.
|
||||
values and no additional semantic processing
|
||||
- `-u` unbuffer output
|
||||
- `-v` version information
|
||||
- `-y` YAML output
|
||||
|
||||
### Exit Codes
|
||||
Any fatal errors within `jc` will generate an exit code of `100`, otherwise the
|
||||
@@ -208,11 +211,11 @@ color output will override both the `NO_COLOR` environment variable and the `-m`
|
||||
option.
|
||||
|
||||
### Streaming Parsers
|
||||
Most parsers load all of the data from STDIN, parse it, then output the entire
|
||||
Most parsers load all of the data from `STDIN`, parse it, then output the entire
|
||||
JSON document serially. There are some streaming parsers (e.g. `ls-s` and
|
||||
`ping-s`) that immediately start processing and outputing the data line-by-line
|
||||
as [JSON Lines](https://jsonlines.org/) (aka [NDJSON](http://ndjson.org/)) while
|
||||
it is being received from STDIN. This can significantly reduce the amount of
|
||||
it is being received from `STDIN`. This can significantly reduce the amount of
|
||||
memory required to parse large amounts of command output (e.g. `ls -lR /`) and
|
||||
can sometimes process the data more quickly. Streaming parsers have slightly
|
||||
different behavior than standard parsers as outlined below.
|
||||
@@ -277,14 +280,14 @@ $ ping 1.1.1.1 | jc --ping-s -u | jq
|
||||
|
||||
#### Using Streaming Parsers as Python Modules
|
||||
|
||||
Streaming parsers accept any iterable object and return an iterator object
|
||||
(generator) allowing lazy processing of the data. The input data should
|
||||
iterate on lines of string data. Examples of good input data are `sys.stdin` or
|
||||
Streaming parsers accept any iterable object and return an iterable object
|
||||
allowing lazy processing of the data. The input data should iterate on lines
|
||||
of string data. Examples of good input data are `sys.stdin` or
|
||||
`str.splitlines()`.
|
||||
|
||||
To use the generator object in your code, simply loop through it or use the
|
||||
[next()](https://docs.python.org/3/library/functions.html#next) builtin
|
||||
function:
|
||||
To use the returned iterable object in your code, simply loop through it or
|
||||
use the [next()](https://docs.python.org/3/library/functions.html#next)
|
||||
builtin function:
|
||||
```python
|
||||
import jc
|
||||
|
||||
@@ -307,8 +310,8 @@ or [`jc/parsers/foo_s.py (streaming)`](https://github.com/kellyjonbrazil/jc/blob
|
||||
parser as a template and simply place a `.py` file in the `jcparsers` subfolder.
|
||||
|
||||
Local plugin filenames must be valid python module names and therefore must
|
||||
start with a letter and consist entirely of alphanumerics. Local plugins
|
||||
may override default parsers.
|
||||
start with a letter and consist entirely of alphanumerics and underscores.
|
||||
Local plugins may override default parsers.
|
||||
|
||||
> Note: The application data directory follows the
|
||||
[XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html)
|
||||
@@ -341,15 +344,30 @@ If a UTC timezone can be detected in the text of the command output, the
|
||||
timestamp will be timezone aware and have a `_utc` suffix on the key name.
|
||||
(e.g. `epoch_utc`) No other timezones are supported for aware timestamps.
|
||||
|
||||
## Use In Other Shells
|
||||
`jc` can be used in most any shell. Some modern shells have JSON deserialization
|
||||
and filtering capabilities built-in which makes using `jc` even more convenient.
|
||||
|
||||
For example, the following is possible in [NGS](https://ngs-lang.org/)
|
||||
(Next Generation Shell):
|
||||
```bash
|
||||
myvar = ``jc dig www.google.com``[0].answer[0].data
|
||||
```
|
||||
This runs `jc`, parses the output JSON, and assigs the resulting data structure
|
||||
to a variable in a single line of code.
|
||||
|
||||
For more examples of how to use `jc` in other shells, see this
|
||||
[wiki page](https://github.com/kellyjonbrazil/jc/wiki/Using-jc-With-Different-Shells).
|
||||
|
||||
## Compatibility
|
||||
Some parsers like `dig`, `xml`, `csv`, etc. will work on any platform. Other
|
||||
parsers that convert platform-specific output will generate a warning message if
|
||||
they are run on an unsupported platform. To see all parser information,
|
||||
including compatibility, run `jc -ap`.
|
||||
|
||||
You may still use a parser on an unsupported platform - for example, you may want
|
||||
to parse a file with linux `lsof` output on an macOS or Windows laptop. In that
|
||||
case you can suppress the warning message with the `-q` cli option or the
|
||||
You may still use a parser on an unsupported platform - for example, you may
|
||||
want to parse a file with linux `lsof` output on an macOS or Windows laptop. In
|
||||
that case you can suppress the warning message with the `-q` cli option or the
|
||||
`quiet=True` function parameter in `parse()`:
|
||||
|
||||
macOS:
|
||||
@@ -378,7 +396,8 @@ Tested on:
|
||||
## Contributions
|
||||
Feel free to add/improve code or parsers! You can use the
|
||||
[`jc/parsers/foo.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo.py)
|
||||
or [`jc/parsers/foo_s.py (streaming)`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo_s.py) parsers as a template and submit your parser with a pull request.
|
||||
or [`jc/parsers/foo_s.py (streaming)`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/foo_s.py) parsers as a template and submit your parser with a pull
|
||||
request.
|
||||
|
||||
Please see the [Contributing Guidelines](https://github.com/kellyjonbrazil/jc/blob/master/CONTRIBUTING.md) for more information.
|
||||
|
||||
|
||||
1
tests/fixtures/centos-7.7/chage.json
vendored
Normal file
1
tests/fixtures/centos-7.7/chage.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"password_last_changed":"never","password_expires":"never","password_inactive":"never","account_expires":"never","min_days_between_password_change":0,"max_days_between_password_change":99999,"warning_days_before_password_expires":7}
|
||||
7
tests/fixtures/centos-7.7/chage.out
vendored
Normal file
7
tests/fixtures/centos-7.7/chage.out
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
Last password change : never
|
||||
Password expires : never
|
||||
Password inactive : never
|
||||
Account expires : never
|
||||
Minimum number of days between password change : 0
|
||||
Maximum number of days between password change : 99999
|
||||
Number of days of warning before password expires : 7
|
||||
1
tests/fixtures/centos-7.7/top-b-n1-gib-allfields-w-streaming.json
vendored
Normal file
1
tests/fixtures/centos-7.7/top-b-n1-gib-allfields-w-streaming.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1
tests/fixtures/centos-7.7/top-b-n1-gib-allfields-w.json
vendored
Normal file
1
tests/fixtures/centos-7.7/top-b-n1-gib-allfields-w.json
vendored
Normal file
File diff suppressed because one or more lines are too long
115
tests/fixtures/centos-7.7/top-b-n1-gib-allfields-w.out
vendored
Normal file
115
tests/fixtures/centos-7.7/top-b-n1-gib-allfields-w.out
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
top - 11:20:43 up 1:18, 2 users, load average: 0.00, 0.01, 0.05
|
||||
Tasks: 108 total, 2 running, 106 sleeping, 0 stopped, 0 zombie
|
||||
%Cpu(s): 5.6 us, 11.1 sy, 0.0 ni, 83.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
|
||||
GiB Mem : 3.7 total, 3.3 free, 0.2 used, 0.2 buff/cache
|
||||
GiB Swap: 2.0 total, 2.0 free, 0.0 used. 3.3 avail Mem
|
||||
|
||||
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND PPID UID RUID RUSER SUID SUSER GID GROUP PGRP TTY TPGID SID nTH P TIME SWAP CODE DATA nMaj nMin nDRT WCHAN Flags CGROUPS SUPGIDS SUPGRPS TGID ENVIRON vMj vMn USED nsIPC nsMNT nsNET nsPID nsUSER nsUTS
|
||||
2225 kbrazil 20 0 158.1m 2.2m 1.6m R 12.5 0.1 0:00.02 top 1884 1000 1000 kbrazil 1000 kbrazil 1000 kbrazil 2225 pts/0 2225 1884 1 0 0:00 0.0m 0.1m 1.0m 0 736 0 - ..4.2... 1:name=systemd:/user.slice/user-1000.+ 10,1000 wheel,kbrazil 2225 XDG_SESSION_ID=2 HOSTNAME=localhost S+ 0 4 2.2m 4026531839 4026531840 4026531956 4026531836 4026531837 4026531838
|
||||
1 root 20 0 125.1m 6.5m 4.1m S 0.0 0.2 0:01.47 systemd 0 0 0 root 0 root 0 root 1 ? -1 1 1 0 0:01 0.0m 1.4m 82.4m 63 13k 0 ep_poll ..4.21.. - - - 1 - 0 0 6.5m - - - - - -
|
||||
2 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kthreadd 0 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 kthreadd ..2.a.4. - - - 2 - 0 0 0.0m - - - - - -
|
||||
4 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kworker/0:0H 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 worker_th+ .42.a.6. - - - 4 - 0 0 0.0m - - - - - -
|
||||
6 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.10 ksoftirqd/0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 smpboot_t+ .42.a.4. - - - 6 - 0 0 0.0m - - - - - -
|
||||
7 root rt 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 migration/0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 smpboot_t+ .42.a.4. - - - 7 - 0 0 0.0m - - - - - -
|
||||
8 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 rcu_bh 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rcu_gp_kt+ ..2.a.4. - - - 8 - 0 0 0.0m - - - - - -
|
||||
9 root 20 0 0.0m 0.0m 0.0m R 0.0 0.0 0:00.49 rcu_sched 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 ? ..2.a.4. - - - 9 - 0 0 0.0m - - - - - -
|
||||
10 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 lru-add-drain 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 10 - 0 0 0.0m - - - - - -
|
||||
11 root rt 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.08 watchdog/0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 smpboot_t+ .42.a14. - - - 11 - 0 0 0.0m - - - - - -
|
||||
13 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kdevtmpfs 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 devtmpfsd ..2.a14. - - - 13 - 0 0 0.0m - - - - - -
|
||||
14 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 netns 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 14 - 0 0 0.0m - - - - - -
|
||||
15 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 khungtaskd 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 watchdog ..2.a.4. - - - 15 - 0 0 0.0m - - - - - -
|
||||
16 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 writeback 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 16 - 0 0 0.0m - - - - - -
|
||||
17 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kintegrityd 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 17 - 0 0 0.0m - - - - - -
|
||||
18 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 bioset 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 18 - 0 0 0.0m - - - - - -
|
||||
19 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 bioset 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 19 - 0 0 0.0m - - - - - -
|
||||
20 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 bioset 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 20 - 0 0 0.0m - - - - - -
|
||||
21 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kblockd 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 21 - 0 0 0.0m - - - - - -
|
||||
22 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 md 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 22 - 0 0 0.0m - - - - - -
|
||||
23 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 edac-poller 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 23 - 0 0 0.0m - - - - - -
|
||||
24 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 watchdogd 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 24 - 0 0 0.0m - - - - - -
|
||||
30 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kswapd0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 kswapd ..a4284. - - - 30 - 0 0 0.0m - - - - - -
|
||||
31 root 25 5 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 ksmd 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 ksm_scan_+ 4.2.2.4. - - - 31 - 0 0 0.0m - - - - - -
|
||||
32 root 39 19 0.0m 0.0m 0.0m S 0.0 0.0 0:00.03 khugepaged 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 khugepaged 4.2.2.4. - - - 32 - 0 0 0.0m - - - - - -
|
||||
33 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 crypto 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 33 - 0 0 0.0m - - - - - -
|
||||
41 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kthrotld 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 41 - 0 0 0.0m - - - - - -
|
||||
43 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kmpath_rdacd 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 43 - 0 0 0.0m - - - - - -
|
||||
44 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kaluad 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 44 - 0 0 0.0m - - - - - -
|
||||
45 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kpsmoused 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 45 - 0 0 0.0m - - - - - -
|
||||
47 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 ipv6_addrconf 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 47 - 0 0 0.0m - - - - - -
|
||||
60 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 deferwq 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 60 - 0 0 0.0m - - - - - -
|
||||
95 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kauditd 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 kauditd_t+ ..2.2.4. - - - 95 - 0 0 0.0m - - - - - -
|
||||
272 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 nfit 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 272 - 0 0 0.0m - - - - - -
|
||||
273 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 mpt_poll_0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 273 - 0 0 0.0m - - - - - -
|
||||
274 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 mpt/0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 274 - 0 0 0.0m - - - - - -
|
||||
275 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 ata_sff 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 275 - 0 0 0.0m - - - - - -
|
||||
321 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 scsi_eh_0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 scsi_erro+ ..2.a.4. - - - 321 - 0 0 0.0m - - - - - -
|
||||
326 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 scsi_tmf_0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 326 - 0 0 0.0m - - - - - -
|
||||
345 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.01 scsi_eh_1 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 scsi_erro+ ..2.a.4. - - - 345 - 0 0 0.0m - - - - - -
|
||||
346 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 scsi_tmf_1 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 346 - 0 0 0.0m - - - - - -
|
||||
347 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.01 scsi_eh_2 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 scsi_erro+ ..2.a.4. - - - 347 - 0 0 0.0m - - - - - -
|
||||
350 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 scsi_tmf_2 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 350 - 0 0 0.0m - - - - - -
|
||||
356 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kworker/u256:4 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 worker_th+ .42.a.6. - - - 356 - 0 0 0.0m - - - - - -
|
||||
359 root -51 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.02 irq/16-vmwgfx 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 irq_thread ..2.a14. - - - 359 - 0 0 0.0m - - - - - -
|
||||
360 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 ttm_swap 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 360 - 0 0 0.0m - - - - - -
|
||||
431 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kdmflush 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 431 - 0 0 0.0m - - - - - -
|
||||
432 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 bioset 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 432 - 0 0 0.0m - - - - - -
|
||||
442 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kdmflush 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 442 - 0 0 0.0m - - - - - -
|
||||
443 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 bioset 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 443 - 0 0 0.0m - - - - - -
|
||||
455 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 bioset 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 455 - 0 0 0.0m - - - - - -
|
||||
456 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfsalloc 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 456 - 0 0 0.0m - - - - - -
|
||||
457 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs_mru_cache 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 457 - 0 0 0.0m - - - - - -
|
||||
458 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-buf/dm-0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 458 - 0 0 0.0m - - - - - -
|
||||
459 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-data/dm-0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 459 - 0 0 0.0m - - - - - -
|
||||
460 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-conv/dm-0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 460 - 0 0 0.0m - - - - - -
|
||||
461 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-cil/dm-0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 461 - 0 0 0.0m - - - - - -
|
||||
462 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-reclaim/dm- 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 462 - 0 0 0.0m - - - - - -
|
||||
463 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-log/dm-0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 463 - 0 0 0.0m - - - - - -
|
||||
464 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-eofblocks/d 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 464 - 0 0 0.0m - - - - - -
|
||||
465 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.81 xfsaild/dm-0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 xfsaild 4.2.284. - - - 465 - 0 0 0.0m - - - - - -
|
||||
466 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.03 kworker/0:1H 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 worker_th+ .42.a.6. - - - 466 - 0 0 0.0m - - - - - -
|
||||
544 root 20 0 38.2m 3.2m 2.9m S 0.0 0.1 0:00.22 systemd-journal 1 0 0 root 0 root 0 root 544 ? -1 544 1 0 0:00 0.0m 0.3m 0.4m 7 3534 0 ep_poll ..4.21.. 3:devices:/system.slice/systemd-journ+ - - 544 - 0 0 3.2m - - - - - -
|
||||
565 root 20 0 196.4m 4.1m 2.5m S 0.0 0.1 0:00.01 lvmetad 1 0 0 root 0 root 0 root 565 ? -1 565 1 0 0:00 0.0m 0.1m 153.5m 1 1536 0 poll_sche+ 4.4.21.. 3:devices:/system.slice/lvm2-lvmetad.+ - - 565 - 0 0 4.1m - - - - - -
|
||||
575 root 20 0 47.0m 5.1m 2.8m S 0.0 0.1 0:00.20 systemd-udevd 1 0 0 root 0 root 0 root 575 ? -1 575 1 0 0:00 0.0m 0.4m 2.4m 3 3107 0 ep_poll ..4.21.. 3:devices:/system.slice/systemd-udevd+ - - 575 - 0 0 5.1m - - - - - -
|
||||
631 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kworker/u257:0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 worker_th+ .42.a.6. - - - 631 - 0 0 0.0m - - - - - -
|
||||
635 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 hci0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 635 - 0 0 0.0m - - - - - -
|
||||
636 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 hci0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 636 - 0 0 0.0m - - - - - -
|
||||
637 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kworker/u257:1 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 worker_th+ .42.a.6. - - - 637 - 0 0 0.0m - - - - - -
|
||||
649 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-buf/sda1 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 649 - 0 0 0.0m - - - - - -
|
||||
654 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-data/sda1 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 654 - 0 0 0.0m - - - - - -
|
||||
659 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-conv/sda1 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 659 - 0 0 0.0m - - - - - -
|
||||
660 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-cil/sda1 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 660 - 0 0 0.0m - - - - - -
|
||||
665 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-reclaim/sda 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 665 - 0 0 0.0m - - - - - -
|
||||
668 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-log/sda1 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 668 - 0 0 0.0m - - - - - -
|
||||
673 root 0 -20 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfs-eofblocks/s 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 rescuer_t+ .42.a.6. - - - 673 - 0 0 0.0m - - - - - -
|
||||
675 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 xfsaild/sda1 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 xfsaild 4.2.284. - - - 675 - 0 0 0.0m - - - - - -
|
||||
757 root 16 -4 54.2m 0.9m 0.5m S 0.0 0.0 0:00.01 auditd 1 0 0 root 0 root 0 root 757 ? -1 757 2 0 0:00 0.0m 0.1m 8.5m 0 218 0 ep_poll ..4.214. 3:devices:/system.slice/auditd.servic+ - - 757 - 0 0 0.9m - - - - - -
|
||||
784 root 20 0 56.2m 2.5m 2.1m S 0.0 0.1 0:00.01 bluetoothd 1 0 0 root 0 root 0 root 784 ? -1 784 1 0 0:00 0.0m 0.9m 0.4m 14 979 0 poll_sche+ 4.4.21.. 3:devices:/system.slice/bluetooth.ser+ - - 784 - 0 0 2.5m - - - - - -
|
||||
785 root 20 0 25.8m 1.8m 1.4m S 0.0 0.0 0:00.08 systemd-logind 1 0 0 root 0 root 0 root 785 ? -1 785 1 0 0:00 0.0m 0.6m 0.4m 4 820 0 ep_poll ..4.21.. 3:devices:/system.slice/systemd-login+ - - 785 - 0 0 1.8m - - - - - -
|
||||
788 root 20 0 51.6m 2.7m 1.9m S 0.0 0.1 0:00.02 smartd 1 0 0 root 0 root 0 root 788 ? -1 788 1 0 0:00 0.0m 0.6m 0.6m 9 1004 0 hrtimer_n+ 4.4.21.. 3:devices:/system.slice/smartd.servic+ - - 788 - 0 0 2.7m - - - - - -
|
||||
789 polkitd 20 0 598.6m 12.7m 4.8m S 0.0 0.3 0:00.11 polkitd 1 999 999 polkitd 999 polkitd 998 polkitd 789 ? -1 789 7 0 0:00 0.0m 0.1m 512.3m 48 2646 0 poll_sche+ 4.4.21.. 3:devices:/system.slice/polkit.servic+ 998 polkitd 789 - 0 0 12.7m - - - - - -
|
||||
790 dbus 20 0 64.9m 2.6m 1.8m S 0.0 0.1 0:00.21 dbus-daemon 1 81 81 dbus 81 dbus 81 dbus 790 ? -1 790 2 0 0:00 0.0m 0.2m 8.7m 2 869 0 ep_poll ..4.21.. 3:devices:/system.slice/dbus.service,+ - - 790 - 0 0 2.6m - - - - - -
|
||||
797 chrony 20 0 115.0m 1.8m 1.3m S 0.0 0.0 0:00.08 chronyd 1 998 998 chrony 998 chrony 996 chrony 796 ? -1 796 1 0 0:00 0.0m 0.2m 72.4m 3 462 0 poll_sche+ 4.4.214. 3:devices:/system.slice/chronyd.servi+ - - 797 - 0 0 1.8m - - - - - -
|
||||
838 root 20 0 123.3m 1.6m 1.0m S 0.0 0.0 0:00.50 crond 1 0 0 root 0 root 0 root 838 ? -1 838 1 0 0:00 0.0m 0.1m 1.3m 1 771 0 hrtimer_n+ 4.4.21.. 3:devices:/system.slice/crond.service+ - - 838 - 0 0 1.6m - - - - - -
|
||||
858 root 20 0 350.3m 28.8m 6.9m S 0.0 0.8 0:00.64 firewalld 1 0 0 root 0 root 0 root 858 ? -1 858 2 0 0:00 0.0m 0.0m 93.1m 64 53k 0 poll_sche+ 4.4.21.. 3:devices:/system.slice/firewalld.ser+ - - 858 - 0 0 28.8m - - - - - -
|
||||
859 root 20 0 107.5m 0.8m 0.7m S 0.0 0.0 0:00.00 agetty 1 0 0 root 0 root 0 root 859 ttyS0 859 859 1 0 0:00 0.0m 0.0m 0.3m 1 394 0 n_tty_read ..4.21.. 3:devices:/system.slice/system-serial+ - - 859 - 0 0 0.8m - - - - - -
|
||||
860 root 20 0 94.3m 2.5m 1.8m S 0.0 0.1 0:00.13 login 1 0 0 root 0 root 1000 kbrazil 860 ? -1 860 1 0 0:00 0.0m 0.0m 0.8m 9 1265 0 do_wait ..4.21.. 1:name=systemd:/user.slice/user-1000.+ 10,1000 wheel,kbrazil 860 - 0 0 2.5m - - - - - -
|
||||
883 root 20 0 813.4m 8.8m 6.7m S 0.0 0.2 0:00.28 NetworkManager 1 0 0 root 0 root 0 root 883 ? -1 883 3 0 0:00 0.0m 2.7m 561.5m 51 2944 0 poll_sche+ 4.4.21.. 3:devices:/system.slice/NetworkManage+ - - 883 - 0 0 8.8m - - - - - -
|
||||
1033 root 20 0 100.5m 5.3m 3.3m S 0.0 0.1 0:00.02 dhclient 883 0 0 root 0 root 0 root 1033 ? -1 883 1 0 0:00 0.0m 0.4m 1.7m 15 1840 0 poll_sche+ 4.4.21.. 3:devices:/system.slice/NetworkManage+ - - 1033 - 0 0 5.3m - - - - - -
|
||||
1224 root 20 0 560.7m 17.0m 6.0m S 0.0 0.5 0:00.97 tuned 1 0 0 root 0 root 0 root 1224 ? -1 1224 5 0 0:00 0.0m 0.0m 297.9m 5 9147 0 poll_sche+ 4.4.21.. 3:devices:/system.slice/tuned.service+ - - 1224 - 0 0 17.0m - - - - - -
|
||||
1225 root 20 0 565.2m 25.1m 12.9m S 0.0 0.7 0:06.57 dockerd-current 1 0 0 root 0 root 0 root 1225 ? -1 1225 9 0 0:06 0.0m 31.1m 464.2m 234 7475 0 do_wait ..4.21.. 3:devices:/system.slice/docker.servic+ - - 1225 - 0 0 25.1m - - - - - -
|
||||
1227 root 20 0 110.3m 4.2m 3.2m S 0.0 0.1 0:00.01 sshd 1 0 0 root 0 root 0 root 1227 ? -1 1227 1 0 0:00 0.0m 0.8m 0.7m 8 1323 0 poll_sche+ 4.4.21.. 3:devices:/system.slice/sshd.service,+ - - 1227 - 0 0 4.2m - - - - - -
|
||||
1228 root 20 0 213.4m 4.3m 3.3m S 0.0 0.1 0:00.65 rsyslogd 1 0 0 root 0 root 0 root 1228 ? -1 1228 3 0 0:00 0.0m 0.6m 145.3m 9 1533 0 poll_sche+ 4.4.21.. 3:devices:/system.slice/rsyslog.servi+ - - 1228 - 0 0 4.3m - - - - - -
|
||||
1272 root 20 0 280.5m 10.9m 5.1m S 0.0 0.3 0:03.09 docker-containe 1225 0 0 root 0 root 0 root 1272 ? -1 1272 8 0 0:03 0.0m 6.5m 255.8m 46 3932 0 futex_wai+ 4.4.21.. 3:devices:/system.slice/docker.servic+ - - 1272 - 0 0 10.9m - - - - - -
|
||||
1501 root 20 0 87.6m 2.1m 1.1m S 0.0 0.1 0:00.04 master 1 0 0 root 0 root 0 root 1501 ? -1 1501 1 0 0:00 0.0m 0.2m 0.8m 0 423 0 ep_poll ..4.214. 3:devices:/system.slice/postfix.servi+ 0 root 1501 - 0 0 2.1m - - - - - -
|
||||
1511 postfix 20 0 87.7m 4.0m 3.0m S 0.0 0.1 0:00.01 pickup 1501 89 89 postfix 89 postfix 89 postfix 1501 ? -1 1501 1 0 0:00 0.0m 0.3m 0.8m 1 1166 0 ep_poll ..4.21.. 3:devices:/system.slice/postfix.servi+ 12,89 mail,postfix 1511 - 0 0 4.0m - - - - - -
|
||||
1512 postfix 20 0 87.8m 4.0m 3.0m S 0.0 0.1 0:00.01 qmgr 1501 89 89 postfix 89 postfix 89 postfix 1501 ? -1 1501 1 0 0:00 0.0m 0.3m 0.8m 1 1195 0 ep_poll ..4.21.. 3:devices:/system.slice/postfix.servi+ 12,89 mail,postfix 1512 - 0 0 4.0m - - - - - -
|
||||
1859 kbrazil 20 0 113.0m 2.3m 1.5m S 0.0 0.1 0:00.01 bash 860 1000 1000 kbrazil 1000 kbrazil 1000 kbrazil 1859 tty1 1859 1859 1 0 0:00 0.0m 0.9m 0.7m 1 1226 0 n_tty_read ..4.21.. 1:name=systemd:/user.slice/user-1000.+ 10,1000 wheel,kbrazil 1859 HOME=/home/kbrazil USER=kbrazil SHELL+ 0 0 2.3m 4026531839 4026531840 4026531956 4026531836 4026531837 4026531838
|
||||
1879 root 20 0 155.2m 5.6m 4.3m S 0.0 0.1 0:00.16 sshd 1227 0 0 root 0 root 0 root 1879 ? -1 1879 1 0 0:00 0.0m 0.8m 0.9m 0 1849 0 poll_sche+ 4.4.21.. 1:name=systemd:/user.slice/user-1000.+ - - 1879 - 0 0 5.6m - - - - - -
|
||||
1883 kbrazil 20 0 155.2m 2.4m 1.1m S 0.0 0.1 0:01.29 sshd 1879 1000 1000 kbrazil 1000 kbrazil 1000 kbrazil 1879 ? -1 1879 1 0 0:01 0.0m 0.8m 0.9m 0 362 0 poll_sche+ 4.4.214. 1:name=systemd:/user.slice/user-1000.+ 10,1000 wheel,kbrazil 1883 - 0 0 2.4m - - - - - -
|
||||
1884 kbrazil 20 0 112.9m 2.2m 1.6m S 0.0 0.1 0:00.07 bash 1883 1000 1000 kbrazil 1000 kbrazil 1000 kbrazil 1884 pts/0 2225 1884 1 0 0:00 0.0m 0.9m 0.6m 0 2593 0 do_wait ..4.2... 1:name=systemd:/user.slice/user-1000.+ 10,1000 wheel,kbrazil 1884 LANG=en_US.UTF-8 USER=kbrazil LOGNAME+ 0 0 2.2m 4026531839 4026531840 4026531956 4026531836 4026531837 4026531838
|
||||
2019 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.11 kworker/u256:0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 worker_th+ .42.a.6. - - - 2019 - 0 0 0.0m - - - - - -
|
||||
2117 root 20 0 122.4m 1.1m 0.9m S 0.0 0.0 0:00.00 anacron 1 0 0 root 0 root 0 root 2117 ? -1 2117 1 0 0:00 0.0m 0.0m 0.4m 0 281 0 sigsuspend ..4.2.4. 1:name=systemd:/user.slice/user-0.sli+ 0 root 2117 - 0 0 1.1m - - - - - -
|
||||
2139 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.36 kworker/0:2 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 worker_th+ .42.a.6. - - - 2139 - 0 0 0.0m - - - - - -
|
||||
2197 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.01 kworker/0:3 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 worker_th+ .42.a.6. - - - 2197 - 0 0 0.0m - - - - - -
|
||||
2205 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.01 kworker/0:0 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 worker_th+ .42.a.6. - - - 2205 - 0 0 0.0m - - - - - -
|
||||
2213 root 20 0 0.0m 0.0m 0.0m S 0.0 0.0 0:00.00 kworker/0:1 2 0 0 root 0 root 0 root 0 ? -1 0 1 0 0:00 0.0m 0.0m 0.0m 0 0 0 worker_th+ .42.a.6. - - - 2213 - 0 0 0.0m - - 5678 - 1234 -
|
||||
1
tests/fixtures/centos-7.7/top-b-n1-gib-streaming.json
vendored
Normal file
1
tests/fixtures/centos-7.7/top-b-n1-gib-streaming.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