1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2026-04-03 17:44:07 +02:00

Compare commits

..

78 Commits
v1.25.5 ... dev

Author SHA1 Message Date
Kelly Brazil
3f2cd81ca7 doc update 2026-03-30 11:51:22 -07:00
Kelly Brazil
6c8aafa2c5 Merge pull request #688 from queelius/fix/dir-lstrip-drive-letter
Fix dir parser: lstrip strips D: drive letter from path
2026-03-30 11:49:51 -07:00
Kelly Brazil
41e2e16436 Merge branch 'dev' into fix/dir-lstrip-drive-letter 2026-03-30 11:46:32 -07:00
Kelly Brazil
20b625860e Merge pull request #686 from queelius/fix/ifconfig-lstrip-hex-mask
Fix ifconfig hex mask conversion: lstrip('0x') -> [2:]
2026-03-30 11:44:57 -07:00
Kelly Brazil
0d703cd3a8 Merge branch 'dev' into fix/ifconfig-lstrip-hex-mask 2026-03-30 11:41:36 -07:00
Kelly Brazil
7b3d345d62 doc update 2026-03-30 11:36:22 -07:00
Kelly Brazil
53b6f1b329 Merge pull request #689 from ReinerBRO/fix/pip-show-files-section
Handle pip show Files sections
2026-03-30 11:29:59 -07:00
Kelly Brazil
ecc267b3cb Merge branch 'dev' into fix/pip-show-files-section 2026-03-30 11:20:09 -07:00
Kelly Brazil
5d2496b5f7 doc update 2026-03-30 10:52:43 -07:00
Kelly Brazil
810eeba724 version bump 2026-03-30 10:50:56 -07:00
Kelly Brazil
fb5c1b9c94 Merge pull request #692 from juliosuas/fix/ifconfig-lstrip-hex-mask
fix: use [2:] instead of lstrip('0x') to strip hex prefix in ifconfig parser
2026-03-30 10:46:54 -07:00
Kelly Brazil
f797127ca9 Merge branch 'dev' into fix/ifconfig-lstrip-hex-mask 2026-03-30 10:39:54 -07:00
Julio César Suástegui
56bd860a5e fix: use [2:] instead of lstrip('0x') to strip hex prefix in ifconfig parser
str.lstrip('0x') strips any combination of '0' and 'x' characters from
the left, not the literal two-character prefix '0x'. For subnet masks
where the hex digits start with '0' (e.g. '0x00000000' for a /0 mask),
lstrip strips all leading zeros along with the 'x', producing an empty
string instead of '00000000'.

Replace with a slice [2:] which correctly removes exactly the first two
characters ('0x') regardless of what follows.

This bug affected both the legacy ipv4_mask field and the ipv4[] list
items in _process() (lines 267 and 292).

Fixes #685
2026-03-30 03:07:11 -06:00
ReinerBRO
9fe659d625 Handle pip show files sections 2026-03-26 14:14:11 +08:00
Alex Towell
128e36404d Fix dir parser stripping D: drive letter from parent directory path
lstrip(" Directory of ") strips any character in the set
{' ','D','i','r','e','c','t','o','y','f'}, which incorrectly removes
the 'D' from D:\ paths. Use fixed-length prefix removal with [len():]
instead.

Fixes #687

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 03:14:43 -05:00
Alex Towell
2f9377cb67 Fix ifconfig hex mask conversion using lstrip('0x') instead of [2:]
lstrip('0x') strips any character in {'0','x'} from the left, not the
literal prefix "0x". This causes incorrect mask conversion for masks
with leading zero hex digits (e.g. 0x00000000 -> empty string instead
of 0.0.0.0).

Replace lstrip('0x') with [2:] to correctly remove only the '0x'
prefix. Fixes both the legacy ipv4_mask field and the ipv4[] list.

Fixes #685

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 03:12:34 -05:00
Kelly Brazil
585ff83a2e update changelog 2026-03-16 12:29:46 -07:00
Kelly Brazil
45b23e8b3c version bump 2026-03-16 12:18:49 -07:00
Kelly Brazil
b9eec1a5cd Merge pull request #673 from native-api/haslib_mode
Correctly parse mode indicators in hashsum output
2026-03-16 12:15:18 -07:00
Kelly Brazil
47545833ed Merge branch 'dev' into haslib_mode 2026-03-16 12:05:52 -07:00
Kelly Brazil
6f8e4fb2ed Merge pull request #679 from jylenhof/master
docs(README): add mise alternate installation documentation
2026-03-16 12:01:45 -07:00
Kelly Brazil
4f7821ac8e Merge branch 'dev' into master 2026-03-16 12:00:13 -07:00
Kelly Brazil
7f2722ff96 remove int_value field and add tests 2026-03-13 15:16:54 -07:00
Kelly Brazil
1d19de3005 add typeset and declare command parser 2026-03-10 18:16:53 -07:00
Kelly Brazil
e01287b329 add stats fields to json output. #676 2026-03-09 17:35:33 -07:00
Kelly Brazil
441bcbde80 fix indent on help text so lines don't wrap over 80 chars. Also fix mypy uncovered value assignment issue. 2026-03-06 15:50:52 -08:00
Kelly Brazil
936432d879 Fix parsing blank targe in verbose output #675 2026-03-06 12:59:16 -08:00
Kelly Brazil
51543437d7 remove comment 2026-02-27 14:57:59 -08:00
Kelly Brazil
dd9229f161 Merge branch 'dev' of https://github.com/kellyjonbrazil/jc into dev 2026-02-27 14:55:50 -08:00
Kelly Brazil
3d9554baec force tests 2026-02-27 14:55:45 -08:00
Kelly Brazil
e33a81269c update os matrix and python versions for tests 2026-02-27 14:54:15 -08:00
Kelly Brazil
f3352352ed fix unknown flags throwing key error (#681) 2026-02-27 12:08:08 -08:00
Kelly Brazil
1c0a35dff8 version bump 2026-02-27 11:37:58 -08:00
jylenhof
8ba75794a6 docs(README): add mise alternate installation documentation
Signed-off-by: jylenhof <jygithub@lenhof.eu.org>
2026-01-10 11:07:10 +01:00
Ivan Pozdeev
77af5ac9d3 Revert ".gitignore: + Pycharm metadata"
This reverts commit 0363ddcc6a.
2025-12-16 03:26:09 +03:00
Ivan Pozdeev
4067bfed9f Support friendly names for modes; rename files and tests to indicate non-default modes 2025-12-16 02:43:16 +03:00
Ivan Pozdeev
0363ddcc6a .gitignore: + Pycharm metadata 2025-12-16 02:07:14 +03:00
Ivan Pozdeev
04303efa75 Fix tests 2025-12-16 01:28:18 +03:00
Ivan Pozdeev
956f74358b Add tests for other mode indicators 2025-12-15 23:42:13 +03:00
Ivan Pozdeev
4fe3377029 Support other mode symbols -- e.g. 'U' and '^' from Perl shasum
Accept any symbol for future-proofing
2025-12-15 23:31:16 +03:00
Ivan Pozdeev
1944a7145e Fix erroneous redundant find&replace 2025-12-11 07:23:53 +03:00
Ivan Pozdeev
3d698e50c0 fix 2025-12-11 07:12:55 +03:00
Ivan Pozdeev
5945ded816 Fix incompatibility with 3.6; more specific regex 2025-12-11 07:10:36 +03:00
Ivan Pozdeev
ecd0e03c66 Parse the mode indicator in *sum output
In accordance with shasum(1) manpage
For legacy md5, set it to blank
2025-12-11 07:01:26 +03:00
Kelly Brazil
9fd13e6987 Merge pull request #671 from kellyjonbrazil/dev
Dev v1.25.6
2025-10-12 18:52:52 -07:00
Kelly Brazil
1feb000231 doc update 2025-10-12 18:09:31 -07:00
Kelly Brazil
d270ddc6ce fixup traceroute and traceroute-s parsers 2025-10-12 17:58:37 -07:00
Shintaro Kojima
07ef285b06 Add traceroute streaming parser - traceroute-s (#669)
* test: split out test fixtures for long ipv6 traceroute for consistency

* refactor(jc/parsers/traceroute): remove duplicate ParseError class

* refactor(jc/parsers/traceroute): pre-process data in _loads() for easy-to-reuse

* refactor(jc/parsers/traceroute): split hop serialization into separate function to reuse

* refactor(jc/parsers/traceroute): simplify numeric conversion and make it reusable for traceroute_s

* fix(jc/parsers/traceroute): stricter regex to match traceroute headers only

* feat(jc/parsers/traceroute_s): v1.0 implementation

* fix(jc/parsers/traceroute): revert "_" prefix in function and class names

* fixup! fix(jc/parsers/traceroute): revert "_" prefix in function and class names

* chore(jc/parsers/traceroute): update the author information
2025-10-12 10:21:16 -07:00
Kelly Brazil
467ad60e20 Fix for who output containing process name #663 2025-09-08 17:14:37 -07:00
Kelly Brazil
91b3572ead parser version bump 2025-09-08 15:04:48 -07:00
Brian Wo
60caa17eb9 add yay as magic command for pacman (#657)
yay is a popular pacman wrapper that adds extra functionality to
standard pacman. It has the same output format as pacman.

Co-authored-by: Kelly Brazil <kellyjonbrazil@gmail.com>
2025-09-08 14:59:55 -07:00
Kelly Brazil
eea31ddbe4 add .DS_Store to gitignore 2025-09-08 14:56:43 -07:00
Kelly Brazil
61793bba31 fix net_localgroup tests 2025-09-08 14:54:45 -07:00
Kelly Brazil
51e4a476ba fixup net_localgroup parser 2025-09-08 14:44:13 -07:00
Kelly Brazil
883f0c9cf7 net-user parser fixup 2025-09-08 14:25:44 -07:00
Kelly Brazil
ffaf455d43 doc updates 2025-09-04 16:59:21 -07:00
Kelly Brazil
b520532578 fixup route-print parser 2025-09-04 16:43:18 -07:00
Jose E. Rodriguez
3b1af1a9b6 Feat: Introduce net-localgroup net-user and route-print parsers (#602)
* feat(patch): introduce net localgroup, net user, and route print parsers

* fix: fix net user parsing error

* fix: address PR findings

---------

Co-authored-by: Kelly Brazil <kellyjonbrazil@gmail.com>
2025-09-04 14:47:28 -07:00
Kelly Brazil
0fa5f7f67f add test 2025-08-03 17:19:21 -07:00
Kelly Brazil
a77298e560 add cable_pairing field to fix #662 2025-08-01 07:41:45 -07:00
Kelly Brazil
5f75df2e4b remove force test comment 2025-07-24 13:13:21 -07:00
Kelly Brazil
38d169f4d0 force tests 2025-07-24 13:09:44 -07:00
Kelly Brazil
e737dde9e0 windows 2019 runner deprecated - move to windows 2022 2025-07-24 13:08:15 -07:00
Kelly Brazil
6e49c87575 update tests 2025-07-24 13:02:37 -07:00
Kelly Brazil
6afa6b449e add unit and byte conversion fields 2025-07-08 12:30:41 -07:00
Kelly Brazil
424d9c1347 add unit string fields and topline bytes fields 2025-07-08 11:45:47 -07:00
Kelly Brazil
10d1ab1c74 add bytes fields 2025-07-08 08:50:12 -07:00
Kelly Brazil
5db256c3e7 add x509-crl parser tests 2025-06-06 15:23:42 -07:00
Kelly Brazil
7f7dcc35ec help screen update 2025-05-28 14:54:29 -07:00
Kelly Brazil
edcde58cb9 remove unused Dict type import 2025-05-28 13:18:00 -07:00
Kelly Brazil
3a7ca118ff doc updates 2025-05-27 09:06:26 -07:00
Kelly Brazil
f36c713110 doc fix 2025-05-20 17:58:04 -07:00
Kelly Brazil
0db2ad2f5e doc fix 2025-05-20 17:56:15 -07:00
Kelly Brazil
816c38e1fe now returns only a single object, not an array of CRL objects 2025-05-20 17:47:05 -07:00
Kelly Brazil
e4cf7b502e doc update 2025-05-18 20:16:58 -07:00
Kelly Brazil
4ca7179481 add x509-crl parser 2025-05-18 20:09:05 -07:00
Kelly Brazil
bebd6a60fb add team-port.config and fix for blank values 2025-05-18 19:24:54 -07:00
Kelly Brazil
5d7940a89b version bump 2025-05-18 19:24:19 -07:00
240 changed files with 11707 additions and 548 deletions

View File

@@ -9,69 +9,14 @@ on:
- "**/*.py"
jobs:
very_old_python:
if: github.event.pull_request.draft == false
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-13, windows-2019]
python-version: ["3.6"]
steps:
- uses: actions/checkout@v3
- name: "Set up timezone to America/Los_Angeles"
uses: szenius/set-timezone@v1.2
with:
timezoneLinux: "America/Los_Angeles"
timezoneMacos: "America/Los_Angeles"
timezoneWindows: "Pacific Standard Time"
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Test with unittest
run: |
python -m unittest discover tests
old_python:
if: github.event.pull_request.draft == false
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-13, ubuntu-22.04, windows-2019]
python-version: ["3.7", "3.8", "3.9", "3.10"]
steps:
- uses: actions/checkout@v3
- name: "Set up timezone to America/Los_Angeles"
uses: szenius/set-timezone@v1.2
with:
timezoneLinux: "America/Los_Angeles"
timezoneMacos: "America/Los_Angeles"
timezoneWindows: "Pacific Standard Time"
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Test with unittest
run: |
python -m unittest discover tests
latest_python:
if: github.event.pull_request.draft == false
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
python-version: ["3.11", "3.12"]
os: [macos-15-intel, macos-latest, ubuntu-latest, ubuntu-24.04-arm, windows-latest]
python-version: ["3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v3
@@ -92,3 +37,59 @@ jobs:
- name: Test with unittest
run: |
python -m unittest discover tests
# very_old_python:
# if: github.event.pull_request.draft == false
# runs-on: ${{ matrix.os }}
# strategy:
# matrix:
# os: [macos-13, windows-2022]
# python-version: ["3.6"]
# steps:
# - uses: actions/checkout@v3
# - name: "Set up timezone to America/Los_Angeles"
# uses: szenius/set-timezone@v1.2
# with:
# timezoneLinux: "America/Los_Angeles"
# timezoneMacos: "America/Los_Angeles"
# timezoneWindows: "Pacific Standard Time"
# - name: Set up Python ${{ matrix.python-version }}
# uses: actions/setup-python@v4
# with:
# python-version: ${{ matrix.python-version }}
# - name: Install dependencies
# run: |
# python -m pip install --upgrade pip
# pip install -r requirements.txt
# - name: Test with unittest
# run: |
# python -m unittest discover tests
# old_python:
# if: github.event.pull_request.draft == false
# runs-on: ${{ matrix.os }}
# strategy:
# matrix:
# os: [macos-13, ubuntu-22.04, windows-2022]
# python-version: ["3.7", "3.8", "3.9", "3.10"]
# steps:
# - uses: actions/checkout@v3
# - name: "Set up timezone to America/Los_Angeles"
# uses: szenius/set-timezone@v1.2
# with:
# timezoneLinux: "America/Los_Angeles"
# timezoneMacos: "America/Los_Angeles"
# timezoneWindows: "Pacific Standard Time"
# - name: Set up Python ${{ matrix.python-version }}
# uses: actions/setup-python@v4
# with:
# python-version: ${{ matrix.python-version }}
# - name: Install dependencies
# run: |
# python -m pip install --upgrade pip
# pip install -r requirements.txt
# - name: Test with unittest
# run: |
# python -m unittest discover tests

1
.gitignore vendored
View File

@@ -7,3 +7,4 @@ build/
.vscode/
_config.yml
.venv
.DS_Store

View File

@@ -1,5 +1,30 @@
jc changelog
20260330 v1.25.7
- Add `typeset` and `declare` Bash internal command parser to convert variables
simple arrays, and associative arrays along with object metadata
- Enhance `pip-show` command parser to add `-f` show files support
- Enhance `rsync` and `rsync-s` parsers to add `--stats` or `--info=stats[1-3]` fields
- Fix `hashsum` command parser to correctly parse the `mode` indicator
- Fix `dir` command parser for incorrect stripping of the `D:` drive letter
- Fix `proc-pid-smaps` proc parser when unknown VmFlags are output
- Fix `ifconfig` command parser for incorrect stripping of leading zeros in some hex numbers
- Fix `iptables` command parser when Target is blank and verbose output is used
20251012 v1.25.6
- Add `net-localgroup` Windows command parser
- Add `net-user` Windows command parser
- Add `route-print` Windows command parser
- Add `traceroute-s` streaming command parser
- Add `max_hops` and `data_bytes` fields to `traceroute` command parser
- Add `x509-crl` file parser to support Certificate Revocation List PEM and DER files
- Add `yay` as a magic command for the `pacman` command parser
- Fix `bluetoothctl` command parser to support output with the `cable_pairing` attribute
- Fix `nmcli` command parser to support blank `team.config` JSON value and `team-port.config` JSON value
- Fix `top` command parsers to correct memory size field parsing. Several new unit
and byte conversion fields have been added
- Fix `who` command parser to support the `process` field on Debian13
20250503 v1.25.5
- Add `amixer` command parser
- Enhance `iptables` command parser to add default policy statistics fields

View File

@@ -1,4 +1,3 @@
[![Tests](https://github.com/kellyjonbrazil/jc/workflows/Tests/badge.svg?branch=master)](https://github.com/kellyjonbrazil/jc/actions)
[![Pypi](https://img.shields.io/pypi/v/jc.svg)](https://pypi.org/project/jc/)
> Check out the `jc` Python [package documentation](https://github.com/kellyjonbrazil/jc/tree/master/docs) for developers
@@ -124,6 +123,7 @@ pip3 install jc
| FreeBSD | `portsnap fetch update && cd /usr/ports/textproc/py-jc && make install clean` |
| Ansible filter plugin | `ansible-galaxy collection install community.general` |
| FortiSOAR connector | Install from FortiSOAR Connector Marketplace |
| Mise-en-place (Linux/MacOS) | `mise use -g jc@latest` |
> For more OS Packages, see https://repology.org/project/jc/versions.
@@ -246,6 +246,8 @@ option.
| `--mpstat-s` | `mpstat` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/mpstat_s) |
| `--needrestart` | `needrestart -b` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/needrestart) |
| `--netstat` | `netstat` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/netstat) |
| `--net-localgroup` | `net localgroup` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/net_localgroup) |
| `--net-user` | `net user` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/net_user) |
| `--nmcli` | `nmcli` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/nmcli) |
| `--nsd-control` | `nsd-control` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/nsd_control) |
| `--ntpq` | `ntpq -p` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ntpq) |
@@ -272,6 +274,7 @@ option.
| `--ps` | `ps` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ps) |
| `--resolve-conf` | `/etc/resolve.conf` file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/resolve_conf) |
| `--route` | `route` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/route) |
| `--route-print` | `route print` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/route_print) |
| `--rpm-qi` | `rpm -qi` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rpm_qi) |
| `--rsync` | `rsync` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync) |
| `--rsync-s` | `rsync` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/rsync_s) |
@@ -303,6 +306,7 @@ option.
| `--top-s` | `top -b` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/top_s) |
| `--tracepath` | `tracepath` and `tracepath6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/tracepath) |
| `--traceroute` | `traceroute` and `traceroute6` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/traceroute) |
| `--traceroute-s` | `traceroute` and `traceroute6` command streaming parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/traceroute_s) |
| `--tune2fs` | `tune2fs -l` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/tune2fs) |
| `--udevadm` | `udevadm info` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/udevadm) |
| `--ufw` | `ufw status` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/ufw) |
@@ -322,6 +326,7 @@ option.
| `--wg-show` | `wg show` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/wg_show) |
| `--who` | `who` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/who) |
| `--x509-cert` | X.509 PEM and DER certificate file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/x509_cert) |
| `--x509-crl` | X.509 PEM and DER certificate revocation list file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/x509_crl) |
| `--x509-csr` | X.509 PEM and DER certificate request file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/x509_csr) |
| `--xml` | XML file parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/xml) |
| `--xrandr` | `xrandr` command parser | [details](https://kellyjonbrazil.github.io/jc/docs/parsers/xrandr) |

View File

@@ -3,8 +3,8 @@ _jc()
local cur prev words cword jc_commands jc_parsers jc_options \
jc_about_options jc_about_mod_options jc_help_options jc_special_options
jc_commands=(acpi airport amixer apt-cache apt-get arp blkid bluetoothctl cbt certbot chage cksum crontab curl date debconf-show df dig dmidecode dpkg du efibootmgr env ethtool file findmnt finger free git gpg hciconfig host id ifconfig iostat ip ipconfig iptables iw iwconfig jobs last lastb ls lsattr lsb_release lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat needrestart netstat nmcli nsd-control ntpq os-prober pacman pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum swapon sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 tune2fs udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc wg who xrandr zipinfo zpool)
jc_parsers=(--acpi --airport --airport-s --amixer --apt-cache-show --apt-get-sqq --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --curl-head --date --datetime-iso --debconf-show --df --dig --dir --dmidecode --dpkg-l --du --efibootmgr --email-address --env --ethtool --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --host --hosts --http-headers --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --ipconfig --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --kv-dup --last --ls --ls-s --lsattr --lsb-release --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --needrestart --netstat --nmcli --nsd-control --ntpq --openvpn --os-prober --os-release --pacman --passwd --path --path-list --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --pkg-index-apk --pkg-index-deb --plist --postconf --proc --proc-buddyinfo --proc-cmdline --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --swapon --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --tune2fs --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --wg-show --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status)
jc_commands=(acpi airport amixer apt-cache apt-get arp blkid bluetoothctl cbt certbot chage cksum crontab curl date debconf-show df dig dmidecode dpkg du efibootmgr env ethtool file findmnt finger free git gpg hciconfig host id ifconfig iostat ip ipconfig iptables iw iwconfig jobs last lastb ls lsattr lsb_release lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat needrestart net netstat nmcli nsd-control ntpq os-prober pacman pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum swapon sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 tune2fs udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc wg who xrandr yay zipinfo zpool)
jc_parsers=(--acpi --airport --airport-s --amixer --apt-cache-show --apt-get-sqq --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --curl-head --date --datetime-iso --debconf-show --df --dig --dir --dmidecode --dpkg-l --du --efibootmgr --email-address --env --ethtool --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --host --hosts --http-headers --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --ipconfig --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --kv-dup --last --ls --ls-s --lsattr --lsb-release --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --needrestart --netstat --net-localgroup --net-user --nmcli --nsd-control --ntpq --openvpn --os-prober --os-release --pacman --passwd --path --path-list --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --pkg-index-apk --pkg-index-deb --plist --postconf --proc --proc-buddyinfo --proc-cmdline --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --route-print --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --swapon --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --traceroute-s --tune2fs --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --wg-show --who --x509-cert --x509-crl --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status)
jc_options=(--force-color -C --debug -d --monochrome -m --meta-out -M --pretty -p --quiet -q --raw -r --slurp -s --unbuffer -u --yaml-out -y)
jc_about_options=(--about -a)
jc_about_mod_options=(--pretty -p --yaml-out -y --monochrome -m --force-color -C)

View File

@@ -9,7 +9,7 @@ _jc() {
jc_help_options jc_help_options_describe \
jc_special_options jc_special_options_describe
jc_commands=(acpi airport amixer apt-cache apt-get arp blkid bluetoothctl cbt certbot chage cksum crontab curl date debconf-show df dig dmidecode dpkg du efibootmgr env ethtool file findmnt finger free git gpg hciconfig host id ifconfig iostat ip ipconfig iptables iw iwconfig jobs last lastb ls lsattr lsb_release lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat needrestart netstat nmcli nsd-control ntpq os-prober pacman pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum swapon sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 tune2fs udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc wg who xrandr zipinfo zpool)
jc_commands=(acpi airport amixer apt-cache apt-get arp blkid bluetoothctl cbt certbot chage cksum crontab curl date debconf-show df dig dmidecode dpkg du efibootmgr env ethtool file findmnt finger free git gpg hciconfig host id ifconfig iostat ip ipconfig iptables iw iwconfig jobs last lastb ls lsattr lsb_release lsblk lsmod lsof lspci lsusb md5 md5sum mdadm mount mpstat needrestart net netstat nmcli nsd-control ntpq os-prober pacman pidstat ping ping6 pip pip3 postconf printenv ps route rpm rsync sfdisk sha1sum sha224sum sha256sum sha384sum sha512sum shasum ss ssh sshd stat sum swapon sysctl systemctl systeminfo timedatectl top tracepath tracepath6 traceroute traceroute6 tune2fs udevadm ufw uname update-alternatives upower uptime vdir veracrypt vmstat w wc wg who xrandr yay zipinfo zpool)
jc_commands_describe=(
'acpi:run "acpi" command with magic syntax.'
'airport:run "airport" command with magic syntax.'
@@ -68,6 +68,7 @@ _jc() {
'mount:run "mount" command with magic syntax.'
'mpstat:run "mpstat" command with magic syntax.'
'needrestart:run "needrestart" command with magic syntax.'
'net:run "net" command with magic syntax.'
'netstat:run "netstat" command with magic syntax.'
'nmcli:run "nmcli" command with magic syntax.'
'nsd-control:run "nsd-control" command with magic syntax.'
@@ -122,10 +123,11 @@ _jc() {
'wg:run "wg" command with magic syntax.'
'who:run "who" command with magic syntax.'
'xrandr:run "xrandr" command with magic syntax.'
'yay:run "yay" command with magic syntax.'
'zipinfo:run "zipinfo" command with magic syntax.'
'zpool:run "zpool" command with magic syntax.'
)
jc_parsers=(--acpi --airport --airport-s --amixer --apt-cache-show --apt-get-sqq --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --curl-head --date --datetime-iso --debconf-show --df --dig --dir --dmidecode --dpkg-l --du --efibootmgr --email-address --env --ethtool --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --host --hosts --http-headers --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --ipconfig --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --kv-dup --last --ls --ls-s --lsattr --lsb-release --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --needrestart --netstat --nmcli --nsd-control --ntpq --openvpn --os-prober --os-release --pacman --passwd --path --path-list --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --pkg-index-apk --pkg-index-deb --plist --postconf --proc --proc-buddyinfo --proc-cmdline --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --swapon --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --tune2fs --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --wg-show --who --x509-cert --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status)
jc_parsers=(--acpi --airport --airport-s --amixer --apt-cache-show --apt-get-sqq --arp --asciitable --asciitable-m --blkid --bluetoothctl --cbt --cef --cef-s --certbot --chage --cksum --clf --clf-s --crontab --crontab-u --csv --csv-s --curl-head --date --datetime-iso --debconf-show --df --dig --dir --dmidecode --dpkg-l --du --efibootmgr --email-address --env --ethtool --file --find --findmnt --finger --free --fstab --git-log --git-log-s --git-ls-remote --gpg --group --gshadow --hash --hashsum --hciconfig --history --host --hosts --http-headers --id --ifconfig --ini --ini-dup --iostat --iostat-s --ip-address --ipconfig --iptables --ip-route --iw-scan --iwconfig --jar-manifest --jobs --jwt --kv --kv-dup --last --ls --ls-s --lsattr --lsb-release --lsblk --lsmod --lsof --lspci --lsusb --m3u --mdadm --mount --mpstat --mpstat-s --needrestart --netstat --net-localgroup --net-user --nmcli --nsd-control --ntpq --openvpn --os-prober --os-release --pacman --passwd --path --path-list --pci-ids --pgpass --pidstat --pidstat-s --ping --ping-s --pip-list --pip-show --pkg-index-apk --pkg-index-deb --plist --postconf --proc --proc-buddyinfo --proc-cmdline --proc-consoles --proc-cpuinfo --proc-crypto --proc-devices --proc-diskstats --proc-filesystems --proc-interrupts --proc-iomem --proc-ioports --proc-loadavg --proc-locks --proc-meminfo --proc-modules --proc-mtrr --proc-pagetypeinfo --proc-partitions --proc-slabinfo --proc-softirqs --proc-stat --proc-swaps --proc-uptime --proc-version --proc-vmallocinfo --proc-vmstat --proc-zoneinfo --proc-driver-rtc --proc-net-arp --proc-net-dev --proc-net-dev-mcast --proc-net-if-inet6 --proc-net-igmp --proc-net-igmp6 --proc-net-ipv6-route --proc-net-netlink --proc-net-netstat --proc-net-packet --proc-net-protocols --proc-net-route --proc-net-tcp --proc-net-unix --proc-pid-fdinfo --proc-pid-io --proc-pid-maps --proc-pid-mountinfo --proc-pid-numa-maps --proc-pid-smaps --proc-pid-stat --proc-pid-statm --proc-pid-status --ps --resolve-conf --route --route-print --rpm-qi --rsync --rsync-s --semver --sfdisk --shadow --srt --ss --ssh-conf --sshd-conf --stat --stat-s --swapon --sysctl --syslog --syslog-s --syslog-bsd --syslog-bsd-s --systemctl --systemctl-lj --systemctl-ls --systemctl-luf --systeminfo --time --timedatectl --timestamp --toml --top --top-s --tracepath --traceroute --traceroute-s --tune2fs --udevadm --ufw --ufw-appinfo --uname --update-alt-gs --update-alt-q --upower --uptime --url --ver --veracrypt --vmstat --vmstat-s --w --wc --wg-show --who --x509-cert --x509-crl --x509-csr --xml --xrandr --yaml --zipinfo --zpool-iostat --zpool-status)
jc_parsers_describe=(
'--acpi:`acpi` command parser'
'--airport:`airport -I` command parser'
@@ -217,6 +219,8 @@ _jc() {
'--mpstat-s:`mpstat` command streaming parser'
'--needrestart:`needrestart -b` command parser'
'--netstat:`netstat` command parser'
'--net-localgroup:`net localgroup` command parser'
'--net-user:`net user` command parser'
'--nmcli:`nmcli` command parser'
'--nsd-control:`nsd-control` command parser'
'--ntpq:`ntpq -p` command parser'
@@ -294,6 +298,7 @@ _jc() {
'--ps:`ps` command parser'
'--resolve-conf:`/etc/resolve.conf` file parser'
'--route:`route` command parser'
'--route-print:`route print` command parser'
'--rpm-qi:`rpm -qi` command parser'
'--rsync:`rsync` command parser'
'--rsync-s:`rsync` command streaming parser'
@@ -325,6 +330,7 @@ _jc() {
'--top-s:`top -b` command streaming parser'
'--tracepath:`tracepath` and `tracepath6` command parser'
'--traceroute:`traceroute` and `traceroute6` command parser'
'--traceroute-s:`traceroute` and `traceroute6` command streaming parser'
'--tune2fs:`tune2fs -l` command parser'
'--udevadm:`udevadm info` command parser'
'--ufw:`ufw status` command parser'
@@ -344,6 +350,7 @@ _jc() {
'--wg-show:`wg show` command parser'
'--who:`who` command parser'
'--x509-cert:X.509 PEM and DER certificate file parser'
'--x509-crl:X.509 PEM and DER certificate revocation list file parser'
'--x509-csr:X.509 PEM and DER certificate request file parser'
'--xml:XML file parser'
'--xrandr:`xrandr` command parser'

View File

@@ -36,7 +36,7 @@ returned.
Parameters:
documentation: (boolean) include parser docstrings if True
documentation: (boolean) include parser docstrings if `True`
show_hidden: (boolean) also show parsers marked as hidden
in their info metadata.
show_deprecated: (boolean) also show parsers marked as
@@ -172,17 +172,17 @@ Parameters:
variants of the module name.
A Module object can also be passed
directly or via get_parser()
directly or via `get_parser()`
data: (string or data to parse (string or bytes for
bytes or standard parsers, iterable of
iterable) strings for streaming parsers)
raw: (boolean) output preprocessed JSON if True
raw: (boolean) output preprocessed JSON if `True`
quiet: (boolean) suppress warning messages if True
quiet: (boolean) suppress warning messages if `True`
ignore_exceptions: (boolean) ignore parsing exceptions if True
ignore_exceptions: (boolean) ignore parsing exceptions if `True`
(streaming parsers only)
Returns:
@@ -209,7 +209,7 @@ Parameters:
variants of the module name as well
as a parser module object.
documentation: (boolean) include parser docstring if True
documentation: (boolean) include parser docstring if `True`
<a id="jc.lib.parser_mod_list"></a>

View File

@@ -69,6 +69,7 @@ a controller and a device but there might be fields corresponding to one entity.
"blocked": string,
"connected": string,
"legacy_pairing": string,
"cable_pairing": string,
"rssi": int,
"txpower": int,
"uuids": array,
@@ -136,4 +137,4 @@ Compatibility: linux
Source: [`jc/parsers/bluetoothctl.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/bluetoothctl.py)
Version 1.4 by Jake Ob (iakopap at gmail.com)
Version 1.5 by Jake Ob (iakopap at gmail.com)

View File

@@ -0,0 +1,81 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.net_localgroup"></a>
# jc.parsers.net_localgroup
jc - JSON Convert `net localgroup` command output parser
Usage (cli):
$ net localgroup | jc --net-localgroup
$ net localgroup /domain | jc --net-localgroup
$ net localgroup Administrators | jc --net-localgroup
$ net localgroup Administrators /domain | jc --net-localgroup
Usage (module):
import jc
result = jc.parse('net_localgroup', net_localgroup_command_output)
Schema:
{
"account_origin": string,
"domain": string,
"comment": string,
"groups": [
{
"name": string
"members": [
string
]
}
],
}
Examples:
$ net localgroup | jc --net-localgroup -p
{
"account_origin": null,
"comment": null,
"domain": null,
"groups": [
{
"name": "Administrators",
"members": [
"Administrator",
"Operator",
"ansible",
"user1"
]
}
]
}
<a id="jc.parsers.net_localgroup.parse"></a>
### parse
```python
def parse(data, raw=False, quiet=False)
```
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:
Parsed dictionary. The raw and processed data structures are the same.
### Parser Information
Compatibility: win32
Source: [`jc/parsers/net_localgroup.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/net_localgroup.py)
Version 1.0 by joehacksalot (joehacksalot@gmail.com)

212
docs/parsers/net_user.md Normal file
View File

@@ -0,0 +1,212 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.net_user"></a>
# jc.parsers.net_user
jc - JSON Convert `net user` command output parser
Usage (cli):
$ net users | jc --net-user
$ net users /domain | jc --net-user
$ net users User1 | jc --net-user
$ net users User1 /domain | jc --net-user
Usage (module):
import jc
result = jc.parse('net_user', net_user_command_output)
Schema:
{
"domain": string,
"account_origin": string,
"user_accounts": [
{
"user_name": string,
"full_name": string,
"comment": string,
"user_comment": string,
"country_region_code": string,
"account_active": boolean,
"account_expires": string,
"password_last_set": string,
"password_expires": string,
"password_changeable": string,
"password_required": boolean,
"user_may_change_password": boolean,
"workstations_allowed": string,
"logon_script": string,
"user_profile": string,
"home_directory": string,
"last_logon": string,
"logon_hours_allowed": string,
"local_group_memberships": [
string,
],
"global_group_memberships": [
string,
]
}
]
}
Examples:
$ net users | jc --net-user -p
{
"account_origin": "\\\\WIN-SERVER16",
"domain": "",
"user_accounts": [
{
"user_name": "Administrator"
},
{
"user_name": "DefaultAccount"
},
{
"user_name": "Guest"
},
{
"user_name": "pentera_BnlLQVnd7p"
},
{
"user_name": "user1"
}
]
}
$ net users /domain | jc --net-user -p
{
"account_origin": "\\\\DESKTOP-WIN10-PRO.somecompany.corp",
"domain": "somecompany.corp",
"user_accounts": [
{
"user_name": "aaron"
},
{
"user_name": "addison"
},
{
"user_name": "Administrator"
},
{
"user_name": "ansible"
},
{
"user_name": "da"
},
{
"user_name": "DefaultAccount"
},
{
"user_name": "Guest"
},
{
"user_name": "harrison"
},
{
"user_name": "james"
},
{
"user_name": "krbtgt"
},
{
"user_name": "liam"
},
{
"user_name": "localadmin"
},
{
"user_name": "tiffany"
}
]
}
$ net users Administrator | jc --net-user -p
{
"domain": "",
"user_accounts": [
{
"account_active": true,
"account_expires": "Never",
"comment": "Built-in account for administering the computer/domain",
"country_region_code": "000 (System Default)",
"global_group_memberships": [],
"last_logon": "2024-08-23T13:47:11",
"local_group_memberships": [
"Administrators"
],
"logon_hours_allowed": "All",
"password_changeable": "2021-12-17T11:07:14",
"password_expires": "2022-01-27T11:07:14",
"password_last_set": "2021-12-16T11:07:14",
"password_required": true,
"user_may_change_password": true,
"user_name": "Administrators",
"workstations_allowed": "All"
}
]
}
$ net users Administrator /domain | jc --net-user -p | jq
{
"domain": "somecompany.corp",
"user_accounts": [
{
"account_active": true,
"account_expires": "Never",
"comment": "Built-in account for administering the computer/domain",
"country_region_code": "000 (System Default)",
"global_group_memberships": [
"Domain Admins",
"Domain Users",
"Group Policy Creator",
"Enterprise Admins",
"Schema Admins"
],
"last_logon": "2024-07-17T13:46:12",
"local_group_memberships": [
"Administrators"
],
"logon_hours_allowed": "All",
"password_changeable": "2023-09-30T11:44:26",
"password_expires": "Never",
"password_last_set": "2023-09-29T11:44:26",
"password_required": true,
"user_may_change_password": true,
"user_name": "Administrators",
"workstations_allowed": "All"
}
]
}
<a id="jc.parsers.net_user.parse"></a>
### parse
```python
def parse(data, raw=False, quiet=False)
```
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:
Parsed dictionary. The raw and processed data structures are the same.
### Parser Information
Compatibility: win32
Source: [`jc/parsers/net_user.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/net_user.py)
Version 1.0 by joehacksalot (joehacksalot@gmail.com)

View File

@@ -41,7 +41,8 @@ These are documented below.
[
{
"<key>": string/integer/float, # [0]
"team_config": object,
"team_config": object/null,
"team_port_config": object/null,
"dhcp4_option_x": {
"name": string,
"value": string/integer/float,
@@ -171,4 +172,4 @@ Compatibility: linux
Source: [`jc/parsers/nmcli.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/nmcli.py)
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -205,4 +205,4 @@ Compatibility: linux, darwin, cygwin, win32, aix, freebsd
Source: [`jc/parsers/pacman.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/pacman.py)
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.1 by Kelly Brazil (kellyjonbrazil@gmail.com)

204
docs/parsers/route_print.md Normal file
View File

@@ -0,0 +1,204 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.route_print"></a>
# jc.parsers.route_print
jc - JSON Convert `route print` command output parser
See also: the `route` command parser
Usage (cli):
$ route print | jc --route-print
Usage (module):
import jc
result = jc.parse('route_print', route_print_command_output)
Schema:
{
"interface_list": [
{
"interface_index": integer,
"mac_address": string,
"description": string
}
],
"ipv4_route_table": {
"active_routes": [
{
"network_destination": string,
"netmask": string,
"gateway": string,
"interface": string,
"metric": integer, # [0]
"metric_set_to_default": boolean # [1]
}
],
"persistent_routes": [
{
"network_address": string,
"netmask": string,
"gateway_address": string,
"metric": integer # [0]
"metric_set_to_default": boolean # [1]
}
]
},
"ipv6_route_table": {
"active_routes": [
{
"interface": integer,
"metric": integer, # [0]
"metric_set_to_default": boolean, # [1]
"network_destination": string,
"gateway": string
}
],
"persistent_routes": [
{
"interface": integer,
"metric": integer, # [0]
"metric_set_to_default": boolean, # [1]
"network_destination": string,
"gateway": string
}
]
}
}
[0] Null/None if "metric" = "Default"
[1] True if "metric" = "Default"
Examples:
$ route print | jc --route-print -p
{
"interface_list": [
{
"interface_index": 28,
"mac_address": null,
"description": "Tailscale Tunnel"
},
{
"interface_index": 12,
"mac_address": "00:1c:42:da:01:6a",
"description": "Parallels VirtIO Ethernet Adapter"
},
{
"interface_index": 1,
"mac_address": null,
"description": "Software Loopback Interface 1"
}
],
"ipv4_route_table": {
"active_routes": [
{
"network_destination": "0.0.0.0",
"netmask": "0.0.0.0",
"gateway": "10.211.55.1",
"interface": "10.211.55.3",
"metric": 15,
"metric_set_to_default": false
},
{
"network_destination": "10.0.0.0",
"netmask": "255.0.0.0",
"gateway": "192.168.22.1",
"interface": "10.211.55.3",
"metric": 16,
"metric_set_to_default": false
},
...
{
"network_destination": "255.255.255.255",
"netmask": "255.255.255.255",
"gateway": "On-link",
"interface": "10.211.55.3",
"metric": null,
"metric_set_to_default": true
}
],
"persistent_routes": [
{
"network_address": "10.0.1.0",
"netmask": "255.255.255.0",
"gateway_address": "192.168.22.1",
"metric": 1,
"metric_set_to_default": false
},
{
"network_address": "10.0.3.0",
"netmask": "255.255.255.0",
"gateway_address": "192.168.22.1",
"metric": 1,
"metric_set_to_default": false
},
...
]
},
"ipv6_route_table": {
"active_routes": [
{
"interface": 1,
"metric": 331,
"network_destination": "::1/128",
"gateway": "On-link",
"metric_set_to_default": false
},
{
"interface": 12,
"metric": 271,
"network_destination": "2001:db8::/64",
"gateway": "fe80::1",
"metric_set_to_default": false
},
...
{
"interface": 12,
"metric": 271,
"network_destination": "ff00::/8",
"gateway": "On-link",
"metric_set_to_default": false
}
],
"persistent_routes": [
{
"interface": 0,
"metric": 4294967295,
"network_destination": "2001:db8::/64",
"gateway": "fe80::1",
"metric_set_to_default": false
}
]
}
}
<a id="jc.parsers.route_print.parse"></a>
### parse
```python
def parse(data, raw=False, quiet=False)
```
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:
Parsed dictionary. The raw and processed data structures are the same.
### Parser Information
Compatibility: win32
Source: [`jc/parsers/route_print.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/route_print.py)
Version 1.0 by joehacksalot (joehacksalot@gmail.com)

View File

@@ -50,23 +50,31 @@ All `-` values are converted to `null`
"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]
"mem_unit": string,
"mem_total": float,
"mem_free": float,
"mem_used": float,
"mem_buff_cache": float,
"swap_unit": string,
"swap_total": float,
"swap_free": float,
"swap_used": float,
"mem_available": float,
"processes": [
{
"pid": integer,
"user": string,
"priority": integer,
"nice": integer,
"virtual_mem": float, # [1]
"resident_mem": float, # [1]
"shared_mem": float, # [1]
"virtual_mem": float,
"virtual_mem_bytes": integer,
"virtual_mem_unit": string,
"resident_mem": float,
"resident_mem_bytes": integer,
"resident_mem_unit": string,
"shared_mem": float,
"shared_mem_bytes": integer,
"shared_mem_unit": string,
"status": string,
"percent_cpu": float,
"percent_mem": float,
@@ -87,9 +95,15 @@ All `-` values are converted to `null`
"thread_count": integer,
"last_used_processor": integer,
"time": string,
"swap": float, # [1]
"code": float, # [1]
"data": float, # [1]
"swap": float,
"swap_bytes": integer,
"swap_unit": string,
"code": float,
"code_bytes": integer,
"code_unit": string,
"data": float,
"data_bytes": integer,
"data_unit": string,
"major_page_fault_count": integer,
"minor_page_fault_count": integer,
"dirty_pages_count": integer,
@@ -108,7 +122,9 @@ All `-` values are converted to `null`
]
"major_page_fault_count_delta": integer,
"minor_page_fault_count_delta": integer,
"used": float, # [1]
"used": float,
"used_bytes": integer,
"used_unit": string,
"ipc_namespace_inode": integer,
"mount_namespace_inode": integer,
"net_namespace_inode": integer,
@@ -129,9 +145,6 @@ All `-` values are converted to `null`
}
]
[0] Values are in the units output by `top`
[1] Unit suffix stripped during float conversion
Examples:
$ top -b -n 3 | jc --top -p
@@ -338,4 +351,4 @@ Compatibility: linux
Source: [`jc/parsers/top.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/top.py)
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -48,23 +48,39 @@ Schema:
"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]
"mem_unit": string,
"swap_unit": string,
"mem_total": float,
"mem_total_bytes": integer,
"mem_free": float,
"mem_free_bytes": integer,
"mem_used": float,
"mem_used_bytes": integer,
"mem_buff_cache": float,
"mem_buff_cache_bytes": integer,
"swap_total": float,
"swap_total_bytes": integer,
"swap_free": float,
"swap_free_bytes": integer,
"swap_used": float,
"swap_used_bytes": integer,
"mem_available": float,
"mem_available_bytes": integer,
"processes": [
{
"pid": integer,
"user": string,
"priority": integer,
"nice": integer,
"virtual_mem": float, # [1]
"resident_mem": float, # [1]
"shared_mem": float, # [1]
"virtual_mem": float,
"virtual_mem_unit": string,
"virtual_mem_bytes": integer,
"resident_mem": float,
"resident_mem_unit": string,
"resident_mem_bytes": integer,
"shared_mem": float,
"shared_mem_unit": string,
"shared_mem_bytes": integer,
"status": string,
"percent_cpu": float,
"percent_mem": float,
@@ -85,9 +101,15 @@ Schema:
"thread_count": integer,
"last_used_processor": integer,
"time": string,
"swap": float, # [1]
"code": float, # [1]
"data": float, # [1]
"swap": float,
"swap_unit": string,
"swap_bytes": integer,
"code": float,
"code_unit": string,
"code_bytes": integer
"data": float,
"data_unit": string,
"data_bytes": integer,
"major_page_fault_count": integer,
"minor_page_fault_count": integer,
"dirty_pages_count": integer,
@@ -106,7 +128,9 @@ Schema:
]
"major_page_fault_count_delta": integer,
"minor_page_fault_count_delta": integer,
"used": float, # [1]
"used": float,
"used_unit": string,
"used_bytes": integer,
"ipc_namespace_inode": integer,
"mount_namespace_inode": integer,
"net_namespace_inode": integer,
@@ -133,9 +157,6 @@ Schema:
}
}
[0] Values are in the units output by `top`
[1] Unit suffix stripped during float conversion
Examples:
$ top -b | jc --top-s
@@ -178,4 +199,4 @@ Compatibility: linux
Source: [`jc/parsers/top_s.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/top_s.py)
Version 1.2 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.3 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -32,6 +32,8 @@ Schema:
{
"destination_ip": string,
"destination_name": string,
"max_hops": integer,
"data_bytes": integer,
"hops": [
{
"hop": integer,
@@ -54,6 +56,8 @@ Examples:
{
"destination_ip": "216.58.194.46",
"destination_name": "google.com",
"max_hops": 64,
"data_bytes": 50,
"hops": [
{
"hop": 1,
@@ -89,6 +93,8 @@ Examples:
{
"destination_ip": "216.58.194.46",
"destination_name": "google.com",
"max_hops": "64",
"data_bytes": "50",
"hops": [
{
"hop": "1",
@@ -145,4 +151,4 @@ Compatibility: linux, darwin, freebsd
Source: [`jc/parsers/traceroute.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/traceroute.py)
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -0,0 +1,167 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.traceroute_s"></a>
# jc.parsers.traceroute_s
jc - JSON Convert `traceroute` command output streaming parser
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
> Dictionaries (module)
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-s`
Usage (cli):
$ traceroute 1.2.3.4 | jc --traceroute-s
Usage (module):
import jc
result = jc.parse('traceroute_s', traceroute_command_output.splitlines())
for item in result:
# do something
Schema:
{
# 'header' or 'hop'
"type": string,
# 'header' type has the fields below:
"destination_ip": string,
"destination_name": string,
"max_hops": integer,
"data_bytes": integer,
# 'hop' type has the fields below:
"hop": integer,
"probes": [
{
"annotation": string,
"asn": integer,
"ip": string,
"name": string,
"rtt": float
}
]
# 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
}
}
Examples:
$ traceroute google.com | jc --traceroute-s -p
{
"type": "header",
"destination_ip": "216.58.194.46",
"destination_name": "google.com",
"max_hops": 30,
"data_bytes": 60
}
{
"type": "hop",
"hop": 1,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": 198.574
},
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": null
},
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": 198.65
}
]
}
...
$ traceroute google.com | jc --traceroute-s -p -r
{
"type": "header",
"destination_ip": "216.58.194.46",
"destination_name": "google.com",
"max_hops": "30",
"data_bytes": "60"
}
{
"type": "hop",
"hop": "1",
"probes": [
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": "198.574"
},
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": null
},
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": "198.650"
}
]
}
...
<a id="jc.parsers.traceroute_s.parse"></a>
### parse
```python
def parse(data, raw=False, quiet=False, ignore_exceptions=False)
```
Main text parsing 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, freebsd
Source: [`jc/parsers/traceroute_s.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/traceroute_s.py)
Version 1.0 by Shintaro Kojima (goodies@codeout.net)

View File

@@ -30,6 +30,7 @@ Schema:
"user": string,
"event": string,
"writeable_tty": string,
"process": string,
"tty": string,
"time": string,
"epoch": integer, # [0]
@@ -160,4 +161,4 @@ Compatibility: linux, darwin, cygwin, aix, freebsd
Source: [`jc/parsers/who.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/who.py)
Version 1.8 by Kelly Brazil (kellyjonbrazil@gmail.com)
Version 1.9 by Kelly Brazil (kellyjonbrazil@gmail.com)

304
docs/parsers/x509_crl.md Normal file
View File

@@ -0,0 +1,304 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.x509_crl"></a>
# jc.parsers.x509_crl
jc - JSON Convert X.509 Certificate Revocation List format file parser
This parser will convert DER and PEM encoded X.509 certificate revocation
list files.
Usage (cli):
$ cat certificateRevocationList.pem | jc --x509-crl
$ cat certificateRevocationList.der | jc --x509-crl
Usage (module):
import jc
result = jc.parse('x509_crl', x509_crl_file_output)
Schema:
{
"tbs_cert_list": {
"version": string,
"signature": {
"algorithm": string,
"parameters": string/null
},
"issuer": {
"organization_name": string,
"organizational_unit_name": string,
"common_name": string
},
"this_update": integer, # [1]
"next_update": integer, # [1]
"revoked_certificates": [
{
"user_certificate": integer,
"revocation_date": integer, # [1]
"crl_entry_extensions": [
{
"extn_id": string,
"critical": boolean,
"extn_value": string,
"extn_value_iso": string
},
"revocation_date_iso": string
}
],
"crl_extensions": [
{
"extn_id": string,
"critical": boolean,
"extn_value": array/object/string/integer # [2]
}
],
"this_update_iso": string,
"next_update_iso": string
},
"signature_algorithm": {
"algorithm": string,
"parameters": string/null
},
"signature": string # [0]
}
[0] in colon-delimited hex notation
[1] time-zone-aware (UTC) epoch timestamp
[2] See below for well-known Extension schemas:
Basic Constraints:
{
"extn_id": "basic_constraints",
"critical": boolean,
"extn_value": {
"ca": boolean,
"path_len_constraint": string/null
}
}
Key Usage:
{
"extn_id": "key_usage",
"critical": boolean,
"extn_value": [
string
]
}
Key Identifier:
{
"extn_id": "key_identifier",
"critical": boolean,
"extn_value": string # [0]
}
Authority Key Identifier:
{
"extn_id": "authority_key_identifier",
"critical": boolean,
"extn_value": {
"key_identifier": string, # [0]
"authority_cert_issuer": string/null,
"authority_cert_serial_number": string/null
}
}
Subject Alternative Name:
{
"extn_id": "subject_alt_name",
"critical": boolean,
"extn_value": [
string
]
}
Certificate Policies:
{
"extn_id": "certificate_policies",
"critical": boolean,
"extn_value": [
{
"policy_identifier": string,
"policy_qualifiers": [ array or null
{
"policy_qualifier_id": string,
"qualifier": string
}
]
}
]
}
Signed Certificate Timestamp List:
{
"extn_id": "signed_certificate_timestamp_list",
"critical": boolean,
"extn_value": string # [0]
}
Examples:
$ cat sample-crl.pem | jc --x509-crl -p
{
"tbs_cert_list": {
"version": "v2",
"signature": {
"algorithm": "sha1_rsa",
"parameters": null
},
"issuer": {
"organization_name": "Sample Signer Organization",
"organizational_unit_name": "Sample Signer Unit",
"common_name": "Sample Signer Cert"
},
"this_update": 1361183520,
"next_update": 1361184120,
"revoked_certificates": [
{
"user_certificate": 1341767,
"revocation_date": 1361182932,
"crl_entry_extensions": [
{
"extn_id": "crl_reason",
"critical": false,
"extn_value": "affiliation_changed"
},
{
"extn_id": "invalidity_date",
"critical": false,
"extn_value": 1361182920,
"extn_value_iso": "2013-02-18T10:22:00+00:00"
}
],
"revocation_date_iso": "2013-02-18T10:22:12+00:00"
},
{
"user_certificate": 1341768,
"revocation_date": 1361182942,
"crl_entry_extensions": [
{
"extn_id": "crl_reason",
"critical": false,
"extn_value": "certificate_hold"
},
{
"extn_id": "invalidity_date",
"critical": false,
"extn_value": 1361182920,
"extn_value_iso": "2013-02-18T10:22:00+00:00"
}
],
"revocation_date_iso": "2013-02-18T10:22:22+00:00"
},
{
"user_certificate": 1341769,
"revocation_date": 1361182952,
"crl_entry_extensions": [
{
"extn_id": "crl_reason",
"critical": false,
"extn_value": "superseded"
},
{
"extn_id": "invalidity_date",
"critical": false,
"extn_value": 1361182920,
"extn_value_iso": "2013-02-18T10:22:00+00:00"
}
],
"revocation_date_iso": "2013-02-18T10:22:32+00:00"
},
{
"user_certificate": 1341770,
"revocation_date": 1361182962,
"crl_entry_extensions": [
{
"extn_id": "crl_reason",
"critical": false,
"extn_value": "key_compromise"
},
{
"extn_id": "invalidity_date",
"critical": false,
"extn_value": 1361182920,
"extn_value_iso": "2013-02-18T10:22:00+00:00"
}
],
"revocation_date_iso": "2013-02-18T10:22:42+00:00"
},
{
"user_certificate": 1341771,
"revocation_date": 1361182971,
"crl_entry_extensions": [
{
"extn_id": "crl_reason",
"critical": false,
"extn_value": "cessation_of_operation"
},
{
"extn_id": "invalidity_date",
"critical": false,
"extn_value": 1361182920,
"extn_value_iso": "2013-02-18T10:22:00+00:00"
}
],
"revocation_date_iso": "2013-02-18T10:22:51+00:00"
}
],
"crl_extensions": [
{
"extn_id": "authority_key_identifier",
"critical": false,
"extn_value": {
"key_identifier": "be:12:01:cc:aa:ea:11:80:da:2e:ad:b2...",
"authority_cert_issuer": null,
"authority_cert_serial_number": null
}
},
{
"extn_id": "crl_number",
"critical": false,
"extn_value": 3
}
],
"this_update_iso": "2013-02-18T10:32:00+00:00",
"next_update_iso": "2013-02-18T10:42:00+00:00"
},
"signature_algorithm": {
"algorithm": "sha1_rsa",
"parameters": null
},
"signature": "42:21:be:81:f1:c3:79:76:66:5b:ce:21:13:8a:68:a..."
}
<a id="jc.parsers.x509_crl.parse"></a>
### parse
```python
def parse(data: Union[str, bytes],
raw: bool = False,
quiet: bool = False) -> Dict
```
Main text parsing function
Parameters:
data: (string or bytes) text or binary 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, darwin, cygwin, win32, aix, freebsd
Source: [`jc/parsers/x509_crl.py`](https://github.com/kellyjonbrazil/jc/blob/master/jc/parsers/x509_crl.py)
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@@ -23,8 +23,9 @@ jc - JSON Convert streaming utils
def add_jc_meta(func: ~F) -> ~F
```
Decorator for streaming parsers to add stream_success and stream_error
objects. This simplifies the yield lines in the streaming parsers.
Decorator for streaming parsers to add `stream_success` and
`stream_error` objects. This simplifies the `yield` lines in the
streaming parsers.
With the decorator on parse():
@@ -58,7 +59,7 @@ In all cases above:
successfully parse.
ignore_exceptions: (bool) continue processing lines and ignore
exceptions if True.
exceptions if `True`.
<a id="jc.streaming.raise_or_yield"></a>
@@ -69,8 +70,8 @@ def raise_or_yield(ignore_exceptions: bool, e: BaseException,
line: str) -> Tuple[BaseException, str]
```
Return the exception object and line string if ignore_exceptions is
True. Otherwise, re-raise the exception from the exception object with
Return the exception object and line string if `ignore_exceptions` is
`True`. Otherwise, re-raise the exception from the exception object with
an annotation.
<a id="jc.streaming.stream_error"></a>

View File

@@ -44,7 +44,7 @@ Parameters:
the parser. compatible options:
linux, darwin, cygwin, win32, aix, freebsd
quiet: (bool) suppress compatibility message if True
quiet: (bool) suppress compatibility message if `True`
Returns:
@@ -181,7 +181,7 @@ Parameters:
Returns:
None - just prints output to STDERR
None - just prints output to `STDERR`
<a id="jc.utils.has_data"></a>
@@ -194,7 +194,7 @@ def has_data(data: Union[str, bytes]) -> bool
Checks if the string input contains data. If there are any
non-whitespace characters then return `True`, else return `False`.
For bytes, returns True if there is any data.
For bytes, returns `True` if there is any data.
Parameters:
@@ -202,9 +202,9 @@ Parameters:
Returns:
Boolean True if input string (data) contains non-whitespace
characters, otherwise False. For bytes data, returns
True if there is any data, otherwise False.
Boolean `True` if input string (data) contains non-whitespace
characters, otherwise `False`. For bytes data, returns
`True` if there is any data, otherwise `False`.
<a id="jc.utils.input_type_check"></a>

View File

@@ -300,8 +300,8 @@ class JcCli():
Pages the parser documentation if a parser is found in the arguments,
otherwise the general help text is printed.
"""
self.indent = 4
self.pad = 22
self.indent = 2
self.pad = 21
if self.show_categories:
utils._safe_print(self.parser_categories_text())
@@ -569,7 +569,11 @@ class JcCli():
if self.debug:
raise
error_msg = os.strerror(e.errno)
if e.errno:
error_msg = os.strerror(e.errno)
else:
error_msg = "no further information provided"
utils.error_message([
f'"{file}" file could not be opened: {error_msg}.'
])
@@ -594,7 +598,11 @@ class JcCli():
if self.debug:
raise
error_msg = os.strerror(e.errno)
if e.errno:
error_msg = os.strerror(e.errno)
else:
error_msg = "no further information provided"
utils.error_message([
f'"{self.magic_run_command_str}" command could not be run: {error_msg}.'
])

View File

@@ -62,52 +62,52 @@ jc converts the output of many commands, file-types, and strings to JSON or YAML
Usage:
Standard syntax:
Standard syntax:
COMMAND | jc [SLICE] [OPTIONS] PARSER
COMMAND | jc [SLICE] [OPTIONS] PARSER
cat FILE | jc [SLICE] [OPTIONS] PARSER
cat FILE | jc [SLICE] [OPTIONS] PARSER
echo STRING | jc [SLICE] [OPTIONS] PARSER
echo STRING | jc [SLICE] [OPTIONS] PARSER
Magic syntax:
Magic syntax:
jc [SLICE] [OPTIONS] COMMAND
jc [SLICE] [OPTIONS] COMMAND
jc [SLICE] [OPTIONS] /proc/<path-to-procfile>
jc [SLICE] [OPTIONS] /proc/<path-to-procfile>
Parsers:
'''
slicetext_string: str = '''\
Slice:
[start]:[end]
[start]:[end]
start: [[-]index] - Zero-based start line, negative index for
counting from the end
start: [[-]index] - Zero-based start line, negative index for
counting from the end
end: [[-]index] - Zero-based end line (excluding the index),
negative index for counting from the end
end: [[-]index] - Zero-based end line (excluding the index),
negative index for counting from the end
'''
helptext_end_string: str = '''\
Examples:
Standard Syntax:
$ dig www.google.com | jc --pretty --dig
$ cat /proc/meminfo | jc --pretty --proc
Standard Syntax:
$ dig www.google.com | jc --pretty --dig
$ cat /proc/meminfo | jc --pretty --proc
Magic Syntax:
$ jc --pretty dig www.google.com
$ jc --pretty /proc/meminfo
Magic Syntax:
$ jc --pretty dig www.google.com
$ jc --pretty /proc/meminfo
Line Slicing:
$ cat output.txt | jc 4:15 --parser # Parse from line 4 to 14
with parser (zero-based)
Line Slicing:
$ cat output.txt | jc 4:15 --<PARSER> # Parse from line 4 to 14
# with <PARSER> (zero-based)
Parser Documentation:
$ jc --help --dig
Parser Documentation:
$ jc --help --dig
More Help:
$ jc -hh # show hidden parsers
$ jc -hhh # list parsers by category tags
More Help:
$ jc -hh # show hidden parsers
$ jc -hhh # list parsers by category tags
'''

View File

@@ -10,7 +10,7 @@ from jc import appdirs
from jc import utils
__version__ = '1.25.5'
__version__ = '1.25.7'
parsers: List[str] = [
'acpi',
@@ -103,6 +103,8 @@ parsers: List[str] = [
'mpstat-s',
'needrestart',
'netstat',
'net-localgroup',
'net-user',
'nmcli',
'nsd-control',
'ntpq',
@@ -180,6 +182,7 @@ parsers: List[str] = [
'ps',
'resolve-conf',
'route',
'route-print',
'rpm-qi',
'rsync',
'rsync-s',
@@ -211,7 +214,9 @@ parsers: List[str] = [
'top-s',
'tracepath',
'traceroute',
'traceroute-s',
'tune2fs',
'typeset',
'udevadm',
'ufw',
'ufw-appinfo',
@@ -230,6 +235,7 @@ parsers: List[str] = [
'wg-show',
'who',
'x509-cert',
'x509-crl',
'x509-csr',
'xml',
'xrandr',
@@ -346,7 +352,8 @@ def _get_parser(parser_mod_name: str) -> ModuleType:
def _parser_is_slurpable(parser: ModuleType) -> bool:
"""
Returns True if this parser can use the `--slurp` command option, else False
Returns `True` if this parser can use the `--slurp` command option, else
`False`
parser is a parser module object.
"""
@@ -358,7 +365,7 @@ def _parser_is_slurpable(parser: ModuleType) -> bool:
def _parser_is_streaming(parser: ModuleType) -> bool:
"""
Returns True if this is a streaming parser, else False
Returns `True` if this is a streaming parser, else `False`
parser is a parser module object.
"""
@@ -369,7 +376,7 @@ def _parser_is_streaming(parser: ModuleType) -> bool:
def _parser_is_hidden(parser: ModuleType) -> bool:
"""
Returns True if this is a hidden parser, else False
Returns `True` if this is a hidden parser, else `False`
parser is a parser module object.
"""
@@ -380,7 +387,7 @@ def _parser_is_hidden(parser: ModuleType) -> bool:
def _parser_is_deprecated(parser: ModuleType) -> bool:
"""
Returns True if this is a deprecated parser, else False
Returns `True` if this is a deprecated parser, else `False`
parser is a parser module object.
"""
@@ -467,17 +474,17 @@ def parse(
variants of the module name.
A Module object can also be passed
directly or via get_parser()
directly or via `get_parser()`
data: (string or data to parse (string or bytes for
bytes or standard parsers, iterable of
iterable) strings for streaming parsers)
raw: (boolean) output preprocessed JSON if True
raw: (boolean) output preprocessed JSON if `True`
quiet: (boolean) suppress warning messages if True
quiet: (boolean) suppress warning messages if `True`
ignore_exceptions: (boolean) ignore parsing exceptions if True
ignore_exceptions: (boolean) ignore parsing exceptions if `True`
(streaming parsers only)
Returns:
@@ -627,7 +634,7 @@ def parser_info(
variants of the module name as well
as a parser module object.
documentation: (boolean) include parser docstring if True
documentation: (boolean) include parser docstring if `True`
"""
parser_mod = get_parser(parser_mod_name)
parser_mod_name = parser_mod.__name__.split('.')[-1]
@@ -664,7 +671,7 @@ def all_parser_info(
Parameters:
documentation: (boolean) include parser docstrings if True
documentation: (boolean) include parser docstrings if `True`
show_hidden: (boolean) also show parsers marked as hidden
in their info metadata.
show_deprecated: (boolean) also show parsers marked as

View File

@@ -64,6 +64,7 @@ a controller and a device but there might be fields corresponding to one entity.
"blocked": string,
"connected": string,
"legacy_pairing": string,
"cable_pairing": string,
"rssi": int,
"txpower": int,
"uuids": array,
@@ -112,7 +113,7 @@ import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.4'
version = '1.5'
description = '`bluetoothctl` command parser'
author = 'Jake Ob'
author_email = 'iakopap at gmail.com'
@@ -165,6 +166,7 @@ try:
"blocked": str,
"connected": str,
"legacy_pairing": str,
"cable_pairing": str,
"rssi": int,
"txpower": int,
"uuids": List[str],
@@ -302,6 +304,7 @@ _device_line_pattern = (
+ r"|\s*TxPower:\s*(?P<txpower>.+)"
+ r"|\s*Battery\sPercentage:\s*0[xX][0-9a-fA-F]*\s*\((?P<battery_percentage>[0-9]+)\)"
+ r"|\s*UUID:\s*(?P<uuid>.+))"
+ r"|\s*CablePairing:\s*(?P<cable_pairing>.+)"
)
@@ -335,6 +338,7 @@ def _parse_device(next_lines: List[str], quiet: bool) -> Optional[Device]:
"blocked": '',
"connected": '',
"legacy_pairing": '',
"cable_pairing": '',
"rssi": 0,
"txpower": 0,
"uuids": [],
@@ -383,6 +387,8 @@ def _parse_device(next_lines: List[str], quiet: bool) -> Optional[Device]:
device["connected"] = matches["connected"]
elif matches["legacy_pairing"]:
device["legacy_pairing"] = matches["legacy_pairing"]
elif matches["cable_pairing"]:
device["cable_pairing"] = matches["cable_pairing"]
elif matches["rssi"]:
rssi = matches["rssi"]
try:

View File

@@ -121,7 +121,7 @@ import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.6'
version = '1.7'
description = '`dir` command parser'
author = 'Rasheed Elsaleh'
author_email = 'rasheed@rebelliondefense.com'
@@ -183,8 +183,8 @@ def parse(data, raw=False, quiet=False):
if jc.utils.has_data(data):
for line in data.splitlines():
if line.startswith(" Directory of"):
parent_dir = line.lstrip(" Directory of ")
if line.startswith(" Directory of "):
parent_dir = line[len(" Directory of "):]
continue
# skip lines that don't start with a date
if not re.match(r'^\d{2}/\d{2}/\d{4}', line):

View File

@@ -28,6 +28,7 @@ Schema:
[
{
"filename": string,
"mode": string,
"hash": string,
}
]
@@ -38,37 +39,44 @@ Examples:
[
{
"filename": "devtoolset-3-gcc-4.9.2-6.el7.x86_64.rpm",
"mode": "text",
"hash": "65fc958c1add637ec23c4b137aecf3d3"
},
{
"filename": "digout",
"mode": "text",
"hash": "5b9312ee5aff080927753c63a347707d"
},
{
"filename": "dmidecode.out",
"mode": "text",
"hash": "716fd11c2ac00db109281f7110b8fb9d"
},
{
"filename": "file with spaces in the name",
"mode": "text",
"hash": "d41d8cd98f00b204e9800998ecf8427e"
},
{
"filename": "id-centos.out",
"mode": "text",
"hash": "4295be239a14ad77ef3253103de976d2"
},
{
"filename": "ifcfg.json",
"mode": "text",
"hash": "01fda0d9ba9a75618b072e64ff512b43"
},
...
]
"""
import re
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.2'
version = '1.3'
description = 'hashsum command parser (`md5sum`, `shasum`, etc.)'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -81,6 +89,15 @@ class info():
__version__ = info.version
_mode_friendly_names = {
" ": "text",
"*": "binary",
# Perl shasum -- specific
"U": "universal",
"^": "bits",
# BSD-style format only supports binary mode
None: "binary"
}
def _process(proc_data):
"""
@@ -95,7 +112,9 @@ def _process(proc_data):
List of Dictionaries. Structured data to conform to the schema.
"""
# no further processing for this parser
for entry in proc_data:
entry['mode'] = _mode_friendly_names.get(entry['mode'],entry['mode'])
return proc_data
@@ -127,18 +146,20 @@ def parse(data, raw=False, quiet=False):
file_name = line.split('=', maxsplit=1)[0].strip()
file_name = file_name[5:]
file_name = file_name[:-1]
# filler, legacy md5 always uses binary mode
file_mode = None
# standard md5sum and shasum command output
else:
file_hash = line.split(maxsplit=1)[0]
file_name = line.split(maxsplit=1)[1]
m = re.match('([0-9a-f]+) (.)(.*)$', line)
if not m:
raise ValueError(f'Invalid line format: "{line}"')
file_hash, file_mode, file_name = m.groups()
item = {
'filename': file_name,
'mode': file_mode,
'hash': file_hash
}
raw_output.append(item)
if raw:
return raw_output
else:
return _process(raw_output)
return raw_output if raw else _process(raw_output)

View File

@@ -219,7 +219,7 @@ import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '2.4'
version = '2.5'
description = '`ifconfig` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -264,7 +264,7 @@ def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
try:
if entry['ipv4_mask'].startswith('0x'):
new_mask = entry['ipv4_mask']
new_mask = new_mask.lstrip('0x')
new_mask = new_mask[2:]
new_mask = '.'.join(str(int(i, 16)) for i in [new_mask[i:i + 2] for i in range(0, len(new_mask), 2)])
entry['ipv4_mask'] = new_mask
except (ValueError, TypeError, AttributeError):
@@ -289,7 +289,7 @@ def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
try:
if ip_address['mask'].startswith('0x'):
new_mask = ip_address['mask']
new_mask = new_mask.lstrip('0x')
new_mask = new_mask[2:]
new_mask = '.'.join(str(int(i, 16)) for i in [new_mask[i:i + 2] for i in range(0, len(new_mask), 2)])
ip_address['mask'] = new_mask
except (ValueError, TypeError, AttributeError):

View File

@@ -173,7 +173,7 @@ import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.12'
version = '1.13'
description = '`iptables` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -294,9 +294,16 @@ def parse(data, raw=False, quiet=False):
else:
# sometimes the "target" column is blank. Stuff in a dummy character
if headers[0] == 'target' and line.startswith(' '):
opt_values = {'--', '-f', '!f'}
line_split = line.split()
if headers[0] == 'target' and line.startswith(' '): # standard output
line = '\u2063' + line
elif headers[0] == 'pkts' and line_split[3] in opt_values: # verbose output
first_section = line_split[:2]
second_section = line_split[2:]
line = ' '.join(first_section) + ' \u2063 ' + ' '.join(second_section)
rule = line.split(maxsplit=len(headers) - 1)
temp_rule = dict(zip(headers, rule))
if temp_rule:

View File

@@ -0,0 +1,194 @@
r"""jc - JSON Convert `net localgroup` command output parser
Usage (cli):
$ net localgroup | jc --net-localgroup
$ net localgroup /domain | jc --net-localgroup
$ net localgroup Administrators | jc --net-localgroup
$ net localgroup Administrators /domain | jc --net-localgroup
Usage (module):
import jc
result = jc.parse('net_localgroup', net_localgroup_command_output)
Schema:
{
"account_origin": string,
"domain": string,
"comment": string,
"groups": [
{
"name": string
"members": [
string
]
}
],
}
Examples:
$ net localgroup | jc --net-localgroup -p
{
"account_origin": null,
"comment": null,
"domain": null,
"groups": [
{
"name": "Administrators",
"members": [
"Administrator",
"Operator",
"ansible",
"user1"
]
}
]
}
"""
import re
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = '`net localgroup` command parser'
author = 'joehacksalot'
author_email = 'joehacksalot@gmail.com'
compatible = ['win32']
magic_commands = ['net localgroup']
tags = ['command']
__version__ = info.version
def parse(data, raw=False, quiet=False):
"""
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:
Parsed dictionary. The raw and processed data structures are the same.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output = {}
if jc.utils.has_data(data):
# Initialize the parsed output dictionary with all fields set to None or empty lists
raw_output = _parse(data)
return raw_output if raw else _process(raw_output)
def _process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (Dictionary) raw structured data to process
Returns:
Processed Dictionary. Structured data to conform to the schema.
"""
return proc_data
class _PushbackIterator:
def __init__(self, iterator):
self.iterator = iterator
self.pushback_stack = []
def __iter__(self):
return self
def __next__(self):
if self.pushback_stack:
return self.pushback_stack.pop()
else:
return next(self.iterator)
def pushback(self, value):
self.pushback_stack.append(value)
def _parse_net_localgroup_list(line_iter, expect_asterisk):
name_list = []
while True:
try:
line = next(line_iter)
if not line.strip():
continue # Skip empty lines
# Check if the line starts with an asterisk
if line == 'The command completed successfully.':
break
elif expect_asterisk and line.startswith('*'):
name_list.append(line[1:].strip())
else:
name_list.append(line)
except StopIteration:
break
return name_list
def _parse(data):
lines = data.splitlines()
parse_type = None # Can be 'groups_list' or 'members'
result = {
"account_origin": None,
"domain": None,
"comment": None,
"groups": []
}
group_name = ""
lines = data.splitlines()
lines = [line.rstrip() for line in lines if line.strip() != ""]
line_iter = _PushbackIterator(iter(lines))
for line in line_iter:
line = line.rstrip()
# Skip empty lines
if not line.strip():
continue
match_domain_processed = re.match(r"^The request will be processed at a domain controller for domain (.+)", line, re.IGNORECASE)
match_localgroup_list = re.match(r"^Aliases for[\s]*([^:]+)", line, re.IGNORECASE) # "Aliases for \\DESKTOP-WIN11:"
match_localgroup_members = re.match(r"^Alias name[\s]*([^:]+)", line, re.IGNORECASE) # "Alias name administrators:"
if match_domain_processed:
# Extract the domain name
result["domain"] = match_domain_processed.group(1).strip()
elif match_localgroup_list:
# Extract the account origin
result["account_origin"] = match_localgroup_list.group(1).strip()
parse_type = 'groups_list' # Prepare to read groups
elif match_localgroup_members:
# We are querying a specific group
group_name = match_localgroup_members.group(1).strip()
parse_type = 'members_list' # Prepare to read members
elif line.startswith('Comment'):
comment_line = line.split('Comment', 1)[1].strip()
result["comment"] = comment_line if comment_line else None
elif line.startswith('---'):
# Start of a section (groups or members)
if parse_type == 'groups_list':
names_list = _parse_net_localgroup_list(line_iter, expect_asterisk=True)
result["groups"] = [{"name": group_name, "members": []} for group_name in names_list]
elif parse_type == 'members_list':
names_list = _parse_net_localgroup_list(line_iter, expect_asterisk=False)
result["groups"] = [{
"name": group_name,
"members": names_list
}]
return result

441
jc/parsers/net_user.py Normal file
View File

@@ -0,0 +1,441 @@
r"""jc - JSON Convert `net user` command output parser
Usage (cli):
$ net users | jc --net-user
$ net users /domain | jc --net-user
$ net users User1 | jc --net-user
$ net users User1 /domain | jc --net-user
Usage (module):
import jc
result = jc.parse('net_user', net_user_command_output)
Schema:
{
"domain": string,
"account_origin": string,
"user_accounts": [
{
"user_name": string,
"full_name": string,
"comment": string,
"user_comment": string,
"country_region_code": string,
"account_active": boolean,
"account_expires": string,
"password_last_set": string,
"password_expires": string,
"password_changeable": string,
"password_required": boolean,
"user_may_change_password": boolean,
"workstations_allowed": string,
"logon_script": string,
"user_profile": string,
"home_directory": string,
"last_logon": string,
"logon_hours_allowed": string,
"local_group_memberships": [
string,
],
"global_group_memberships": [
string,
]
}
]
}
Examples:
$ net users | jc --net-user -p
{
"account_origin": "\\\\WIN-SERVER16",
"domain": "",
"user_accounts": [
{
"user_name": "Administrator"
},
{
"user_name": "DefaultAccount"
},
{
"user_name": "Guest"
},
{
"user_name": "pentera_BnlLQVnd7p"
},
{
"user_name": "user1"
}
]
}
$ net users /domain | jc --net-user -p
{
"account_origin": "\\\\DESKTOP-WIN10-PRO.somecompany.corp",
"domain": "somecompany.corp",
"user_accounts": [
{
"user_name": "aaron"
},
{
"user_name": "addison"
},
{
"user_name": "Administrator"
},
{
"user_name": "ansible"
},
{
"user_name": "da"
},
{
"user_name": "DefaultAccount"
},
{
"user_name": "Guest"
},
{
"user_name": "harrison"
},
{
"user_name": "james"
},
{
"user_name": "krbtgt"
},
{
"user_name": "liam"
},
{
"user_name": "localadmin"
},
{
"user_name": "tiffany"
}
]
}
$ net users Administrator | jc --net-user -p
{
"domain": "",
"user_accounts": [
{
"account_active": true,
"account_expires": "Never",
"comment": "Built-in account for administering the computer/domain",
"country_region_code": "000 (System Default)",
"global_group_memberships": [],
"last_logon": "2024-08-23T13:47:11",
"local_group_memberships": [
"Administrators"
],
"logon_hours_allowed": "All",
"password_changeable": "2021-12-17T11:07:14",
"password_expires": "2022-01-27T11:07:14",
"password_last_set": "2021-12-16T11:07:14",
"password_required": true,
"user_may_change_password": true,
"user_name": "Administrators",
"workstations_allowed": "All"
}
]
}
$ net users Administrator /domain | jc --net-user -p | jq
{
"domain": "somecompany.corp",
"user_accounts": [
{
"account_active": true,
"account_expires": "Never",
"comment": "Built-in account for administering the computer/domain",
"country_region_code": "000 (System Default)",
"global_group_memberships": [
"Domain Admins",
"Domain Users",
"Group Policy Creator",
"Enterprise Admins",
"Schema Admins"
],
"last_logon": "2024-07-17T13:46:12",
"local_group_memberships": [
"Administrators"
],
"logon_hours_allowed": "All",
"password_changeable": "2023-09-30T11:44:26",
"password_expires": "Never",
"password_last_set": "2023-09-29T11:44:26",
"password_required": true,
"user_may_change_password": true,
"user_name": "Administrators",
"workstations_allowed": "All"
}
]
}
"""
from datetime import datetime
import re
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = '`net user` command parser'
author = 'joehacksalot'
author_email = 'joehacksalot@gmail.com'
compatible = ['win32']
magic_commands = ['net user']
tags = ['command']
__version__ = info.version
def parse(data, raw=False, quiet=False):
"""
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:
Parsed dictionary. The raw and processed data structures are the same.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output = {}
if jc.utils.has_data(data):
raw_output = _parse(data)
if not raw_output:
raw_output = {}
return raw_output if raw else _process(raw_output)
def _set_if_not_none(output_dict, key, value):
if value is not None:
output_dict[key] = value
def _process_string_is_yes(text):
if text:
return text.lower() == "yes"
else:
return None
def _process_date(s):
if s is not None:
for fmt in ('%m/%d/%Y %I:%M:%S %p', '%m/%d/%Y %H:%M:%S %p'):
try:
return datetime.strptime(s, fmt).isoformat()
except ValueError:
continue
return s # Return the original string if parsing fails
def _process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (Dictionary) raw structured data to process
Returns:
Processed Dictionary. Structured data to conform to the schema.
"""
for user_account in proc_data.get("user_accounts", []):
_set_if_not_none(user_account, "account_active", _process_string_is_yes(user_account.get("account_active", None)))
_set_if_not_none(user_account, "password_last_set", _process_date(user_account.get("password_last_set", None)))
_set_if_not_none(user_account, "password_expires", _process_date(user_account.get("password_expires", None)))
_set_if_not_none(user_account, "password_changeable", _process_date(user_account.get("password_changeable", None)))
_set_if_not_none(user_account, "password_required", _process_string_is_yes(user_account.get("password_required", None)))
_set_if_not_none(user_account, "user_may_change_password", _process_string_is_yes(user_account.get("user_may_change_password", None)))
_set_if_not_none(user_account, "last_logon", _process_date(user_account.get("last_logon", None)))
if not proc_data:
proc_data = {}
return proc_data
class _PushbackIterator:
def __init__(self, iterator):
self.iterator = iterator
self.pushback_stack = []
def __iter__(self):
return self
def __next__(self):
if self.pushback_stack:
return self.pushback_stack.pop()
else:
return next(self.iterator)
def pushback(self, value):
self.pushback_stack.append(value)
def _parse_user_account_keypairs(keypair_dict):
user_account_parsed = {}
_set_if_not_none(user_account_parsed, "user_name", keypair_dict.get("user_name", None))
_set_if_not_none(user_account_parsed, "full_name", keypair_dict.get("full_name", None))
_set_if_not_none(user_account_parsed, "comment", keypair_dict.get("comment", None))
_set_if_not_none(user_account_parsed, "users_comment", keypair_dict.get("users_comment", None))
_set_if_not_none(user_account_parsed, "country_region_code", keypair_dict.get("country_region_code", None))
_set_if_not_none(user_account_parsed, "account_active", keypair_dict.get("account_active", None))
_set_if_not_none(user_account_parsed, "account_expires", keypair_dict.get("account_expires", None))
_set_if_not_none(user_account_parsed, "password_last_set", keypair_dict.get("password_last_set", None))
_set_if_not_none(user_account_parsed, "password_expires", keypair_dict.get("password_expires", None))
_set_if_not_none(user_account_parsed, "password_changeable", keypair_dict.get("password_changeable", None))
_set_if_not_none(user_account_parsed, "password_required", keypair_dict.get("password_required", None))
_set_if_not_none(user_account_parsed, "user_may_change_password", keypair_dict.get("user_may_change_password", None))
_set_if_not_none(user_account_parsed, "workstations_allowed", keypair_dict.get("workstations_allowed", None))
_set_if_not_none(user_account_parsed, "logon_script", keypair_dict.get("logon_script", None))
_set_if_not_none(user_account_parsed, "user_profile", keypair_dict.get("user_profile", None))
_set_if_not_none(user_account_parsed, "home_directory", keypair_dict.get("home_directory", None))
_set_if_not_none(user_account_parsed, "last_logon", keypair_dict.get("last_logon", None))
_set_if_not_none(user_account_parsed, "logon_hours_allowed", keypair_dict.get("logon_hours_allowed", None))
_set_if_not_none(user_account_parsed, "local_group_memberships", keypair_dict.get("local_group_memberships", None))
_set_if_not_none(user_account_parsed, "global_group_memberships", keypair_dict.get("global_group_memberships", None))
return user_account_parsed
def _parse_groups(line_iter):
group_list = []
# Process additional lines that belong to the current entry (e.g., additional DNS servers, DNS Suffix Search List)
while True:
try:
next_line = next(line_iter).strip()
if not next_line:
continue # Skip empty lines
# Check if the line is indented (starts with whitespace)
if next_line.startswith('*'):
groups = next_line.split("*")
groups = [group.strip() for group in groups if group.strip() != ""]
if "None" in groups:
groups.remove("None")
# It's an indented line; append the stripped line to entry_list
group_list.extend(groups)
else:
# Not an indented line; push it back and exit
line_iter.pushback(next_line)
break
except StopIteration:
break
return group_list
def _parse(data):
result = {
"domain": "",
"user_accounts": []
}
lines = data.splitlines()
lines = [line.rstrip() for line in lines if line.strip() != ""]
line_iter = _PushbackIterator(iter(lines))
for line in line_iter:
line = line.rstrip()
# Skip empty lines
if not line.strip():
continue
match_domain_processed = re.match(r"^The request will be processed at a domain controller for domain (.+)\.$", line, re.IGNORECASE)
if match_domain_processed:
result["domain"] = match_domain_processed.group(1).strip()
# Check if the text is of the first type (detailed user info)
elif "User name" in line:
line_iter.pushback(line)
user_account_keypairs = {}
# Regular expression to match key-value pairs
kv_pattern = re.compile(r'^([\w\s\/\'\-]{1,29})\s*(.+)?$')
key = None
while True:
# Process each line
# Break when done
try:
line = next(line_iter)
line = line.strip()
if not line:
continue # Skip empty lines
match = kv_pattern.match(line)
if "The command completed" in line:
break
elif match:
key_raw = match.group(1).strip()
key = key_raw.lower().replace(" ", "_").replace("'", "").replace("/", "_").replace("-", "_")
if len(match.groups()) == 2 and match.group(2) is not None:
value = match.group(2).strip()
if key in ["local_group_memberships", "global_group_memberships"]:
line_iter.pushback(value)
user_account_keypairs[key] = _parse_groups(line_iter)
else:
user_account_keypairs[key] = value
else:
# Line without value, it's a key with empty value
user_account_keypairs[key] = None
else:
raise ValueError(f"Unexpected line: {line}")
except StopIteration:
break
# Convert specific fields
result["user_accounts"].append(_parse_user_account_keypairs(user_account_keypairs))
elif "User accounts for" in line:
line_iter.pushback(line)
collecting_users = False
while True:
# Process each line
# Break when done
try:
line = next(line_iter)
line = line.strip()
if not line:
continue # Skip empty lines
# Check for domain line
domain_pattern = re.compile(r'^User accounts for (.+)$')
account_origin_match = domain_pattern.match(line)
if account_origin_match:
result["account_origin"] = account_origin_match.group(1)
continue
# Check for the line of dashes indicating start of user list
if line.startswith('---'):
collecting_users = True
continue
# Check for the completion message
if line.startswith('The command completed'):
break
if collecting_users:
# Split the line into usernames
user_matches = re.match(r'(.{1,20})(\s+.{1,20})?(\s+.{1,20})?', line)
if user_matches:
for username in user_matches.groups():
if username:
username = username.strip()
user_account = {"user_name": username}
result["user_accounts"].append(user_account)
except StopIteration:
break
else:
raise ValueError(f"Unexpected line: {line}")
return result

View File

@@ -36,7 +36,8 @@ These are documented below.
[
{
"<key>": string/integer/float, # [0]
"team_config": object,
"team_config": object/null,
"team_port_config": object/null,
"dhcp4_option_x": {
"name": string,
"value": string/integer/float,
@@ -151,7 +152,7 @@ from jc.exceptions import ParseError
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.1'
version = '1.2'
description = '`nmcli` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -320,23 +321,32 @@ def _connection_show_x_parse(data: str) -> List[Dict]:
for line in filter(None, data.splitlines()):
# fix for team.config, which is multi-line JSON
if line.startswith('team.config:'):
# fix for team.config and team-port.config, which are multi-line JSON
if line.startswith('team.config:') or line.startswith('team-port.config:'):
key, value = line.split(':', maxsplit=1)
key_team = _normalize_key(key)
value_team = value.strip()
if value_team == '--':
team_config_value = []
item[key_team] = None
continue
in_team_config = True
_, value = line.split(':', maxsplit=1)
team_config_value.append(value.strip())
item['team_config'] = {}
team_config_value.append(value_team)
item[key_team] = {}
continue
if not line.startswith('team.') and in_team_config:
STARTSWITH_TEAM = line.startswith('team.') or line.startswith('team-port.')
if not STARTSWITH_TEAM and in_team_config:
team_config_value.append(line.strip())
continue
in_team_config = False
if team_config_value:
# team.config value should always be JSON
item['team_config'] = json.loads(''.join(team_config_value))
# team.config and team-port.config values should always be JSON
item[key_team] = json.loads(''.join(team_config_value))
team_config_value = []
key, value = line.split(':', maxsplit=1)

View File

@@ -180,13 +180,13 @@ import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
version = '1.1'
description = '`pacman` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['command', 'file']
magic_commands = ['pacman']
magic_commands = ['pacman', 'yay']
__version__ = info.version

View File

@@ -26,7 +26,10 @@ Schema:
"license": string,
"location": string,
"requires": string,
"required_by": string
"required_by": string,
"files": [
string
]
}
]
@@ -60,13 +63,13 @@ Examples:
}
]
"""
from typing import List, Dict, Optional
from typing import List, Dict
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.5'
version = '1.6'
description = '`pip show` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -120,6 +123,22 @@ def parse(
last_key: str = ''
last_key_data: List = []
def flush_last_key_data() -> None:
"""Append buffered continuation lines to the previous field."""
nonlocal last_key_data
if not last_key_data:
return
if last_key == 'files':
package[last_key].extend(last_key_data)
else:
if not isinstance(package[last_key], str):
package[last_key] = ''
package[last_key] = package[last_key] + '\n' + '\n'.join(last_key_data)
last_key_data = []
# Clear any blank lines
cleandata = list(filter(None, data.splitlines()))
@@ -127,8 +146,7 @@ def parse(
for row in cleandata:
if row.startswith('---'):
if last_key_data:
package[last_key] = package[last_key] + '\n' + '\n'.join(last_key_data)
flush_last_key_data()
raw_output.append(package)
package = {}
@@ -137,17 +155,17 @@ def parse(
continue
if not row.startswith(' '):
item_key = row.split(': ', maxsplit=1)[0].lower().replace('-', '_')
item_value: Optional[str] = row.split(': ', maxsplit=1)[1]
item_key, item_value = row.split(':', maxsplit=1)
item_key = item_key.lower().replace('-', '_')
item_value = item_value.lstrip()
if item_value == '':
if item_key == 'files':
item_value = []
elif item_value == '':
item_value = None
if last_key_data and last_key != item_key:
if not isinstance(package[last_key], str):
package[last_key] = ''
package[last_key] = package[last_key] + '\n' + '\n'.join(last_key_data)
last_key_data = []
flush_last_key_data()
package[item_key] = item_value
last_key = item_key
@@ -158,8 +176,7 @@ def parse(
continue
if package:
if last_key_data:
package[last_key] = package[last_key] + '\n' + '\n'.join(last_key_data)
flush_last_key_data()
raw_output.append(package)

View File

@@ -168,7 +168,7 @@ import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
version = '1.1'
description = '`/proc/<pid>/smaps` file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -205,33 +205,46 @@ def _process(proc_data: List[Dict]) -> List[Dict]:
vmflags_map = {
'rd': 'readable',
'wr': 'writeable',
'ex': 'executable',
'sh': 'shared',
'mr': 'may read',
'mw': 'may write',
'me': 'may execute',
'ms': 'may share',
'mp': 'MPX-specific VMA',
'gd': 'stack segment growns down',
'pf': 'pure PFN range',
'dw': 'disabled write to the mapped file',
'lo': 'pages are locked in memory',
'io': 'memory mapped I/O area',
'sr': 'sequential read advise provided',
'rr': 'random read advise provided',
'dc': 'do not copy area on fork',
'de': 'do not expand area on remapping',
'ac': 'area is accountable',
'nr': 'swap space is not reserved for the area',
'ht': 'area uses huge tlb pages',
'ar': 'architecture specific flag',
'dd': 'do not include area into core dump',
'sd': 'soft-dirty flag',
'mm': 'mixed map area',
'hg': 'huge page advise flag',
'nh': 'no-huge page advise flag',
'mg': 'mergable advise flag'
'wr': 'writeable',
'ex': 'executable',
'sh': 'shared',
'mr': 'may read',
'mw': 'may write',
'me': 'may execute',
'ms': 'may share',
'mp': 'MPX-specific VMA',
'gd': 'stack segment growns down',
'pf': 'pure PFN range',
'dw': 'disabled write to the mapped file',
'lo': 'pages are locked in memory',
'io': 'memory mapped I/O area',
'sr': 'sequential read advise provided',
'rr': 'random read advise provided',
'dc': 'do not copy area on fork',
'de': 'do not expand area on remapping',
'ac': 'area is accountable',
'nr': 'swap space is not reserved for the area',
'ht': 'area uses huge tlb pages',
'sf': 'perform synchronous page faults',
'nl': 'non-linear mapping',
'ar': 'architecture specific flag',
'wf': 'wipe on fork',
'dd': 'do not include area into core dump',
'sd': 'soft-dirty flag',
'mm': 'mixed map area',
'hg': 'huge page advise flag',
'nh': 'no-huge page advise flag',
'mg': 'mergable advise flag',
'bt': 'arm64 BTI guarded page',
'mt': 'arm64 MTE allocation tags are enabled',
'um': 'userfaultfd missing pages tracking',
'uw': 'userfaultfd wprotect pages tracking',
'ui': 'userfaultfd minor fault',
'ss': 'shadow/guarded control stack page',
'sl': 'sealed',
'lf': 'lock on fault pages',
'dp': 'always lazily freeable mapping',
'gu': 'maybe contains guard regions'
}
for entry in proc_data:
@@ -245,7 +258,7 @@ def _process(proc_data: List[Dict]) -> List[Dict]:
if 'VmFlags' in entry:
entry['VmFlags'] = entry['VmFlags'].split()
entry['VmFlags_pretty'] = [vmflags_map[x] for x in entry['VmFlags']]
entry['VmFlags_pretty'] = [vmflags_map.get(x, x) for x in entry['VmFlags']]
return proc_data

View File

@@ -111,8 +111,6 @@ Examples:
]
"""
import jc.utils
import jc.parsers.universal
class info():
"""Provides parser metadata (version, author, etc.)"""

455
jc/parsers/route_print.py Normal file
View File

@@ -0,0 +1,455 @@
r"""jc - JSON Convert `route print` command output parser
See also: the `route` command parser
Usage (cli):
$ route print | jc --route-print
Usage (module):
import jc
result = jc.parse('route_print', route_print_command_output)
Schema:
{
"interface_list": [
{
"interface_index": integer,
"mac_address": string,
"description": string
}
],
"ipv4_route_table": {
"active_routes": [
{
"network_destination": string,
"netmask": string,
"gateway": string,
"interface": string,
"metric": integer, # [0]
"metric_set_to_default": boolean # [1]
}
],
"persistent_routes": [
{
"network_address": string,
"netmask": string,
"gateway_address": string,
"metric": integer # [0]
"metric_set_to_default": boolean # [1]
}
]
},
"ipv6_route_table": {
"active_routes": [
{
"interface": integer,
"metric": integer, # [0]
"metric_set_to_default": boolean, # [1]
"network_destination": string,
"gateway": string
}
],
"persistent_routes": [
{
"interface": integer,
"metric": integer, # [0]
"metric_set_to_default": boolean, # [1]
"network_destination": string,
"gateway": string
}
]
}
}
[0] Null/None if "metric" = "Default"
[1] True if "metric" = "Default"
Examples:
$ route print | jc --route-print -p
{
"interface_list": [
{
"interface_index": 28,
"mac_address": null,
"description": "Tailscale Tunnel"
},
{
"interface_index": 12,
"mac_address": "00:1c:42:da:01:6a",
"description": "Parallels VirtIO Ethernet Adapter"
},
{
"interface_index": 1,
"mac_address": null,
"description": "Software Loopback Interface 1"
}
],
"ipv4_route_table": {
"active_routes": [
{
"network_destination": "0.0.0.0",
"netmask": "0.0.0.0",
"gateway": "10.211.55.1",
"interface": "10.211.55.3",
"metric": 15,
"metric_set_to_default": false
},
{
"network_destination": "10.0.0.0",
"netmask": "255.0.0.0",
"gateway": "192.168.22.1",
"interface": "10.211.55.3",
"metric": 16,
"metric_set_to_default": false
},
...
{
"network_destination": "255.255.255.255",
"netmask": "255.255.255.255",
"gateway": "On-link",
"interface": "10.211.55.3",
"metric": null,
"metric_set_to_default": true
}
],
"persistent_routes": [
{
"network_address": "10.0.1.0",
"netmask": "255.255.255.0",
"gateway_address": "192.168.22.1",
"metric": 1,
"metric_set_to_default": false
},
{
"network_address": "10.0.3.0",
"netmask": "255.255.255.0",
"gateway_address": "192.168.22.1",
"metric": 1,
"metric_set_to_default": false
},
...
]
},
"ipv6_route_table": {
"active_routes": [
{
"interface": 1,
"metric": 331,
"network_destination": "::1/128",
"gateway": "On-link",
"metric_set_to_default": false
},
{
"interface": 12,
"metric": 271,
"network_destination": "2001:db8::/64",
"gateway": "fe80::1",
"metric_set_to_default": false
},
...
{
"interface": 12,
"metric": 271,
"network_destination": "ff00::/8",
"gateway": "On-link",
"metric_set_to_default": false
}
],
"persistent_routes": [
{
"interface": 0,
"metric": 4294967295,
"network_destination": "2001:db8::/64",
"gateway": "fe80::1",
"metric_set_to_default": false
}
]
}
}
"""
import re
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = '`route print` command parser'
author = 'joehacksalot'
author_email = 'joehacksalot@gmail.com'
details = 'See also: `route` command parser'
compatible = ['win32']
magic_commands = ['route print']
tags = ['command']
__version__ = info.version
def parse(data, raw=False, quiet=False):
"""
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:
Parsed dictionary. The raw and processed data structures are the same.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output = {}
if jc.utils.has_data(data):
raw_data = {
"interface_list": [],
"ipv4_route_table": {
"active_routes": [],
"persistent_routes": []
},
"ipv6_route_table": {
"active_routes": [],
"persistent_routes": []
}
}
lines = data.splitlines()
_parse_interface_list(raw_data, _PushbackIterator(iter(lines)))
_parse_ipv4_route_table(raw_data, _PushbackIterator(iter(lines)))
_parse_ipv6_route_table(raw_data, _PushbackIterator(iter(lines)))
raw_output = raw_data
return raw_output if raw else _process(raw_output)
def _process(proc_data):
"""
Final processing to conform to the schema.
Parameters:
proc_data: (Dictionary) raw structured data to process
Returns:
Processed Dictionary. Structured data to conform to the schema.
"""
if not proc_data:
return {}
for interface in proc_data['interface_list']:
if interface["mac_address"] == '' or interface["mac_address"] == '00 00 00 00 00 00 00 e0': # Placeholder MAC address for virtual adapters
mac_address = None
else:
mac_address = interface["mac_address"].replace(" ", ":")
interface["mac_address"] = mac_address
interface["interface_index"] = jc.utils.convert_to_int(interface["interface_index"])
for ipv4_active_route in proc_data['ipv4_route_table']['active_routes']:
if ipv4_active_route["metric"] != "Default":
ipv4_active_route["metric"] = jc.utils.convert_to_int(ipv4_active_route["metric"])
ipv4_active_route["metric_set_to_default"] = False
else:
ipv4_active_route["metric"] = None
ipv4_active_route["metric_set_to_default"] = True
for ipv4_persistent_route in proc_data['ipv4_route_table']['persistent_routes']:
if ipv4_persistent_route["metric"] != "Default":
ipv4_persistent_route["metric"] = jc.utils.convert_to_int(ipv4_persistent_route["metric"])
ipv4_persistent_route["metric_set_to_default"] = False
else:
ipv4_persistent_route["metric"] = None
ipv4_persistent_route["metric_set_to_default"] = True
for ipv6_active_route in proc_data['ipv6_route_table']['active_routes']:
ipv6_active_route["interface"] = jc.utils.convert_to_int(ipv6_active_route["interface"])
if ipv6_active_route["metric"] != "Default":
ipv6_active_route["metric"] = jc.utils.convert_to_int(ipv6_active_route["metric"])
ipv6_active_route["metric_set_to_default"] = False
else:
ipv6_active_route["metric"] = None
ipv6_active_route["metric_set_to_default"] = True
for ipv6_persistent_route in proc_data['ipv6_route_table']['persistent_routes']:
ipv6_persistent_route["interface"] = jc.utils.convert_to_int(ipv6_persistent_route["interface"])
if ipv6_persistent_route["metric"] != "Default":
ipv6_persistent_route["metric"] = jc.utils.convert_to_int(ipv6_persistent_route["metric"])
ipv6_persistent_route["metric_set_to_default"] = False
else:
ipv6_persistent_route["metric"] = None
ipv6_persistent_route["metric_set_to_default"] = True
return proc_data
class _PushbackIterator:
"""Iterator that allows pushing back values onto the iterator. Supports handing off
parsing to localized parsers while maintaining line synchonization."""
def __init__(self, iterator):
self.iterator = iterator
self.pushback_stack = []
def __iter__(self):
return self
def __next__(self):
if self.pushback_stack:
return self.pushback_stack.pop()
else:
return next(self.iterator)
def pushback(self, value):
self.pushback_stack.append(value)
def contains(self, pattern):
iter_lines = list(self.iterator)
list_lines = self.pushback_stack.copy()
list_lines.extend(iter_lines)
self.iterator = iter(list_lines)
self.pushback_stack = []
# Check the pushback stack first
for line in list_lines:
if re.match(pattern, line):
return True
return False
def skip_until(self, pattern):
for line in self:
if re.match(pattern, line):
return line
return None
def _parse_interface_list(data, lines_iter):
start_of_interface_list_pattern = r'^Interface List'
if lines_iter.contains(start_of_interface_list_pattern):
line = lines_iter.skip_until(start_of_interface_list_pattern)
for line in lines_iter:
if re.match(r'^=+$', line):
break # End of interface list
interface_index = line[:5].replace(".", "").strip()
mac_address = line[5:30].replace(".","").strip()
description = line[30:].strip()
data['interface_list'].append({
"interface_index": interface_index,
"mac_address": mac_address,
"description": description
})
def _parse_ipv4_route_table(data, lines_iter):
def _parse_ipv4_active_routes(data, lines_iter):
line = lines_iter.skip_until(r'^Active Routes')
line = next(lines_iter, '') # Skip the header line
if line.strip() == 'None':
return
for line in lines_iter:
if re.match(r'^=+$', line):
break # End of interface list
if 'Default Gateway' in line:
continue
lines_split = line.split()
network_destination = lines_split[0]
netmask = lines_split[1]
gateway = lines_split[2]
interface = lines_split[3]
metric = lines_split[4]
data['ipv4_route_table']["active_routes"].append({
"network_destination": network_destination,
"netmask": netmask,
"gateway": gateway,
"interface": interface,
"metric": metric
})
def _parse_ipv4_persistent_routes(data, lines_iter):
line = lines_iter.skip_until(r'^Persistent Routes')
line = next(lines_iter, '') # line is either "None" and we abort parsing this section or we skip header line
if line.strip() == 'None':
return
for line in lines_iter:
if re.match(r'^=+$', line):
break
lines_split = line.split()
network_address = lines_split[0]
netmask = lines_split[1]
gateway_address = lines_split[2]
metric = lines_split[3]
data['ipv4_route_table']["persistent_routes"].append({
"network_address": network_address,
"netmask": netmask,
"gateway_address": gateway_address,
"metric": metric
})
start_of_ipv4_route_table_pattern = r'^IPv4 Route Table'
if lines_iter.contains(start_of_ipv4_route_table_pattern):
line = lines_iter.skip_until(start_of_ipv4_route_table_pattern)
line = next(lines_iter, '') # Skip the separator line
_parse_ipv4_active_routes(data, lines_iter)
_parse_ipv4_persistent_routes(data, lines_iter)
def _parse_ipv6_route_table(data, lines_iter):
def _parse_ipv6_active_routes(data, lines_iter):
line = lines_iter.skip_until(r'^Active Routes')
line = next(lines_iter, '') # line is either "None" and we abort parsing this section or we skip header line
if line.strip() == 'None':
return
for line in lines_iter:
if re.match(r'^=+$', line):
break
split_line = line.split()
interface = split_line[0]
metric = split_line[1]
network_destination = split_line[2]
if len(split_line) > 3:
gateway = split_line[3]
else:
gateway = next(lines_iter, '').strip()
data['ipv6_route_table']["active_routes"].append({
"interface": interface,
"metric": metric,
"network_destination": network_destination,
"gateway": gateway
})
def _parse_ipv6_persistent_routes(data, lines_iter):
line = lines_iter.skip_until(r'^Persistent Routes')
line = next(lines_iter, '') # line is either "None" and we abort parsing this section or we skip header line
if line.strip() == 'None':
return
for line in lines_iter:
if re.match(r'^=+$', line):
break
split_line = line.split()
interface = split_line[0]
metric = split_line[1]
network_destination = split_line[2]
if len(split_line) > 3:
gateway = split_line[3]
else:
gateway = next(lines_iter, '').strip()
data['ipv6_route_table']["persistent_routes"].append({
"interface": interface,
"metric": metric,
"network_destination": network_destination,
"gateway": gateway
})
start_of_ipv6_route_table_pattern = r'^IPv6 Route Table'
if lines_iter.contains(start_of_ipv6_route_table_pattern):
line = lines_iter.skip_until(start_of_ipv6_route_table_pattern)
line = next(lines_iter, '') # Skip the separator line
_parse_ipv6_active_routes(data, lines_iter)
_parse_ipv6_persistent_routes(data, lines_iter)

View File

@@ -4,6 +4,8 @@ Supports the `-i` or `--itemize-changes` options with all levels of
verbosity. This parser will process the `STDOUT` output or a log file
generated with the `--log-file` option.
The `--stats` or `--info=stats[1-3]` options are also supported.
Usage (cli):
$ rsync -i -a source/ dest | jc --rsync
@@ -37,7 +39,21 @@ Schema:
"false_alarms": integer,
"data": integer,
"bytes_sec": float,
"speedup": float
"speedup": float,
"total_files": integer,
"regular_files": integer,
"dir_files": integer,
"total_created_files": integer,
"created_regular_files": integer,
"created_dir_files": integer,
"deleted_files": integer,
"transferred_files": integer,
"transferred_file_size": integer,
"literal_data": integer,
"matched_data": integer,
"file_list_size": integer,
"file_list_generation_time": float,
"file_list_transfer_time": float,
},
"files": [
{
@@ -62,6 +78,8 @@ Schema:
}
]
Size values are in bytes.
[0] 'file sent', 'file received', 'local change or creation',
'hard link', 'not updated', 'message'
[1] 'file', 'directory', 'symlink', 'device', 'special file'
@@ -137,7 +155,7 @@ import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.2'
version = '1.3'
description = '`rsync` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -163,10 +181,16 @@ def _process(proc_data: List[Dict]) -> List[Dict]:
"""
int_list = {
'process', 'sent', 'received', 'total_size', 'matches', 'hash_hits',
'false_alarms', 'data'
'false_alarms', 'data', 'total_files', 'regular_files', 'dir_files',
'total_created_files', 'created_regular_files', 'created_dir_files',
'deleted_files', 'transferred_files', 'transferred_file_size',
'literal_data', 'matched_data', 'file_list_size'
}
float_list = {'bytes_sec', 'speedup'}
float_list = {
'bytes_sec', 'speedup', 'file_list_generation_time',
'file_list_transfer_time'
}
for item in proc_data:
for key in item['summary']:
@@ -338,6 +362,17 @@ def parse(
stat2_line_log_v_re = re.compile(r'(?P<date>\d\d\d\d/\d\d/\d\d)\s+(?P<time>\d\d:\d\d:\d\d)\s+\[(?P<process>\d+)\]\s+sent\s+(?P<sent>[\d,]+)\s+bytes\s+received\s+(?P<received>[\d,]+)\s+bytes\s+(?P<bytes_sec>[\d,.]+)\s+bytes/sec')
stat3_line_log_v_re = re.compile(r'(?P<date>\d\d\d\d/\d\d/\d\d)\s+(?P<time>\d\d:\d\d:\d\d)\s+\[(?P<process>\d+)]\s+total\s+size\s+is\s+(?P<total_size>[\d,]+)\s+speedup\s+is\s+(?P<speedup>[\d,.]+)')
stat_ex_files_number_re = re.compile(r'Number\sof\sfiles:\s(?P<files_total>[,0123456789]+)\s\(reg:\s(?P<files_regular>[,0123456789]+),\sdir:\s(?P<files_dir>[,0123456789]+)\)$')
stat_ex_files_created_re = re.compile(r'Number\sof\screated\sfiles:\s(?P<files_created_total>[,0123456789]+)\s\(reg:\s(?P<files_created_regular>[,0123456789]+),\sdir:\s(?P<files_created_dir>[,0123456789]+)\)$')
stat_ex_files_deleted_re = re.compile(r'Number\sof\sdeleted\sfiles:\s(?P<files_deleted>[,0123456789]+)$')
stat_ex_files_transferred_re = re.compile(r'Number\sof\sregular\sfiles\stransferred:\s(?P<files_transferred>[,0123456789]+)$')
stat_ex_files_transferred_size_re = re.compile(r'Total\sfile\ssize:\s(?P<files_transferred_size>[,.0123456789]+\S?)\sbytes$')
stat_ex_literal_data_re = re.compile(r'Literal\sdata:\s(?P<literal_data>[,.0123456789]+\S?)\sbytes$')
stat_ex_matched_data_re = re.compile(r'Matched\sdata:\s(?P<matched_data>[,.0123456789]+\S?)\sbytes$')
stat_ex_file_list_size_re = re.compile(r'File\slist\ssize:\s(?P<file_list_size>[,.0123456789]+\S?)$')
stat_ex_file_list_generation_time_re = re.compile(r'File\slist\sgeneration\stime:\s(?P<file_list_generation_time>[,.0123456789]+\S?)\sseconds$')
stat_ex_file_list_transfer_time_re = re.compile(r'File\slist\stransfer\stime:\s(?P<file_list_transfer_time>[,.0123456789]+\S?)\sseconds$')
if jc.utils.has_data(data):
for line in filter(None, data.splitlines()):
@@ -451,11 +486,11 @@ def parse(
stat1_line = stat1_line_re.match(line)
if stat1_line:
rsync_run['summary'] = {
rsync_run['summary'].update({
'sent': stat1_line.group('sent'),
'received': stat1_line.group('received'),
'bytes_sec': stat1_line.group('bytes_sec')
}
})
continue
stat2_line = stat2_line_re.match(line)
@@ -466,11 +501,11 @@ def parse(
stat1_line_simple = stat1_line_simple_re.match(line)
if stat1_line_simple:
rsync_run['summary'] = {
rsync_run['summary'].update({
'sent': stat1_line_simple.group('sent'),
'received': stat1_line_simple.group('received'),
'bytes_sec': stat1_line_simple.group('bytes_sec')
}
})
continue
stat2_line_simple = stat2_line_simple_re.match(line)
@@ -481,19 +516,19 @@ def parse(
stat_line_log = stat_line_log_re.match(line)
if stat_line_log:
rsync_run['summary'] = {
rsync_run['summary'].update({
'date': stat_line_log.group('date'),
'time': stat_line_log.group('time'),
'process': stat_line_log.group('process'),
'sent': stat_line_log.group('sent'),
'received': stat_line_log.group('received'),
'total_size': stat_line_log.group('total_size')
}
})
continue
stat1_line_log_v = stat1_line_log_v_re.match(line)
if stat1_line_log_v:
rsync_run['summary'] = {
rsync_run['summary'].update({
'date': stat1_line_log_v.group('date'),
'time': stat1_line_log_v.group('time'),
'process': stat1_line_log_v.group('process'),
@@ -501,7 +536,7 @@ def parse(
'hash_hits': stat1_line_log_v.group('hash_hits'),
'false_alarms': stat1_line_log_v.group('false_alarms'),
'data': stat1_line_log_v.group('data')
}
})
continue
stat2_line_log_v = stat2_line_log_v_re.match(line)
@@ -517,6 +552,61 @@ def parse(
rsync_run['summary']['speedup'] = stat3_line_log_v.group('speedup')
continue
# extra stats lines when using rsync --stats or --info=stats[1-3]
stat_ex_files_number_v = stat_ex_files_number_re.match(line)
if stat_ex_files_number_v:
rsync_run['summary']['total_files'] = stat_ex_files_number_v.group('files_total')
rsync_run['summary']['regular_files'] = stat_ex_files_number_v.group('files_regular')
rsync_run['summary']['dir_files'] = stat_ex_files_number_v.group('files_dir')
continue
stat_ex_files_created_v = stat_ex_files_created_re.match(line)
if stat_ex_files_created_v:
rsync_run['summary']['total_created_files'] = stat_ex_files_created_v.group('files_created_total')
rsync_run['summary']['created_regular_files'] = stat_ex_files_created_v.group('files_created_regular')
rsync_run['summary']['created_dir_files'] = stat_ex_files_created_v.group('files_created_dir')
continue
stat_ex_files_deleted_v = stat_ex_files_deleted_re.match(line)
if stat_ex_files_deleted_v:
rsync_run['summary']['deleted_files'] = stat_ex_files_deleted_v.group('files_deleted')
continue
stat_ex_files_transferred_v = stat_ex_files_transferred_re.match(line)
if stat_ex_files_transferred_v:
rsync_run['summary']['transferred_files'] = stat_ex_files_transferred_v.group('files_transferred')
continue
stat_ex_files_transferred_size_v = stat_ex_files_transferred_size_re.match(line)
if stat_ex_files_transferred_size_v:
rsync_run['summary']['transferred_file_size'] = stat_ex_files_transferred_size_v.group('files_transferred_size')
continue
stat_ex_literal_data_v = stat_ex_literal_data_re.match(line)
if stat_ex_literal_data_v:
rsync_run['summary']['literal_data'] = stat_ex_literal_data_v.group('literal_data')
continue
stat_ex_matched_data_v = stat_ex_matched_data_re.match(line)
if stat_ex_matched_data_v:
rsync_run['summary']['matched_data'] = stat_ex_matched_data_v.group('matched_data')
continue
stat_ex_file_list_size_v = stat_ex_file_list_size_re.match(line)
if stat_ex_file_list_size_v:
rsync_run['summary']['file_list_size'] = stat_ex_file_list_size_v.group('file_list_size')
continue
stat_ex_file_list_generation_time_v = stat_ex_file_list_generation_time_re.match(line)
if stat_ex_file_list_generation_time_v:
rsync_run['summary']['file_list_generation_time'] = stat_ex_file_list_generation_time_v.group('file_list_generation_time')
continue
stat_ex_file_list_transfer_time_v = stat_ex_file_list_transfer_time_re.match(line)
if stat_ex_file_list_transfer_time_v:
rsync_run['summary']['file_list_transfer_time'] = stat_ex_file_list_transfer_time_v.group('file_list_transfer_time')
continue
raw_output.append(rsync_run)
# cleanup blank entries

View File

@@ -7,6 +7,8 @@ Supports the `-i` or `--itemize-changes` options with all levels of
verbosity. This parser will process the `STDOUT` output or a log file
generated with the `--log-file` option.
The `--stats` or `--info=stats[1-3]` options are also supported.
Usage (cli):
$ rsync -i -a source/ dest | jc --rsync-s
@@ -64,6 +66,8 @@ Schema:
}
}
Size values are in bytes.
[0] 'file sent', 'file received', 'local change or creation',
'hard link', 'not updated', 'message'
[1] 'file', 'directory', 'symlink', 'device', 'special file'
@@ -88,7 +92,7 @@ from jc.streaming import (
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.3'
version = '1.4'
description = '`rsync` command streaming parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -114,10 +118,16 @@ def _process(proc_data: Dict) -> Dict:
"""
int_list = {
'process', 'sent', 'received', 'total_size', 'matches', 'hash_hits',
'false_alarms', 'data'
'false_alarms', 'data', 'total_files', 'regular_files', 'dir_files',
'total_created_files', 'created_regular_files', 'created_dir_files',
'deleted_files', 'transferred_files', 'transferred_file_size',
'literal_data', 'matched_data', 'file_list_size'
}
float_list = {'bytes_sec', 'speedup'}
float_list = {
'bytes_sec', 'speedup', 'file_list_generation_time',
'file_list_transfer_time'
}
for key in proc_data.copy():
if key in int_list:
@@ -281,6 +291,17 @@ def parse(
stat2_line_log_v_re = re.compile(r'(?P<date>\d\d\d\d/\d\d/\d\d)\s+(?P<time>\d\d:\d\d:\d\d)\s+\[(?P<process>\d+)\]\s+sent\s+(?P<sent>[\d,]+)\s+bytes\s+received\s+(?P<received>[\d,]+)\s+bytes\s+(?P<bytes_sec>[\d,.]+)\s+bytes/sec')
stat3_line_log_v_re = re.compile(r'(?P<date>\d\d\d\d/\d\d/\d\d)\s+(?P<time>\d\d:\d\d:\d\d)\s+\[(?P<process>\d+)]\s+total\s+size\s+is\s+(?P<total_size>[\d,]+)\s+speedup\s+is\s+(?P<speedup>[\d,.]+)')
stat_ex_files_number_re = re.compile(r'Number\sof\sfiles:\s(?P<files_total>[,0123456789]+)\s\(reg:\s(?P<files_regular>[,0123456789]+),\sdir:\s(?P<files_dir>[,0123456789]+)\)$')
stat_ex_files_created_re = re.compile(r'Number\sof\screated\sfiles:\s(?P<files_created_total>[,0123456789]+)\s\(reg:\s(?P<files_created_regular>[,0123456789]+),\sdir:\s(?P<files_created_dir>[,0123456789]+)\)$')
stat_ex_files_deleted_re = re.compile(r'Number\sof\sdeleted\sfiles:\s(?P<files_deleted>[,0123456789]+)$')
stat_ex_files_transferred_re = re.compile(r'Number\sof\sregular\sfiles\stransferred:\s(?P<files_transferred>[,0123456789]+)$')
stat_ex_files_transferred_size_re = re.compile(r'Total\sfile\ssize:\s(?P<files_transferred_size>[,.0123456789]+\S?)\sbytes$')
stat_ex_literal_data_re = re.compile(r'Literal\sdata:\s(?P<literal_data>[,.0123456789]+\S?)\sbytes$')
stat_ex_matched_data_re = re.compile(r'Matched\sdata:\s(?P<matched_data>[,.0123456789]+\S?)\sbytes$')
stat_ex_file_list_size_re = re.compile(r'File\slist\ssize:\s(?P<file_list_size>[,.0123456789]+\S?)$')
stat_ex_file_list_generation_time_re = re.compile(r'File\slist\sgeneration\stime:\s(?P<file_list_generation_time>[,.0123456789]+\S?)\sseconds$')
stat_ex_file_list_transfer_time_re = re.compile(r'File\slist\stransfer\stime:\s(?P<file_list_transfer_time>[,.0123456789]+\S?)\sseconds$')
for line in data:
try:
streaming_line_input_type_check(line)
@@ -408,12 +429,12 @@ def parse(
stat1_line = stat1_line_re.match(line)
if stat1_line:
summary = {
summary.update({
'type': 'summary',
'sent': stat1_line.group('sent'),
'received': stat1_line.group('received'),
'bytes_sec': stat1_line.group('bytes_sec')
}
})
continue
stat2_line = stat2_line_re.match(line)
@@ -424,12 +445,12 @@ def parse(
stat1_line_simple = stat1_line_simple_re.match(line)
if stat1_line_simple:
summary = {
summary.update({
'type': 'summary',
'sent': stat1_line_simple.group('sent'),
'received': stat1_line_simple.group('received'),
'bytes_sec': stat1_line_simple.group('bytes_sec')
}
})
continue
stat2_line_simple = stat2_line_simple_re.match(line)
@@ -440,7 +461,7 @@ def parse(
stat_line_log = stat_line_log_re.match(line)
if stat_line_log:
summary = {
summary.update({
'type': 'summary',
'date': stat_line_log.group('date'),
'time': stat_line_log.group('time'),
@@ -448,12 +469,12 @@ def parse(
'sent': stat_line_log.group('sent'),
'received': stat_line_log.group('received'),
'total_size': stat_line_log.group('total_size')
}
})
continue
stat1_line_log_v = stat1_line_log_v_re.match(line)
if stat1_line_log_v:
summary = {
summary.update({
'type': 'summary',
'date': stat1_line_log_v.group('date'),
'time': stat1_line_log_v.group('time'),
@@ -462,7 +483,7 @@ def parse(
'hash_hits': stat1_line_log_v.group('hash_hits'),
'false_alarms': stat1_line_log_v.group('false_alarms'),
'data': stat1_line_log_v.group('data')
}
})
continue
stat2_line_log_v = stat2_line_log_v_re.match(line)
@@ -478,6 +499,61 @@ def parse(
summary['speedup'] = stat3_line_log_v.group('speedup')
continue
# extra stats lines when using rsync --stats or --info=stats[1-3]
stat_ex_files_number_v = stat_ex_files_number_re.match(line)
if stat_ex_files_number_v:
summary['total_files'] = stat_ex_files_number_v.group('files_total')
summary['regular_files'] = stat_ex_files_number_v.group('files_regular')
summary['dir_files'] = stat_ex_files_number_v.group('files_dir')
continue
stat_ex_files_created_v = stat_ex_files_created_re.match(line)
if stat_ex_files_created_v:
summary['total_created_files'] = stat_ex_files_created_v.group('files_created_total')
summary['created_regular_files'] = stat_ex_files_created_v.group('files_created_regular')
summary['created_dir_files'] = stat_ex_files_created_v.group('files_created_dir')
continue
stat_ex_files_deleted_v = stat_ex_files_deleted_re.match(line)
if stat_ex_files_deleted_v:
summary['deleted_files'] = stat_ex_files_deleted_v.group('files_deleted')
continue
stat_ex_files_transferred_v = stat_ex_files_transferred_re.match(line)
if stat_ex_files_transferred_v:
summary['transferred_files'] = stat_ex_files_transferred_v.group('files_transferred')
continue
stat_ex_files_transferred_size_v = stat_ex_files_transferred_size_re.match(line)
if stat_ex_files_transferred_size_v:
summary['transferred_file_size'] = stat_ex_files_transferred_size_v.group('files_transferred_size')
continue
stat_ex_literal_data_v = stat_ex_literal_data_re.match(line)
if stat_ex_literal_data_v:
summary['literal_data'] = stat_ex_literal_data_v.group('literal_data')
continue
stat_ex_matched_data_v = stat_ex_matched_data_re.match(line)
if stat_ex_matched_data_v:
summary['matched_data'] = stat_ex_matched_data_v.group('matched_data')
continue
stat_ex_file_list_size_v = stat_ex_file_list_size_re.match(line)
if stat_ex_file_list_size_v:
summary['file_list_size'] = stat_ex_file_list_size_v.group('file_list_size')
continue
stat_ex_file_list_generation_time_v = stat_ex_file_list_generation_time_re.match(line)
if stat_ex_file_list_generation_time_v:
summary['file_list_generation_time'] = stat_ex_file_list_generation_time_v.group('file_list_generation_time')
continue
stat_ex_file_list_transfer_time_v = stat_ex_file_list_transfer_time_re.match(line)
if stat_ex_file_list_transfer_time_v:
summary['file_list_transfer_time'] = stat_ex_file_list_transfer_time_v.group('file_list_transfer_time')
continue
except Exception as e:
yield raise_or_yield(ignore_exceptions, e, line)
@@ -488,3 +564,6 @@ def parse(
except Exception as e:
yield raise_or_yield(ignore_exceptions, e, '')
# unused return for Mypy
return []

View File

@@ -45,23 +45,31 @@ All `-` values are converted to `null`
"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]
"mem_unit": string,
"mem_total": float,
"mem_free": float,
"mem_used": float,
"mem_buff_cache": float,
"swap_unit": string,
"swap_total": float,
"swap_free": float,
"swap_used": float,
"mem_available": float,
"processes": [
{
"pid": integer,
"user": string,
"priority": integer,
"nice": integer,
"virtual_mem": float, # [1]
"resident_mem": float, # [1]
"shared_mem": float, # [1]
"virtual_mem": float,
"virtual_mem_bytes": integer,
"virtual_mem_unit": string,
"resident_mem": float,
"resident_mem_bytes": integer,
"resident_mem_unit": string,
"shared_mem": float,
"shared_mem_bytes": integer,
"shared_mem_unit": string,
"status": string,
"percent_cpu": float,
"percent_mem": float,
@@ -82,9 +90,15 @@ All `-` values are converted to `null`
"thread_count": integer,
"last_used_processor": integer,
"time": string,
"swap": float, # [1]
"code": float, # [1]
"data": float, # [1]
"swap": float,
"swap_bytes": integer,
"swap_unit": string,
"code": float,
"code_bytes": integer,
"code_unit": string,
"data": float,
"data_bytes": integer,
"data_unit": string,
"major_page_fault_count": integer,
"minor_page_fault_count": integer,
"dirty_pages_count": integer,
@@ -103,7 +117,9 @@ All `-` values are converted to `null`
]
"major_page_fault_count_delta": integer,
"minor_page_fault_count_delta": integer,
"used": float, # [1]
"used": float,
"used_bytes": integer,
"used_unit": string,
"ipc_namespace_inode": integer,
"mount_namespace_inode": integer,
"net_namespace_inode": integer,
@@ -124,9 +140,6 @@ All `-` values are converted to `null`
}
]
[0] Values are in the units output by `top`
[1] Unit suffix stripped during float conversion
Examples:
$ top -b -n 3 | jc --top -p
@@ -316,7 +329,7 @@ from jc.parsers.universal import sparse_table_parse as parse_table
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.2'
version = '1.3'
description = '`top -b` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -440,13 +453,25 @@ def _process(proc_data: List[Dict], quiet=False) -> List[Dict]:
'mem_available', 'virtual_mem', 'resident_mem', 'shared_mem', 'swap', 'code', 'data', 'used'
}
bytes_list: Set = {
'mem_total', 'mem_free', 'mem_used', 'mem_available', 'mem_buff_cache',
'swap_total', 'swap_free', 'swap_used', 'virtual_mem', 'resident_mem',
'shared_mem', 'swap', 'code', 'data', 'used'
}
for idx, item in enumerate(proc_data):
for key in item:
for key in item.copy():
# 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 bytes_list:
if key.startswith('mem_'):
item[key + '_bytes'] = jc.utils.convert_size_to_int(item[key] + item['mem_unit'])
if key.startswith('swap_'):
item[key + '_bytes'] = jc.utils.convert_size_to_int(item[key] + item['swap_unit'])
if key in int_list:
item[key] = jc.utils.convert_to_int(item[key])
@@ -463,7 +488,8 @@ def _process(proc_data: List[Dict], quiet=False) -> List[Dict]:
jc.utils.warning_message([f'Unknown field detected at item[{idx}]["processes"]: {old_key}'])
# cleanup values
for key in proc.keys():
proc_copy = proc.copy()
for key in proc_copy.keys():
# set dashes to nulls
if proc[key] == '-':
@@ -482,6 +508,13 @@ def _process(proc_data: List[Dict], quiet=False) -> List[Dict]:
# do int/float conversions for the process objects
if proc[key]:
if key in bytes_list:
if proc[key][-1] not in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'):
proc[key + '_unit'] = proc[key][-1]
else:
proc[key + '_unit'] = 'b'
proc[key + '_bytes'] = jc.utils.convert_size_to_int(proc[key], posix_mode=True)
if key in int_list:
proc[key] = jc.utils.convert_to_int(proc[key])
@@ -604,6 +637,7 @@ def parse(
line_list = line.split()
item_obj.update(
{
'mem_unit': line_list[0],
'mem_total': line_list[3],
'mem_free': line_list[5],
'mem_used': line_list[7],
@@ -617,6 +651,7 @@ def parse(
line_list = line.split()
item_obj.update(
{
'swap_unit': line_list[0],
'swap_total': line_list[2],
'swap_free': line_list[4],
'swap_used': line_list[6],

View File

@@ -43,23 +43,39 @@ Schema:
"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]
"mem_unit": string,
"swap_unit": string,
"mem_total": float,
"mem_total_bytes": integer,
"mem_free": float,
"mem_free_bytes": integer,
"mem_used": float,
"mem_used_bytes": integer,
"mem_buff_cache": float,
"mem_buff_cache_bytes": integer,
"swap_total": float,
"swap_total_bytes": integer,
"swap_free": float,
"swap_free_bytes": integer,
"swap_used": float,
"swap_used_bytes": integer,
"mem_available": float,
"mem_available_bytes": integer,
"processes": [
{
"pid": integer,
"user": string,
"priority": integer,
"nice": integer,
"virtual_mem": float, # [1]
"resident_mem": float, # [1]
"shared_mem": float, # [1]
"virtual_mem": float,
"virtual_mem_unit": string,
"virtual_mem_bytes": integer,
"resident_mem": float,
"resident_mem_unit": string,
"resident_mem_bytes": integer,
"shared_mem": float,
"shared_mem_unit": string,
"shared_mem_bytes": integer,
"status": string,
"percent_cpu": float,
"percent_mem": float,
@@ -80,9 +96,15 @@ Schema:
"thread_count": integer,
"last_used_processor": integer,
"time": string,
"swap": float, # [1]
"code": float, # [1]
"data": float, # [1]
"swap": float,
"swap_unit": string,
"swap_bytes": integer,
"code": float,
"code_unit": string,
"code_bytes": integer
"data": float,
"data_unit": string,
"data_bytes": integer,
"major_page_fault_count": integer,
"minor_page_fault_count": integer,
"dirty_pages_count": integer,
@@ -101,7 +123,9 @@ Schema:
]
"major_page_fault_count_delta": integer,
"minor_page_fault_count_delta": integer,
"used": float, # [1]
"used": float,
"used_unit": string,
"used_bytes": integer,
"ipc_namespace_inode": integer,
"mount_namespace_inode": integer,
"net_namespace_inode": integer,
@@ -128,9 +152,6 @@ Schema:
}
}
[0] Values are in the units output by `top`
[1] Unit suffix stripped during float conversion
Examples:
$ top -b | jc --top-s
@@ -153,7 +174,7 @@ from jc.parsers.universal import sparse_table_parse as parse_table
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.2'
version = '1.3'
description = '`top -b` command streaming parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -277,12 +298,24 @@ def _process(proc_data: Dict, idx=0, quiet=False) -> Dict:
'mem_available', 'virtual_mem', 'resident_mem', 'shared_mem', 'swap', 'code', 'data', 'used'
}
for key in proc_data:
bytes_list: Set = {
'mem_total', 'mem_free', 'mem_used', 'mem_available', 'mem_buff_cache',
'swap_total', 'swap_free', 'swap_used', 'virtual_mem', 'resident_mem',
'shared_mem', 'swap', 'code', 'data', 'used'
}
for key in proc_data.copy():
# 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 bytes_list:
if key.startswith('mem_'):
proc_data[key + '_bytes'] = jc.utils.convert_size_to_int(proc_data[key] + proc_data['mem_unit'])
if key.startswith('swap_'):
proc_data[key + '_bytes'] = jc.utils.convert_size_to_int(proc_data[key] + proc_data['swap_unit'])
if key in int_list:
proc_data[key] = jc.utils.convert_to_int(proc_data[key])
@@ -299,7 +332,8 @@ def _process(proc_data: Dict, idx=0, quiet=False) -> Dict:
jc.utils.warning_message([f'Unknown field detected at item[{idx}]["processes"]: {old_key}'])
# cleanup values
for key in proc.keys():
proc_copy = proc.copy()
for key in proc_copy.keys():
# set dashes to nulls
if proc[key] == '-':
@@ -318,6 +352,13 @@ def _process(proc_data: Dict, idx=0, quiet=False) -> Dict:
# do int/float conversions for the process objects
if proc[key]:
if key in bytes_list:
if proc[key][-1] not in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'):
proc[key + '_unit'] = proc[key][-1]
else:
proc[key + '_unit'] = 'b'
proc[key + '_bytes'] = jc.utils.convert_size_to_int(proc[key], posix_mode=True)
if key in int_list:
proc[key] = jc.utils.convert_to_int(proc[key])
@@ -448,6 +489,7 @@ def parse(
line_list = line.split()
output_line.update(
{
'mem_unit': line_list[0],
'mem_total': line_list[3],
'mem_free': line_list[5],
'mem_used': line_list[7],
@@ -461,6 +503,7 @@ def parse(
line_list = line.split()
output_line.update(
{
'swap_unit': line_list[0],
'swap_total': line_list[2],
'swap_free': line_list[4],
'swap_used': line_list[6],
@@ -489,3 +532,5 @@ def parse(
if process_list:
output_line['processes'] = parse_table(process_list)
yield output_line if raw else _process(output_line, idx=idx, quiet=quiet)
return None

View File

@@ -27,6 +27,8 @@ Schema:
{
"destination_ip": string,
"destination_name": string,
"max_hops": integer,
"data_bytes": integer,
"hops": [
{
"hop": integer,
@@ -49,6 +51,8 @@ Examples:
{
"destination_ip": "216.58.194.46",
"destination_name": "google.com",
"max_hops": 64,
"data_bytes": 50,
"hops": [
{
"hop": 1,
@@ -84,6 +88,8 @@ Examples:
{
"destination_ip": "216.58.194.46",
"destination_name": "google.com",
"max_hops": "64",
"data_bytes": "50",
"hops": [
{
"hop": "1",
@@ -119,11 +125,12 @@ import re
from decimal import Decimal
import jc.utils
from copy import deepcopy
from jc.exceptions import ParseError
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.8'
version = '1.9'
description = '`traceroute` and `traceroute6` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -164,7 +171,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
'''
RE_HEADER = re.compile(r'(\S+)\s+\((\d+\.\d+\.\d+\.\d+|[0-9a-fA-F:]+)\)')
RE_HEADER = re.compile(r'traceroute6? to (\S+)\s+\((\d+\.\d+\.\d+\.\d+|[0-9a-fA-F:]+)\)')
RE_HEADER_HOPS_BYTES = re.compile(r'(\d+) hops max, (\d+) byte packets')
RE_PROBE_NAME_IP = re.compile(r'(\S+)\s+\((\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[0-9a-fA-F:]+)\)+')
RE_PROBE_IP_ONLY = re.compile(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+([^\(])')
RE_PROBE_IPV6_ONLY = re.compile(r'(([a-f0-9]*:)+[a-f0-9]+)')
@@ -175,9 +183,11 @@ RE_PROBE_RTT_ANNOTATION = re.compile(r'(?:(\d+(?:\.?\d+)?)\s+ms|(\s+\*\s+))\s*(!
class _Traceroute(object):
def __init__(self, dest_name, dest_ip):
def __init__(self, dest_name, dest_ip, max_hops=None, data_bytes=None):
self.dest_name = dest_name
self.dest_ip = dest_ip
self.max_hops = max_hops
self.data_bytes = data_bytes
self.hops = []
def add_hop(self, hop):
@@ -291,8 +301,23 @@ def _get_probes(hop_string: str):
return probes
def _loads(data):
lines = data.splitlines()
def _loads(data: str, quiet: bool):
lines = []
# remove any warning lines
for data_line in data.splitlines():
if 'traceroute: Warning: ' not in data_line and 'traceroute6: Warning: ' not in data_line:
lines.append(data_line)
else:
continue
# check if header row exists, otherwise add a dummy header
if not lines[0].startswith('traceroute to ') and not lines[0].startswith('traceroute6 to '):
lines[:0] = ['traceroute to <<_>> (<<_>>), ? hops max, ? byte packets']
# print warning to STDERR
if not quiet:
jc.utils.warning_message(['No header row found. For destination info redirect STDERR to STDOUT'])
# Get headers
match_dest = RE_HEADER.search(lines[0])
@@ -301,8 +326,15 @@ def _loads(data):
dest_name = match_dest.group(1)
dest_ip = match_dest.group(2)
m = RE_HEADER_HOPS_BYTES.search(lines[0])
max_hops = None
data_bytes = None
if m:
max_hops = m.group(1)
data_bytes = m.group(2)
# The Traceroute node is the root of the tree
traceroute = _Traceroute(dest_name, dest_ip)
traceroute = _Traceroute(dest_name, dest_ip, max_hops, data_bytes)
# Parse the remaining lines, they should be only hops/probes
for line in lines[1:]:
@@ -312,16 +344,17 @@ def _loads(data):
hop_match = RE_HOP.match(line)
if hop_match.group(1):
hop_index = int(hop_match.group(1))
else:
hop_index = None
if hop_match:
if hop_match.group(1):
hop_index = int(hop_match.group(1))
else:
hop_index = None
if hop_index is not None:
hop = _Hop(hop_index)
traceroute.add_hop(hop)
if hop_index is not None:
hop = _Hop(hop_index)
traceroute.add_hop(hop)
hop_string = hop_match.group(2)
hop_string = hop_match.group(2)
probes = _get_probes(hop_string)
for probe in probes:
@@ -330,11 +363,25 @@ def _loads(data):
return traceroute
class ParseError(Exception):
pass
def _serialize_hop(hop: _Hop):
hop_obj = {}
hop_obj['hop'] = str(hop.idx)
probe_list = []
if hop.probes:
for probe in hop.probes:
probe_obj = {
'annotation': probe.annotation,
'asn': None if probe.asn is None else str(probe.asn),
'ip': probe.ip,
'name': probe.name,
'rtt': None if probe.rtt is None else str(probe.rtt)
}
probe_list.append(probe_obj)
########################################################################################
hop_obj['probes'] = probe_list
return hop_obj
def _process(proc_data):
@@ -349,26 +396,20 @@ def _process(proc_data):
Dictionary. Structured to conform to the schema.
"""
int_list = {'hop', 'asn'}
int_list = {'hop', 'asn', 'max_hops', 'data_bytes'}
float_list = {'rtt'}
if 'hops' in proc_data:
for entry in proc_data['hops']:
for key in entry:
if key in int_list:
entry[key] = jc.utils.convert_to_int(entry[key])
for entry in proc_data.get('hops', []):
_process(entry)
for entry in proc_data.get('probes', []):
_process(entry)
if key in float_list:
entry[key] = jc.utils.convert_to_float(entry[key])
for key in proc_data:
if key in int_list:
proc_data[key] = jc.utils.convert_to_int(proc_data[key])
if 'probes' in entry:
for item in entry['probes']:
for key in item:
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])
if key in float_list:
proc_data[key] = jc.utils.convert_to_float(proc_data[key])
return proc_data
@@ -393,52 +434,17 @@ def parse(data, raw=False, quiet=False):
raw_output = {}
if jc.utils.has_data(data):
# remove any warning lines
new_data = []
for data_line in data.splitlines():
if 'traceroute: Warning: ' not in data_line and 'traceroute6: Warning: ' not in data_line:
new_data.append(data_line)
else:
continue
# check if header row exists, otherwise add a dummy header
if not new_data[0].startswith('traceroute to ') and not new_data[0].startswith('traceroute6 to '):
new_data[:0] = ['traceroute to <<_>> (<<_>>), 30 hops max, 60 byte packets']
# print warning to STDERR
if not quiet:
jc.utils.warning_message(['No header row found. For destination info redirect STDERR to STDOUT'])
data = '\n'.join(new_data)
tr = _loads(data)
hops = tr.hops
tr = _loads(data, quiet)
hops_list = []
if hops:
for hop in hops:
hop_obj = {}
hop_obj['hop'] = str(hop.idx)
probe_list = []
if hop.probes:
for probe in hop.probes:
probe_obj = {
'annotation': probe.annotation,
'asn': None if probe.asn is None else str(probe.asn),
'ip': probe.ip,
'name': probe.name,
'rtt': None if probe.rtt is None else str(probe.rtt)
}
probe_list.append(probe_obj)
hop_obj['probes'] = probe_list
hops_list.append(hop_obj)
for hop in tr.hops:
hops_list.append(_serialize_hop(hop))
raw_output = {
'destination_ip': tr.dest_ip,
'destination_name': tr.dest_name,
'max_hops': tr.max_hops,
'data_bytes': tr.data_bytes,
'hops': hops_list
}

277
jc/parsers/traceroute_s.py Normal file
View File

@@ -0,0 +1,277 @@
r"""jc - JSON Convert `traceroute` command output streaming parser
> This streaming parser outputs JSON Lines (cli) or returns an Iterable of
> Dictionaries (module)
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-s`
Usage (cli):
$ traceroute 1.2.3.4 | jc --traceroute-s
Usage (module):
import jc
result = jc.parse('traceroute_s', traceroute_command_output.splitlines())
for item in result:
# do something
Schema:
{
# 'header' or 'hop'
"type": string,
# 'header' type has the fields below:
"destination_ip": string,
"destination_name": string,
"max_hops": integer,
"data_bytes": integer,
# 'hop' type has the fields below:
"hop": integer,
"probes": [
{
"annotation": string,
"asn": integer,
"ip": string,
"name": string,
"rtt": float
}
]
# 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
}
}
Examples:
$ traceroute google.com | jc --traceroute-s -p
{
"type": "header",
"destination_ip": "216.58.194.46",
"destination_name": "google.com",
"max_hops": 30,
"data_bytes": 60
}
{
"type": "hop",
"hop": 1,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": 198.574
},
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": null
},
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": 198.65
}
]
}
...
$ traceroute google.com | jc --traceroute-s -p -r
{
"type": "header",
"destination_ip": "216.58.194.46",
"destination_name": "google.com",
"max_hops": "30",
"data_bytes": "60"
}
{
"type": "hop",
"hop": "1",
"probes": [
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": "198.574"
},
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": null
},
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": "198.650"
}
]
}
...
"""
from typing import Optional
import jc.utils
from jc.exceptions import ParseError
from jc.streaming import (
add_jc_meta, streaming_input_type_check, streaming_line_input_type_check, raise_or_yield
)
from .traceroute import RE_HEADER, RE_HOP, RE_HEADER_HOPS_BYTES, _Hop, _loads, _process, _serialize_hop
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = '`traceroute` and `traceroute6` command streaming parser'
author = 'Shintaro Kojima'
author_email = 'goodies@codeout.net'
compatible = ['linux', 'darwin', 'freebsd']
tags = ['command']
streaming = True
__version__ = info.version
'''
Copyright (C) 2015 Luis Benitez
Parses the output of a traceroute execution into an AST (Abstract Syntax Tree).
The MIT License (MIT)
Copyright (c) 2014 Luis Benitez
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
'''
def _hop_output(hop: _Hop, raw: bool):
raw_output = {
'type': 'hop',
**_serialize_hop(hop),
}
return raw_output if raw else _process(raw_output)
@add_jc_meta
def parse(data, raw=False, quiet=False, ignore_exceptions=False):
"""
Main text parsing 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)
# Estimated number of probe packets per hop. See `traceroute -q` on Linux, for example.
queries = 0
# Accumulated hop across multiple lines
hop_cache: Optional[_Hop] = None
for line in data: # type: str
try:
streaming_line_input_type_check(line)
if RE_HEADER.search(line):
tr = _loads(line, quiet)
raw_output = {
'type': 'header',
'destination_ip': tr.dest_ip,
'destination_name': tr.dest_name,
'max_hops': tr.max_hops,
'data_bytes': tr.data_bytes
}
yield raw_output if raw else _process(raw_output)
else:
m = RE_HOP.match(line)
if not m:
continue
# A single hop can wrap across multiple lines, e.g.:
#
# 6 [AS0] 94.142.122.45 (94.142.122.45) 42.790 ms 46.352 ms
# [AS0] 94.142.122.44 (94.142.122.44) 41.479 ms
#
if not m.group(1):
if not hop_cache:
raise ParseError('No hop index found')
# If the hop index is not found, prepend the hop index (6) to the following lines before parsing.
line = f"{hop_cache.idx} {line}"
# Specify quiet=True to suppress the 'No header row found' warning for hop lines
tr = _loads(line, quiet=True)
if not tr.hops:
continue
hop_cache.probes.extend(tr.hops[0].probes)
else:
# if the hop index is found, yield the previous hop
if hop_cache:
yield _hop_output(hop_cache, raw)
hop_cache = None
# Specify quiet=True to suppress the 'No header row found' warning for hop lines
tr = _loads(line, quiet=True)
if not tr.hops:
continue
hop_cache = tr.hops[0]
except Exception as e:
yield raise_or_yield(ignore_exceptions, e, line)
if hop_cache:
yield _hop_output(hop_cache, raw)

335
jc/parsers/typeset.py Normal file
View File

@@ -0,0 +1,335 @@
r"""jc - JSON Convert `typeset` and `declare` Bash internal command output parser
Convert `typeset` and `declare` bash internal commands with no options or the
following: `-a`, `-A`, `-i`, `-l`, `-p`, `-r`, `-u`, and `-x`
Note: function parsing is not supported (e.g. `-f` or `-F`)
Usage (cli):
$ typeset | jc --typeset
Usage (module):
import jc
result = jc.parse('typeset', typeset_command_output)
Schema:
[
{
"name": string,
"value": string/integer/array/object/null, # [0]
"type": string, # [1]
"readonly": boolean/null,
"integer": boolean/null,
"lowercase": boolean/null,
"uppercase": boolean/null,
"exported": boolean/null
}
]
Key/value pairs other than `name`, `value`, and `type` will only be non-null
when the information is available from the `typeset` or `declare` output.
If declare options are not given to `jc` within the `typeset` output, then
it will assume all arrays are simple `array` type.
[0] Based on type. `variable` type is null if not set, a string when the
bash variable is set unless the `integer` field is set to `True`, then
the type is integer. `array` type is an array of strings or integers as
above. `associative` type is an object of key/value pairs where values
are strings or integers as above. Objects have the schema of:
{
"<key1>": string/integer,
"<key2>": string/integer
}
[1] Possible values: `variable`, `array`, or `associative`
Examples:
$ typeset -p | jc --typeset -p
[
{
"name": "associative_array",
"value": {
"key2": "abc",
"key3": "1 2 3",
"key1": "hello \"world\""
},
"type": "associative",
"readonly": false,
"integer": false,
"lowercase": false,
"uppercase": false,
"exported": false
},
{
"name": "integers_associative_array",
"value": {
"one": 1,
"two": 500,
"three": 999
},
"type": "associative",
"readonly": false,
"integer": true,
"lowercase": false,
"uppercase": false,
"exported": false
}
]
$ typeset -p | jc --typeset -p -r
[
{
"name": "associative_array",
"value": {
"key2": "abc",
"key3": "1 2 3",
"key1": "hello \"world\""
},
"type": "associative",
"readonly": false,
"integer": false,
"lowercase": false,
"uppercase": false,
"exported": false
},
{
"name": "integers_associative_array",
"value": {
"one": "1",
"two": "500",
"three": "999"
},
"type": "associative",
"readonly": false,
"integer": true,
"lowercase": false,
"uppercase": false,
"exported": false
}
]
"""
import shlex
import re
from typing import List, Dict
from jc.jc_types import JSONDictType
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = '`typeset` and `declare` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['command']
__version__ = info.version
VAR_DEF_PATTERN = re.compile(r'(?P<name>[a-zA-Z_][a-zA-Z0-9_]*)=(?P<val>[^(][^[].+)$')
SIMPLE_ARRAY_DEF_PATTERN = re.compile(r'(?P<name>[a-zA-Z_][a-zA-Z0-9_]*)=(?P<body>\(\[\d+\]=.+\))$')
ASSOCIATIVE_ARRAY_DEF_PATTERN = re.compile(r'(?P<name>[a-zA-Z_][a-zA-Z0-9_]*)=(?P<body>\(\[[a-zA-Z_][a-zA-Z0-9_]*\]=.+\))$')
EMPTY_ARRAY_DEF_PATTERN = re.compile(r'(?P<name>[a-zA-Z_][a-zA-Z0-9_]*)=\(\)$')
EMPTY_VAR_DEF_PATTERN = re.compile(r'declare\s.+\s(?P<name>[a-zA-Z_][a-zA-Z0-9_]*)$')
DECLARE_OPTS_PATTERN = re.compile(r'declare\s(?P<options>.+?)\s[a-zA-Z_][a-zA-Z0-9_]*')
def _process(proc_data: List[JSONDictType]) -> List[JSONDictType]:
"""
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.
"""
for item in proc_data:
if item['type'] == 'variable' and item['integer']:
item['value'] = jc.utils.convert_to_int(item['value'])
elif item['type'] == 'array' and item['integer'] \
and isinstance(item['value'], list):
new_num_list = []
for number in item['value']:
new_num_list.append(jc.utils.convert_to_int(number))
item['value'] = new_num_list
elif (item['type'] == 'array' and item['integer'] \
and isinstance(item['value'], dict)) \
or (item['type'] == 'associative' and item['integer']):
new_num_dict: Dict[str, int] = {}
for key, val in item['value'].items():
new_num_dict.update({key: jc.utils.convert_to_int(val)})
item['value'] = new_num_dict
return proc_data
def _get_simple_array_vals(body: str) -> List[str]:
body = _remove_bookends(body)
body_split = shlex.split(body)
values = []
for item in body_split:
_, val = item.split('=', maxsplit=1)
values.append(_remove_quotes(val))
return values
def _get_associative_array_vals(body: str) -> Dict[str, str]:
body = _remove_bookends(body)
body_split = shlex.split(body)
values: Dict = {}
for item in body_split:
key, val = item.split('=', maxsplit=1)
key = _remove_bookends(key, '[', ']')
values.update({key: val})
return values
def _get_declare_options(line: str, type_hint: str = 'variable') -> Dict:
opts = {
'type': type_hint,
'readonly': None,
'integer': None,
'lowercase': None,
'uppercase': None,
'exported': None
}
opts_map = {
'r': 'readonly',
'i': 'integer',
'l': 'lowercase',
'u': 'uppercase',
'x': 'exported'
}
declare_opts_match = re.match(DECLARE_OPTS_PATTERN, line)
if declare_opts_match:
for opt in declare_opts_match['options']:
if opt in opts_map:
opts[opts_map[opt]] = True
continue
if 'a' in declare_opts_match['options']:
opts['type'] = 'array'
elif 'A' in declare_opts_match['options']:
opts['type'] = 'associative'
# flip all remaining Nones to False
for option in opts.items():
key, val = option
if val is None:
opts[key] = False
return opts
def _remove_bookends(data: str, start_char: str = '(', end_char: str = ')') -> str:
if data.startswith(start_char) and data.endswith(end_char):
return data[1:-1]
return data
def _remove_quotes(data: str, remove_char: str ='"') -> str:
if data.startswith(remove_char) and data.endswith(remove_char):
return data[1:-1]
return data
def parse(
data: str,
raw: bool = False,
quiet: bool = False
) -> List[JSONDictType]:
"""
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[Dict] = []
if jc.utils.has_data(data):
for line in filter(None, data.splitlines()):
item = {
"name": '',
"value": '',
"type": None,
"readonly": None,
"integer": None,
"lowercase": None,
"uppercase": None,
"exported": None
}
# regular variable
var_def_match = re.search(VAR_DEF_PATTERN, line)
if var_def_match:
item['name'] = var_def_match['name']
item['value'] = _remove_quotes(var_def_match['val'])
item.update(_get_declare_options(line, 'variable'))
raw_output.append(item)
continue
# empty variable
empty_var_def_match = re.search(EMPTY_VAR_DEF_PATTERN, line)
if empty_var_def_match:
item['name'] = empty_var_def_match['name']
item['value'] = None
item.update(_get_declare_options(line, 'variable'))
raw_output.append(item)
continue
# simple array
simple_arr_def_match = re.search(SIMPLE_ARRAY_DEF_PATTERN, line)
if simple_arr_def_match:
item['name'] = simple_arr_def_match['name']
item['value'] = _get_simple_array_vals(simple_arr_def_match['body'])
item.update(_get_declare_options(line, 'array'))
raw_output.append(item)
continue
# associative array
associative_arr_def_match = re.search(ASSOCIATIVE_ARRAY_DEF_PATTERN, line)
if associative_arr_def_match:
item['name'] = associative_arr_def_match['name']
item['value'] = _get_associative_array_vals(associative_arr_def_match['body'])
item.update(_get_declare_options(line, 'associative'))
raw_output.append(item)
continue
# empty array
empty_arr_def_match = re.search(EMPTY_ARRAY_DEF_PATTERN, line)
if empty_arr_def_match:
item['name'] = empty_arr_def_match['name']
item['value'] = []
item.update(_get_declare_options(line, 'array'))
raw_output.append(item)
continue
return raw_output if raw else _process(raw_output)

View File

@@ -25,6 +25,7 @@ Schema:
"user": string,
"event": string,
"writeable_tty": string,
"process": string,
"tty": string,
"time": string,
"epoch": integer, # [0]
@@ -136,7 +137,7 @@ import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.8'
version = '1.9'
description = '`who` command parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
@@ -254,6 +255,12 @@ def parse(data, raw=False, quiet=False):
raw_output.append(output_line)
continue
# some output contains process name between the username and pts
# pull the process name for use later if we can find it
user_process = None
if re.match(r'^\S+\s+[^ +-]+\s+pts\/\d+\s', line):
user_process = linedata.pop(1)
# user logins
output_line['user'] = linedata.pop(0)
@@ -262,6 +269,9 @@ def parse(data, raw=False, quiet=False):
output_line['tty'] = linedata.pop(0)
if user_process:
output_line['process'] = user_process
# mac
if re.match(r'[JFMASOND][aepuco][nbrynlgptvc]', linedata[0]):
output_line['time'] = ' '.join([linedata.pop(0),

333
jc/parsers/x509_crl.py Normal file
View File

@@ -0,0 +1,333 @@
r"""jc - JSON Convert X.509 Certificate Revocation List format file parser
This parser will convert DER and PEM encoded X.509 certificate revocation
list files.
Usage (cli):
$ cat certificateRevocationList.pem | jc --x509-crl
$ cat certificateRevocationList.der | jc --x509-crl
Usage (module):
import jc
result = jc.parse('x509_crl', x509_crl_file_output)
Schema:
{
"tbs_cert_list": {
"version": string,
"signature": {
"algorithm": string,
"parameters": string/null
},
"issuer": {
"organization_name": string,
"organizational_unit_name": string,
"common_name": string
},
"this_update": integer, # [1]
"next_update": integer, # [1]
"revoked_certificates": [
{
"user_certificate": integer,
"revocation_date": integer, # [1]
"crl_entry_extensions": [
{
"extn_id": string,
"critical": boolean,
"extn_value": string,
"extn_value_iso": string
},
"revocation_date_iso": string
}
],
"crl_extensions": [
{
"extn_id": string,
"critical": boolean,
"extn_value": array/object/string/integer # [2]
}
],
"this_update_iso": string,
"next_update_iso": string
},
"signature_algorithm": {
"algorithm": string,
"parameters": string/null
},
"signature": string # [0]
}
[0] in colon-delimited hex notation
[1] time-zone-aware (UTC) epoch timestamp
[2] See below for well-known Extension schemas:
Basic Constraints:
{
"extn_id": "basic_constraints",
"critical": boolean,
"extn_value": {
"ca": boolean,
"path_len_constraint": string/null
}
}
Key Usage:
{
"extn_id": "key_usage",
"critical": boolean,
"extn_value": [
string
]
}
Key Identifier:
{
"extn_id": "key_identifier",
"critical": boolean,
"extn_value": string # [0]
}
Authority Key Identifier:
{
"extn_id": "authority_key_identifier",
"critical": boolean,
"extn_value": {
"key_identifier": string, # [0]
"authority_cert_issuer": string/null,
"authority_cert_serial_number": string/null
}
}
Subject Alternative Name:
{
"extn_id": "subject_alt_name",
"critical": boolean,
"extn_value": [
string
]
}
Certificate Policies:
{
"extn_id": "certificate_policies",
"critical": boolean,
"extn_value": [
{
"policy_identifier": string,
"policy_qualifiers": [ array or null
{
"policy_qualifier_id": string,
"qualifier": string
}
]
}
]
}
Signed Certificate Timestamp List:
{
"extn_id": "signed_certificate_timestamp_list",
"critical": boolean,
"extn_value": string # [0]
}
Examples:
$ cat sample-crl.pem | jc --x509-crl -p
{
"tbs_cert_list": {
"version": "v2",
"signature": {
"algorithm": "sha1_rsa",
"parameters": null
},
"issuer": {
"organization_name": "Sample Signer Organization",
"organizational_unit_name": "Sample Signer Unit",
"common_name": "Sample Signer Cert"
},
"this_update": 1361183520,
"next_update": 1361184120,
"revoked_certificates": [
{
"user_certificate": 1341767,
"revocation_date": 1361182932,
"crl_entry_extensions": [
{
"extn_id": "crl_reason",
"critical": false,
"extn_value": "affiliation_changed"
},
{
"extn_id": "invalidity_date",
"critical": false,
"extn_value": 1361182920,
"extn_value_iso": "2013-02-18T10:22:00+00:00"
}
],
"revocation_date_iso": "2013-02-18T10:22:12+00:00"
},
{
"user_certificate": 1341768,
"revocation_date": 1361182942,
"crl_entry_extensions": [
{
"extn_id": "crl_reason",
"critical": false,
"extn_value": "certificate_hold"
},
{
"extn_id": "invalidity_date",
"critical": false,
"extn_value": 1361182920,
"extn_value_iso": "2013-02-18T10:22:00+00:00"
}
],
"revocation_date_iso": "2013-02-18T10:22:22+00:00"
},
{
"user_certificate": 1341769,
"revocation_date": 1361182952,
"crl_entry_extensions": [
{
"extn_id": "crl_reason",
"critical": false,
"extn_value": "superseded"
},
{
"extn_id": "invalidity_date",
"critical": false,
"extn_value": 1361182920,
"extn_value_iso": "2013-02-18T10:22:00+00:00"
}
],
"revocation_date_iso": "2013-02-18T10:22:32+00:00"
},
{
"user_certificate": 1341770,
"revocation_date": 1361182962,
"crl_entry_extensions": [
{
"extn_id": "crl_reason",
"critical": false,
"extn_value": "key_compromise"
},
{
"extn_id": "invalidity_date",
"critical": false,
"extn_value": 1361182920,
"extn_value_iso": "2013-02-18T10:22:00+00:00"
}
],
"revocation_date_iso": "2013-02-18T10:22:42+00:00"
},
{
"user_certificate": 1341771,
"revocation_date": 1361182971,
"crl_entry_extensions": [
{
"extn_id": "crl_reason",
"critical": false,
"extn_value": "cessation_of_operation"
},
{
"extn_id": "invalidity_date",
"critical": false,
"extn_value": 1361182920,
"extn_value_iso": "2013-02-18T10:22:00+00:00"
}
],
"revocation_date_iso": "2013-02-18T10:22:51+00:00"
}
],
"crl_extensions": [
{
"extn_id": "authority_key_identifier",
"critical": false,
"extn_value": {
"key_identifier": "be:12:01:cc:aa:ea:11:80:da:2e:ad:b2...",
"authority_cert_issuer": null,
"authority_cert_serial_number": null
}
},
{
"extn_id": "crl_number",
"critical": false,
"extn_value": 3
}
],
"this_update_iso": "2013-02-18T10:32:00+00:00",
"next_update_iso": "2013-02-18T10:42:00+00:00"
},
"signature_algorithm": {
"algorithm": "sha1_rsa",
"parameters": null
},
"signature": "42:21:be:81:f1:c3:79:76:66:5b:ce:21:13:8a:68:a..."
}
"""
from typing import List, Dict, Union
import jc.utils
from jc.parsers.asn1crypto import pem, crl, jc_global
from jc.parsers.x509_cert import _fix_objects
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = 'X.509 PEM and DER certificate revocation list file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
details = 'Using the asn1crypto library at https://github.com/wbond/asn1crypto/releases/tag/1.5.1'
compatible = ['linux', 'darwin', 'cygwin', 'win32', 'aix', 'freebsd']
tags = ['standard', 'file', 'string', 'binary']
__version__ = info.version
def parse(
data: Union[str, bytes],
raw: bool = False,
quiet: bool = False
) -> Dict:
"""
Main text parsing function
Parameters:
data: (string or bytes) text or binary 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_global.quiet = quiet # to inject quiet setting into asn1crypto library
raw_output: Dict = {}
if jc.utils.has_data(data):
# convert to bytes, if not already, for PEM detection since that's
# what pem.detect() needs. (cli.py will auto-convert to UTF-8 if it can)
try:
der_bytes = bytes(data, 'utf-8') # type: ignore
except TypeError:
der_bytes = data # type: ignore
if pem.detect(der_bytes):
for type_name, headers, der_bytes in pem.unarmor(der_bytes, multiple=True):
if type_name == 'X509 CRL':
crl_obj = crl.CertificateList.load(der_bytes)
break
else:
crl_obj = crl.CertificateList.load(der_bytes)
raw_output = _fix_objects(crl_obj.native)
return raw_output

View File

@@ -249,9 +249,6 @@ Examples:
}
]
"""
# import binascii
# from collections import OrderedDict
# from datetime import datetime
from typing import List, Dict, Union
import jc.utils
from jc.parsers.asn1crypto import pem, csr, jc_global

View File

@@ -1,7 +1,7 @@
"""jc - JSON Convert streaming utils"""
from functools import wraps
from typing import Dict, Tuple, Union, Iterable, Callable, TypeVar, cast, Any
from typing import Tuple, Union, Iterable, Callable, TypeVar, cast, Any
from .jc_types import JSONDictType
@@ -47,8 +47,9 @@ def stream_error(e: BaseException, line: str) -> JSONDictType:
def add_jc_meta(func: F) -> F:
"""
Decorator for streaming parsers to add stream_success and stream_error
objects. This simplifies the yield lines in the streaming parsers.
Decorator for streaming parsers to add `stream_success` and
`stream_error` objects. This simplifies the `yield` lines in the
streaming parsers.
With the decorator on parse():
@@ -82,7 +83,7 @@ def add_jc_meta(func: F) -> F:
successfully parse.
ignore_exceptions: (bool) continue processing lines and ignore
exceptions if True.
exceptions if `True`.
"""
@wraps(func)
def wrapper(*args, **kwargs):
@@ -109,8 +110,8 @@ def raise_or_yield(
line: str
) -> Tuple[BaseException, str]:
"""
Return the exception object and line string if ignore_exceptions is
True. Otherwise, re-raise the exception from the exception object with
Return the exception object and line string if `ignore_exceptions` is
`True`. Otherwise, re-raise the exception from the exception object with
an annotation.
"""
ignore_exceptions_msg = '... Use the ignore_exceptions option (-qq) to ignore streaming parser errors.'

View File

@@ -100,7 +100,7 @@ def error_message(message_lines: List[str]) -> None:
Returns:
None - just prints output to STDERR
None - just prints output to `STDERR`
"""
columns = shutil.get_terminal_size().columns
@@ -148,7 +148,7 @@ def compatibility(mod_name: str, compatible: List[str], quiet: bool = False) ->
the parser. compatible options:
linux, darwin, cygwin, win32, aix, freebsd
quiet: (bool) suppress compatibility message if True
quiet: (bool) suppress compatibility message if `True`
Returns:
@@ -169,7 +169,7 @@ def has_data(data: Union[str, bytes]) -> bool:
Checks if the string input contains data. If there are any
non-whitespace characters then return `True`, else return `False`.
For bytes, returns True if there is any data.
For bytes, returns `True` if there is any data.
Parameters:
@@ -177,9 +177,9 @@ def has_data(data: Union[str, bytes]) -> bool:
Returns:
Boolean True if input string (data) contains non-whitespace
characters, otherwise False. For bytes data, returns
True if there is any data, otherwise False.
Boolean `True` if input string (data) contains non-whitespace
characters, otherwise `False`. For bytes data, returns
`True` if there is any data, otherwise `False`.
"""
if isinstance(data, str):
return bool(data and not data.isspace())

View File

@@ -1,4 +1,4 @@
.TH jc 1 2025-05-10 1.25.5 "JSON Convert"
.TH jc 1 2025-10-12 1.25.6 "JSON Convert"
.SH NAME
\fBjc\fP \- JSON Convert JSONifies the output of many CLI tools, file-types,
and strings
@@ -487,6 +487,16 @@ M3U and M3U8 file parser
\fB--netstat\fP
`netstat` command parser
.TP
.B
\fB--net-localgroup\fP
`net localgroup` command parser
.TP
.B
\fB--net-user\fP
`net user` command parser
.TP
.B
\fB--nmcli\fP
@@ -872,6 +882,11 @@ PLIST file parser
\fB--route\fP
`route` command parser
.TP
.B
\fB--route-print\fP
`route print` command parser
.TP
.B
\fB--rpm-qi\fP
@@ -1027,6 +1042,11 @@ TOML file parser
\fB--traceroute\fP
`traceroute` and `traceroute6` command parser
.TP
.B
\fB--traceroute-s\fP
`traceroute` and `traceroute6` command streaming parser
.TP
.B
\fB--tune2fs\fP
@@ -1122,6 +1142,11 @@ Version string parser
\fB--x509-cert\fP
X.509 PEM and DER certificate file parser
.TP
.B
\fB--x509-crl\fP
X.509 PEM and DER certificate revocation list file parser
.TP
.B
\fB--x509-csr\fP

View File

@@ -1,11 +1,12 @@
import setuptools
with open('README.md', 'r') as f:
long_description = f.read()
setuptools.setup(
name='jc',
version='1.25.5',
version='1.25.7',
author='Kelly Brazil',
author_email='kellyjonbrazil@gmail.com',
description='Converts the output of popular command-line tools and file-types to JSON.',

View File

@@ -1,4 +1,3 @@
[![Tests](https://github.com/kellyjonbrazil/jc/workflows/Tests/badge.svg?branch=master)](https://github.com/kellyjonbrazil/jc/actions)
[![Pypi](https://img.shields.io/pypi/v/jc.svg)](https://pypi.org/project/jc/)
> Check out the `jc` Python [package documentation](https://github.com/kellyjonbrazil/jc/tree/master/docs) for developers

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,291 @@
[
{
"type": "header",
"destination_ip": "151.101.197.67",
"destination_name": "www.cnn.com",
"max_hops": 30,
"data_bytes": 60
},
{
"type": "hop",
"hop": 1,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "192.168.1.254",
"name": "dsldevice.attlocal.net",
"rtt": 4.024
},
{
"annotation": null,
"asn": null,
"ip": "192.168.1.254",
"name": "dsldevice.attlocal.net",
"rtt": 3.683
},
{
"annotation": null,
"asn": null,
"ip": "192.168.1.254",
"name": "dsldevice.attlocal.net",
"rtt": 3.706
}
]
},
{
"type": "hop",
"hop": 2,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "76.220.24.1",
"name": "76-220-24-1.lightspeed.sntcca.sbcglobal.net",
"rtt": 24.038
},
{
"annotation": null,
"asn": null,
"ip": "76.220.24.1",
"name": "76-220-24-1.lightspeed.sntcca.sbcglobal.net",
"rtt": 23.911
},
{
"annotation": null,
"asn": null,
"ip": "76.220.24.1",
"name": "76-220-24-1.lightspeed.sntcca.sbcglobal.net",
"rtt": 23.724
}
]
},
{
"type": "hop",
"hop": 3,
"probes": []
},
{
"type": "hop",
"hop": 4,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "12.122.149.186",
"name": "12.122.149.186",
"rtt": 42.273
},
{
"annotation": null,
"asn": null,
"ip": "12.122.149.186",
"name": "12.122.149.186",
"rtt": 42.213
},
{
"annotation": null,
"asn": null,
"ip": "12.122.149.186",
"name": "12.122.149.186",
"rtt": 42.083
}
]
},
{
"type": "hop",
"hop": 5,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "12.122.2.77",
"name": "12.122.2.77",
"rtt": 36.789
},
{
"annotation": null,
"asn": null,
"ip": "12.122.2.77",
"name": "12.122.2.77",
"rtt": 43.691
},
{
"annotation": null,
"asn": null,
"ip": "12.122.2.77",
"name": "12.122.2.77",
"rtt": 36.597
}
]
},
{
"type": "hop",
"hop": 6,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "12.122.2.94",
"name": "sd2ca21crs.ip.att.net",
"rtt": 41.587
},
{
"annotation": null,
"asn": null,
"ip": "12.122.2.94",
"name": "sd2ca21crs.ip.att.net",
"rtt": 40.24
},
{
"annotation": null,
"asn": null,
"ip": "12.122.2.94",
"name": "sd2ca21crs.ip.att.net",
"rtt": 44.659
}
]
},
{
"type": "hop",
"hop": 7,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "12.123.215.161",
"name": "12.123.215.161",
"rtt": 37.858
},
{
"annotation": null,
"asn": null,
"ip": "12.123.215.161",
"name": "12.123.215.161",
"rtt": 37.321
},
{
"annotation": null,
"asn": null,
"ip": "12.123.215.161",
"name": "12.123.215.161",
"rtt": 37.092
}
]
},
{
"type": "hop",
"hop": 8,
"probes": []
},
{
"type": "hop",
"hop": 9,
"probes": []
},
{
"type": "hop",
"hop": 10,
"probes": []
},
{
"type": "hop",
"hop": 11,
"probes": []
},
{
"type": "hop",
"hop": 12,
"probes": []
},
{
"type": "hop",
"hop": 13,
"probes": []
},
{
"type": "hop",
"hop": 14,
"probes": []
},
{
"type": "hop",
"hop": 15,
"probes": []
},
{
"type": "hop",
"hop": 16,
"probes": []
},
{
"type": "hop",
"hop": 17,
"probes": []
},
{
"type": "hop",
"hop": 18,
"probes": []
},
{
"type": "hop",
"hop": 19,
"probes": []
},
{
"type": "hop",
"hop": 20,
"probes": []
},
{
"type": "hop",
"hop": 21,
"probes": []
},
{
"type": "hop",
"hop": 22,
"probes": []
},
{
"type": "hop",
"hop": 23,
"probes": []
},
{
"type": "hop",
"hop": 24,
"probes": []
},
{
"type": "hop",
"hop": 25,
"probes": []
},
{
"type": "hop",
"hop": 26,
"probes": []
},
{
"type": "hop",
"hop": 27,
"probes": []
},
{
"type": "hop",
"hop": 28,
"probes": []
},
{
"type": "hop",
"hop": 29,
"probes": []
},
{
"type": "hop",
"hop": 30,
"probes": []
}
]

View File

@@ -1 +1 @@
{"destination_ip": "151.101.197.67", "destination_name": "www.cnn.com", "hops": [{"hop": 1, "probes": [{"annotation": null, "asn": null, "ip": "192.168.1.254", "name": "dsldevice.attlocal.net", "rtt": 4.024}, {"annotation": null, "asn": null, "ip": "192.168.1.254", "name": "dsldevice.attlocal.net", "rtt": 3.683}, {"annotation": null, "asn": null, "ip": "192.168.1.254", "name": "dsldevice.attlocal.net", "rtt": 3.706}]}, {"hop": 2, "probes": [{"annotation": null, "asn": null, "ip": "76.220.24.1", "name": "76-220-24-1.lightspeed.sntcca.sbcglobal.net", "rtt": 24.038}, {"annotation": null, "asn": null, "ip": "76.220.24.1", "name": "76-220-24-1.lightspeed.sntcca.sbcglobal.net", "rtt": 23.911}, {"annotation": null, "asn": null, "ip": "76.220.24.1", "name": "76-220-24-1.lightspeed.sntcca.sbcglobal.net", "rtt": 23.724}]}, {"hop": 3, "probes": []}, {"hop": 4, "probes": [{"annotation": null, "asn": null, "ip": "12.122.149.186", "name": "12.122.149.186", "rtt": 42.273}, {"annotation": null, "asn": null, "ip": "12.122.149.186", "name": "12.122.149.186", "rtt": 42.213}, {"annotation": null, "asn": null, "ip": "12.122.149.186", "name": "12.122.149.186", "rtt": 42.083}]}, {"hop": 5, "probes": [{"annotation": null, "asn": null, "ip": "12.122.2.77", "name": "12.122.2.77", "rtt": 36.789}, {"annotation": null, "asn": null, "ip": "12.122.2.77", "name": "12.122.2.77", "rtt": 43.691}, {"annotation": null, "asn": null, "ip": "12.122.2.77", "name": "12.122.2.77", "rtt": 36.597}]}, {"hop": 6, "probes": [{"annotation": null, "asn": null, "ip": "12.122.2.94", "name": "sd2ca21crs.ip.att.net", "rtt": 41.587}, {"annotation": null, "asn": null, "ip": "12.122.2.94", "name": "sd2ca21crs.ip.att.net", "rtt": 40.24}, {"annotation": null, "asn": null, "ip": "12.122.2.94", "name": "sd2ca21crs.ip.att.net", "rtt": 44.659}]}, {"hop": 7, "probes": [{"annotation": null, "asn": null, "ip": "12.123.215.161", "name": "12.123.215.161", "rtt": 37.858}, {"annotation": null, "asn": null, "ip": "12.123.215.161", "name": "12.123.215.161", "rtt": 37.321}, {"annotation": null, "asn": null, "ip": "12.123.215.161", "name": "12.123.215.161", "rtt": 37.092}]}, {"hop": 8, "probes": []}, {"hop": 9, "probes": []}, {"hop": 10, "probes": []}, {"hop": 11, "probes": []}, {"hop": 12, "probes": []}, {"hop": 13, "probes": []}, {"hop": 14, "probes": []}, {"hop": 15, "probes": []}, {"hop": 16, "probes": []}, {"hop": 17, "probes": []}, {"hop": 18, "probes": []}, {"hop": 19, "probes": []}, {"hop": 20, "probes": []}, {"hop": 21, "probes": []}, {"hop": 22, "probes": []}, {"hop": 23, "probes": []}, {"hop": 24, "probes": []}, {"hop": 25, "probes": []}, {"hop": 26, "probes": []}, {"hop": 27, "probes": []}, {"hop": 28, "probes": []}, {"hop": 29, "probes": []}, {"hop": 30, "probes": []}]}
{"destination_ip":"151.101.197.67","destination_name":"www.cnn.com","max_hops":30,"data_bytes":60,"hops":[{"hop":1,"probes":[{"annotation":null,"asn":null,"ip":"192.168.1.254","name":"dsldevice.attlocal.net","rtt":4.024},{"annotation":null,"asn":null,"ip":"192.168.1.254","name":"dsldevice.attlocal.net","rtt":3.683},{"annotation":null,"asn":null,"ip":"192.168.1.254","name":"dsldevice.attlocal.net","rtt":3.706}]},{"hop":2,"probes":[{"annotation":null,"asn":null,"ip":"76.220.24.1","name":"76-220-24-1.lightspeed.sntcca.sbcglobal.net","rtt":24.038},{"annotation":null,"asn":null,"ip":"76.220.24.1","name":"76-220-24-1.lightspeed.sntcca.sbcglobal.net","rtt":23.911},{"annotation":null,"asn":null,"ip":"76.220.24.1","name":"76-220-24-1.lightspeed.sntcca.sbcglobal.net","rtt":23.724}]},{"hop":3,"probes":[]},{"hop":4,"probes":[{"annotation":null,"asn":null,"ip":"12.122.149.186","name":"12.122.149.186","rtt":42.273},{"annotation":null,"asn":null,"ip":"12.122.149.186","name":"12.122.149.186","rtt":42.213},{"annotation":null,"asn":null,"ip":"12.122.149.186","name":"12.122.149.186","rtt":42.083}]},{"hop":5,"probes":[{"annotation":null,"asn":null,"ip":"12.122.2.77","name":"12.122.2.77","rtt":36.789},{"annotation":null,"asn":null,"ip":"12.122.2.77","name":"12.122.2.77","rtt":43.691},{"annotation":null,"asn":null,"ip":"12.122.2.77","name":"12.122.2.77","rtt":36.597}]},{"hop":6,"probes":[{"annotation":null,"asn":null,"ip":"12.122.2.94","name":"sd2ca21crs.ip.att.net","rtt":41.587},{"annotation":null,"asn":null,"ip":"12.122.2.94","name":"sd2ca21crs.ip.att.net","rtt":40.24},{"annotation":null,"asn":null,"ip":"12.122.2.94","name":"sd2ca21crs.ip.att.net","rtt":44.659}]},{"hop":7,"probes":[{"annotation":null,"asn":null,"ip":"12.123.215.161","name":"12.123.215.161","rtt":37.858},{"annotation":null,"asn":null,"ip":"12.123.215.161","name":"12.123.215.161","rtt":37.321},{"annotation":null,"asn":null,"ip":"12.123.215.161","name":"12.123.215.161","rtt":37.092}]},{"hop":8,"probes":[]},{"hop":9,"probes":[]},{"hop":10,"probes":[]},{"hop":11,"probes":[]},{"hop":12,"probes":[]},{"hop":13,"probes":[]},{"hop":14,"probes":[]},{"hop":15,"probes":[]},{"hop":16,"probes":[]},{"hop":17,"probes":[]},{"hop":18,"probes":[]},{"hop":19,"probes":[]},{"hop":20,"probes":[]},{"hop":21,"probes":[]},{"hop":22,"probes":[]},{"hop":23,"probes":[]},{"hop":24,"probes":[]},{"hop":25,"probes":[]},{"hop":26,"probes":[]},{"hop":27,"probes":[]},{"hop":28,"probes":[]},{"hop":29,"probes":[]},{"hop":30,"probes":[]}]}

1
tests/fixtures/debian13/who.json vendored Normal file
View File

@@ -0,0 +1 @@
[{"user":"root","tty":"tty1","time":"Sep 1 12:20","epoch":null},{"user":"frenkye","tty":"pts/4","process":"sshd","time":"Sep 1 12:05","from":"x.x.x.x","epoch":null},{"user":"root","tty":"tty1","time":"Sep 1 12:25","epoch":null},{"user":"frenkye","tty":"pts/4","time":"Sep 1 12:05","from":"x.x.x.x","epoch":null},{"user":"frenkye","tty":"pts/443","process":"kelly","time":"Sep 1 12:05","from":"x.x.x.x","epoch":null}]

5
tests/fixtures/debian13/who.out vendored Normal file
View File

@@ -0,0 +1,5 @@
root tty1 Sep 1 12:20
frenkye sshd pts/4 Sep 1 12:05 (x.x.x.x)
root tty1 Sep 1 12:25
frenkye pts/4 Sep 1 12:05 (x.x.x.x)
frenkye kelly pts/443 Sep 1 12:05 (x.x.x.x)

View File

@@ -0,0 +1,216 @@
[
{
"type": "header",
"destination_ip": "8.8.8.8",
"destination_name": "8.8.8.8",
"max_hops": 64,
"data_bytes": 40
},
{
"type": "hop",
"hop": 1,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "192.168.1.254",
"name": "dsldevice.attlocal.net",
"rtt": 3.263
},
{
"annotation": null,
"asn": null,
"ip": "192.168.1.254",
"name": "dsldevice.attlocal.net",
"rtt": 4.146
},
{
"annotation": null,
"asn": null,
"ip": "192.168.1.254",
"name": "dsldevice.attlocal.net",
"rtt": 4.273
}
]
},
{
"type": "hop",
"hop": 2,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "76.220.24.1",
"name": "76-220-24-1.lightspeed.sntcca.sbcglobal.net",
"rtt": 20.839
},
{
"annotation": null,
"asn": null,
"ip": "76.220.24.1",
"name": "76-220-24-1.lightspeed.sntcca.sbcglobal.net",
"rtt": 23.434
},
{
"annotation": null,
"asn": null,
"ip": "76.220.24.1",
"name": "76-220-24-1.lightspeed.sntcca.sbcglobal.net",
"rtt": 22.032
}
]
},
{
"type": "hop",
"hop": 3,
"probes": []
},
{
"type": "hop",
"hop": 4,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "12.122.149.186",
"name": "12.122.149.186",
"rtt": 33.17
},
{
"annotation": null,
"asn": null,
"ip": "12.122.149.186",
"name": "12.122.149.186",
"rtt": 26.593
},
{
"annotation": null,
"asn": null,
"ip": "12.122.149.186",
"name": "12.122.149.186",
"rtt": 32.851
}
]
},
{
"type": "hop",
"hop": 5,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "12.122.3.70",
"name": "sffca22crs.ip.att.net",
"rtt": 26.045
},
{
"annotation": null,
"asn": null,
"ip": "12.122.3.70",
"name": "sffca22crs.ip.att.net",
"rtt": 29.235
},
{
"annotation": null,
"asn": null,
"ip": "12.122.3.70",
"name": "sffca22crs.ip.att.net",
"rtt": 28.28
}
]
},
{
"type": "hop",
"hop": 6,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "12.122.163.61",
"name": "12.122.163.61",
"rtt": 25.3
},
{
"annotation": null,
"asn": null,
"ip": "12.122.163.61",
"name": "12.122.163.61",
"rtt": 24.156
},
{
"annotation": null,
"asn": null,
"ip": "12.122.163.61",
"name": "12.122.163.61",
"rtt": 24.849
}
]
},
{
"type": "hop",
"hop": 7,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "12.255.10.226",
"name": "12.255.10.226",
"rtt": 25.375
},
{
"annotation": null,
"asn": null,
"ip": "12.255.10.224",
"name": "12.255.10.224",
"rtt": 24.011
},
{
"annotation": null,
"asn": null,
"ip": "12.255.10.224",
"name": "12.255.10.224",
"rtt": 25.322
}
]
},
{
"type": "hop",
"hop": 8,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "108.170.243.1",
"name": "108.170.243.1",
"rtt": 29.376
}
]
},
{
"type": "hop",
"hop": 9,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "8.8.8.8",
"name": "dns.google",
"rtt": 23.228
},
{
"annotation": null,
"asn": null,
"ip": "209.85.252.251",
"name": "209.85.252.251",
"rtt": 24.548
},
{
"annotation": null,
"asn": null,
"ip": "108.170.237.23",
"name": "108.170.237.23",
"rtt": 24.332
}
]
}
]

View File

@@ -1 +1 @@
{"destination_ip": "8.8.8.8", "destination_name": "8.8.8.8", "hops": [{"hop": 1, "probes": [{"annotation": null, "asn": null, "ip": "192.168.1.254", "name": "dsldevice.attlocal.net", "rtt": 3.263}, {"annotation": null, "asn": null, "ip": "192.168.1.254", "name": "dsldevice.attlocal.net", "rtt": 4.146}, {"annotation": null, "asn": null, "ip": "192.168.1.254", "name": "dsldevice.attlocal.net", "rtt": 4.273}]}, {"hop": 2, "probes": [{"annotation": null, "asn": null, "ip": "76.220.24.1", "name": "76-220-24-1.lightspeed.sntcca.sbcglobal.net", "rtt": 20.839}, {"annotation": null, "asn": null, "ip": "76.220.24.1", "name": "76-220-24-1.lightspeed.sntcca.sbcglobal.net", "rtt": 23.434}, {"annotation": null, "asn": null, "ip": "76.220.24.1", "name": "76-220-24-1.lightspeed.sntcca.sbcglobal.net", "rtt": 22.032}]}, {"hop": 3, "probes": []}, {"hop": 4, "probes": [{"annotation": null, "asn": null, "ip": "12.122.149.186", "name": "12.122.149.186", "rtt": 33.17}, {"annotation": null, "asn": null, "ip": "12.122.149.186", "name": "12.122.149.186", "rtt": 26.593}, {"annotation": null, "asn": null, "ip": "12.122.149.186", "name": "12.122.149.186", "rtt": 32.851}]}, {"hop": 5, "probes": [{"annotation": null, "asn": null, "ip": "12.122.3.70", "name": "sffca22crs.ip.att.net", "rtt": 26.045}, {"annotation": null, "asn": null, "ip": "12.122.3.70", "name": "sffca22crs.ip.att.net", "rtt": 29.235}, {"annotation": null, "asn": null, "ip": "12.122.3.70", "name": "sffca22crs.ip.att.net", "rtt": 28.28}]}, {"hop": 6, "probes": [{"annotation": null, "asn": null, "ip": "12.122.163.61", "name": "12.122.163.61", "rtt": 25.3}, {"annotation": null, "asn": null, "ip": "12.122.163.61", "name": "12.122.163.61", "rtt": 24.156}, {"annotation": null, "asn": null, "ip": "12.122.163.61", "name": "12.122.163.61", "rtt": 24.849}]}, {"hop": 7, "probes": [{"annotation": null, "asn": null, "ip": "12.255.10.226", "name": "12.255.10.226", "rtt": 25.375}, {"annotation": null, "asn": null, "ip": "12.255.10.224", "name": "12.255.10.224", "rtt": 24.011}, {"annotation": null, "asn": null, "ip": "12.255.10.224", "name": "12.255.10.224", "rtt": 25.322}]}, {"hop": 8, "probes": [{"annotation": null, "asn": null, "ip": "108.170.243.1", "name": "108.170.243.1", "rtt": 29.376}]}, {"hop": 9, "probes": [{"annotation": null, "asn": null, "ip": "8.8.8.8", "name": "dns.google", "rtt": 23.228}, {"annotation": null, "asn": null, "ip": "209.85.252.251", "name": "209.85.252.251", "rtt": 24.548}, {"annotation": null, "asn": null, "ip": "108.170.237.23", "name": "108.170.237.23", "rtt": 24.332}]}]}
{"destination_ip":"8.8.8.8","destination_name":"8.8.8.8","max_hops":64,"data_bytes":40,"hops":[{"hop":1,"probes":[{"annotation":null,"asn":null,"ip":"192.168.1.254","name":"dsldevice.attlocal.net","rtt":3.263},{"annotation":null,"asn":null,"ip":"192.168.1.254","name":"dsldevice.attlocal.net","rtt":4.146},{"annotation":null,"asn":null,"ip":"192.168.1.254","name":"dsldevice.attlocal.net","rtt":4.273}]},{"hop":2,"probes":[{"annotation":null,"asn":null,"ip":"76.220.24.1","name":"76-220-24-1.lightspeed.sntcca.sbcglobal.net","rtt":20.839},{"annotation":null,"asn":null,"ip":"76.220.24.1","name":"76-220-24-1.lightspeed.sntcca.sbcglobal.net","rtt":23.434},{"annotation":null,"asn":null,"ip":"76.220.24.1","name":"76-220-24-1.lightspeed.sntcca.sbcglobal.net","rtt":22.032}]},{"hop":3,"probes":[]},{"hop":4,"probes":[{"annotation":null,"asn":null,"ip":"12.122.149.186","name":"12.122.149.186","rtt":33.17},{"annotation":null,"asn":null,"ip":"12.122.149.186","name":"12.122.149.186","rtt":26.593},{"annotation":null,"asn":null,"ip":"12.122.149.186","name":"12.122.149.186","rtt":32.851}]},{"hop":5,"probes":[{"annotation":null,"asn":null,"ip":"12.122.3.70","name":"sffca22crs.ip.att.net","rtt":26.045},{"annotation":null,"asn":null,"ip":"12.122.3.70","name":"sffca22crs.ip.att.net","rtt":29.235},{"annotation":null,"asn":null,"ip":"12.122.3.70","name":"sffca22crs.ip.att.net","rtt":28.28}]},{"hop":6,"probes":[{"annotation":null,"asn":null,"ip":"12.122.163.61","name":"12.122.163.61","rtt":25.3},{"annotation":null,"asn":null,"ip":"12.122.163.61","name":"12.122.163.61","rtt":24.156},{"annotation":null,"asn":null,"ip":"12.122.163.61","name":"12.122.163.61","rtt":24.849}]},{"hop":7,"probes":[{"annotation":null,"asn":null,"ip":"12.255.10.226","name":"12.255.10.226","rtt":25.375},{"annotation":null,"asn":null,"ip":"12.255.10.224","name":"12.255.10.224","rtt":24.011},{"annotation":null,"asn":null,"ip":"12.255.10.224","name":"12.255.10.224","rtt":25.322}]},{"hop":8,"probes":[{"annotation":null,"asn":null,"ip":"108.170.243.1","name":"108.170.243.1","rtt":29.376}]},{"hop":9,"probes":[{"annotation":null,"asn":null,"ip":"8.8.8.8","name":"dns.google","rtt":23.228},{"annotation":null,"asn":null,"ip":"209.85.252.251","name":"209.85.252.251","rtt":24.548},{"annotation":null,"asn":null,"ip":"108.170.237.23","name":"108.170.237.23","rtt":24.332}]}]}

View File

@@ -0,0 +1,208 @@
[
{
"type": "header",
"destination_ip": "2a04:4e42::323",
"destination_name": "turner-tls.map.fastly.net",
"max_hops": 64,
"data_bytes": 20
},
{
"type": "hop",
"hop": 1,
"probes": []
},
{
"type": "hop",
"hop": 2,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2001:506:6000:11b:71:156:212:143",
"name": null,
"rtt": 27.603
},
{
"annotation": null,
"asn": null,
"ip": "2001:506:6000:11b:71:156:212:143",
"name": null,
"rtt": 28.659
},
{
"annotation": null,
"asn": null,
"ip": "2001:506:6000:11b:71:156:212:143",
"name": null,
"rtt": 33.235
}
]
},
{
"type": "hop",
"hop": 3,
"probes": []
},
{
"type": "hop",
"hop": 4,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2001:1890:ff:ff08:12:242:117:16",
"name": null,
"rtt": 36.731
},
{
"annotation": null,
"asn": null,
"ip": "2001:1890:ff:ff08:12:242:117:16",
"name": null,
"rtt": 28.875
},
{
"annotation": null,
"asn": null,
"ip": "2001:1890:ff:ff08:12:242:117:16",
"name": null,
"rtt": 28.959
}
]
},
{
"type": "hop",
"hop": 5,
"probes": []
},
{
"type": "hop",
"hop": 6,
"probes": []
},
{
"type": "hop",
"hop": 7,
"probes": []
},
{
"type": "hop",
"hop": 8,
"probes": []
},
{
"type": "hop",
"hop": 9,
"probes": []
},
{
"type": "hop",
"hop": 10,
"probes": []
},
{
"type": "hop",
"hop": 11,
"probes": []
},
{
"type": "hop",
"hop": 12,
"probes": []
},
{
"type": "hop",
"hop": 13,
"probes": []
},
{
"type": "hop",
"hop": 14,
"probes": []
},
{
"type": "hop",
"hop": 15,
"probes": []
},
{
"type": "hop",
"hop": 16,
"probes": []
},
{
"type": "hop",
"hop": 17,
"probes": []
},
{
"type": "hop",
"hop": 18,
"probes": []
},
{
"type": "hop",
"hop": 19,
"probes": []
},
{
"type": "hop",
"hop": 20,
"probes": []
},
{
"type": "hop",
"hop": 21,
"probes": []
},
{
"type": "hop",
"hop": 22,
"probes": []
},
{
"type": "hop",
"hop": 23,
"probes": []
},
{
"type": "hop",
"hop": 24,
"probes": []
},
{
"type": "hop",
"hop": 25,
"probes": []
},
{
"type": "hop",
"hop": 26,
"probes": []
},
{
"type": "hop",
"hop": 27,
"probes": []
},
{
"type": "hop",
"hop": 28,
"probes": []
},
{
"type": "hop",
"hop": 29,
"probes": []
},
{
"type": "hop",
"hop": 30,
"probes": []
},
{
"type": "hop",
"hop": 31,
"probes": []
}
]

View File

@@ -1 +1 @@
{"destination_ip": "2a04:4e42::323", "destination_name": "turner-tls.map.fastly.net", "hops": [{"hop": 1, "probes": []}, {"hop": 2, "probes": [{"annotation": null, "asn": null, "ip": "2001:506:6000:11b:71:156:212:143", "name": null, "rtt": 27.603}, {"annotation": null, "asn": null, "ip": "2001:506:6000:11b:71:156:212:143", "name": null, "rtt": 28.659}, {"annotation": null, "asn": null, "ip": "2001:506:6000:11b:71:156:212:143", "name": null, "rtt": 33.235}]}, {"hop": 3, "probes": []}, {"hop": 4, "probes": [{"annotation": null, "asn": null, "ip": "2001:1890:ff:ff08:12:242:117:16", "name": null, "rtt": 36.731}, {"annotation": null, "asn": null, "ip": "2001:1890:ff:ff08:12:242:117:16", "name": null, "rtt": 28.875}, {"annotation": null, "asn": null, "ip": "2001:1890:ff:ff08:12:242:117:16", "name": null, "rtt": 28.959}]}, {"hop": 5, "probes": []}, {"hop": 6, "probes": []}, {"hop": 7, "probes": []}, {"hop": 8, "probes": []}, {"hop": 9, "probes": []}, {"hop": 10, "probes": []}, {"hop": 11, "probes": []}, {"hop": 12, "probes": []}, {"hop": 13, "probes": []}, {"hop": 14, "probes": []}, {"hop": 15, "probes": []}, {"hop": 16, "probes": []}, {"hop": 17, "probes": []}, {"hop": 18, "probes": []}, {"hop": 19, "probes": []}, {"hop": 20, "probes": []}, {"hop": 21, "probes": []}, {"hop": 22, "probes": []}, {"hop": 23, "probes": []}, {"hop": 24, "probes": []}, {"hop": 25, "probes": []}, {"hop": 26, "probes": []}, {"hop": 27, "probes": []}, {"hop": 28, "probes": []}, {"hop": 29, "probes": []}, {"hop": 30, "probes": []}, {"hop": 31, "probes": []}]}
{"destination_ip":"2a04:4e42::323","destination_name":"turner-tls.map.fastly.net","max_hops":64,"data_bytes":20,"hops":[{"hop":1,"probes":[]},{"hop":2,"probes":[{"annotation":null,"asn":null,"ip":"2001:506:6000:11b:71:156:212:143","name":null,"rtt":27.603},{"annotation":null,"asn":null,"ip":"2001:506:6000:11b:71:156:212:143","name":null,"rtt":28.659},{"annotation":null,"asn":null,"ip":"2001:506:6000:11b:71:156:212:143","name":null,"rtt":33.235}]},{"hop":3,"probes":[]},{"hop":4,"probes":[{"annotation":null,"asn":null,"ip":"2001:1890:ff:ff08:12:242:117:16","name":null,"rtt":36.731},{"annotation":null,"asn":null,"ip":"2001:1890:ff:ff08:12:242:117:16","name":null,"rtt":28.875},{"annotation":null,"asn":null,"ip":"2001:1890:ff:ff08:12:242:117:16","name":null,"rtt":28.959}]},{"hop":5,"probes":[]},{"hop":6,"probes":[]},{"hop":7,"probes":[]},{"hop":8,"probes":[]},{"hop":9,"probes":[]},{"hop":10,"probes":[]},{"hop":11,"probes":[]},{"hop":12,"probes":[]},{"hop":13,"probes":[]},{"hop":14,"probes":[]},{"hop":15,"probes":[]},{"hop":16,"probes":[]},{"hop":17,"probes":[]},{"hop":18,"probes":[]},{"hop":19,"probes":[]},{"hop":20,"probes":[]},{"hop":21,"probes":[]},{"hop":22,"probes":[]},{"hop":23,"probes":[]},{"hop":24,"probes":[]},{"hop":25,"probes":[]},{"hop":26,"probes":[]},{"hop":27,"probes":[]},{"hop":28,"probes":[]},{"hop":29,"probes":[]},{"hop":30,"probes":[]},{"hop":31,"probes":[]}]}

View File

@@ -0,0 +1 @@
[{"chain":"INPUT","default_policy":"ACCEPT","default_packets":0,"default_bytes":0,"rules":[{"pkts":17,"bytes":1172,"target":null,"prot":"all","opt":null,"in":"*","out":"*","source":"0.0.0.0/0","destination":"0.0.0.0/0"}]}]

View File

@@ -0,0 +1,3 @@
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
17 1172 all -- * * 0.0.0.0/0 0.0.0.0/0

View File

@@ -0,0 +1 @@
[{"connection_id":"Team connection 1","connection_uuid":"258e02c2-d9f9-44bb-8d27-887e11aa1828","connection_stable_id":null,"connection_type":"team","connection_interface_name":"team0","connection_autoconnect":"yes","connection_autoconnect_priority":0,"connection_autoconnect_retries":-1,"connection_autoconnect_retries_text":"default","connection_multi_connect":0,"connection_multi_connect_text":"default","connection_auth_retries":-1,"connection_timestamp":0,"connection_read_only":"no","connection_permissions":null,"connection_zone":null,"connection_master":null,"connection_slave_type":null,"connection_autoconnect_slaves":-1,"connection_autoconnect_slaves_text":"default","connection_secondaries":null,"connection_gateway_ping_timeout":0,"connection_metered":"unknown","connection_lldp":"default","connection_mdns":-1,"connection_mdns_text":"default","connection_llmnr":-1,"connection_llmnr_text":"default","connection_dns_over_tls":-1,"connection_dns_over_tls_text":"default","connection_wait_device_timeout":-1,"ipv4_method":"auto","ipv4_dns":null,"ipv4_dns_search":null,"ipv4_dns_options":null,"ipv4_dns_priority":0,"ipv4_addresses":null,"ipv4_gateway":null,"ipv4_routes":null,"ipv4_route_metric":-1,"ipv4_route_table":0,"ipv4_route_table_text":"unspec","ipv4_routing_rules":null,"ipv4_ignore_auto_routes":"no","ipv4_ignore_auto_dns":"no","ipv4_dhcp_client_id":null,"ipv4_dhcp_iaid":null,"ipv4_dhcp_timeout":0,"ipv4_dhcp_timeout_text":"default","ipv4_dhcp_send_hostname":"yes","ipv4_dhcp_hostname":null,"ipv4_dhcp_fqdn":null,"ipv4_dhcp_hostname_flags":"0x0","ipv4_dhcp_hostname_flags_text":"none","ipv4_never_default":"no","ipv4_may_fail":"yes","ipv4_required_timeout":-1,"ipv4_required_timeout_text":"default","ipv4_dad_timeout":-1,"ipv4_dad_timeout_text":"default","ipv4_dhcp_vendor_class_identifier":null,"ipv4_dhcp_reject_servers":null,"ipv6_method":"auto","ipv6_dns":null,"ipv6_dns_search":null,"ipv6_dns_options":null,"ipv6_dns_priority":0,"ipv6_addresses":null,"ipv6_gateway":null,"ipv6_routes":null,"ipv6_route_metric":-1,"ipv6_route_table":0,"ipv6_route_table_text":"unspec","ipv6_routing_rules":null,"ipv6_ignore_auto_routes":"no","ipv6_ignore_auto_dns":"no","ipv6_never_default":"no","ipv6_may_fail":"yes","ipv6_required_timeout":-1,"ipv6_required_timeout_text":"default","ipv6_ip6_privacy":-1,"ipv6_ip6_privacy_text":"unknown","ipv6_addr_gen_mode":"stable-privacy","ipv6_ra_timeout":0,"ipv6_ra_timeout_text":"default","ipv6_dhcp_duid":null,"ipv6_dhcp_iaid":null,"ipv6_dhcp_timeout":0,"ipv6_dhcp_timeout_text":"default","ipv6_dhcp_send_hostname":"yes","ipv6_dhcp_hostname":null,"ipv6_dhcp_hostname_flags":"0x0","ipv6_dhcp_hostname_flags_text":"none","ipv6_token":null,"team_config":{"runner":{"name":"roundrobin"},"link_watch":{"name":"ethtool"}},"team_notify_peers_count":-1,"team_notify_peers_count_text":"unset","team_notify_peers_interval":-1,"team_notify_peers_interval_text":"unset","team_mcast_rejoin_count":-1,"team_mcast_rejoin_count_text":"unset","team_mcast_rejoin_interval":-1,"team_mcast_rejoin_interval_text":"unset","team_runner":"roundrobin","team_runner_hwaddr_policy":null,"team_runner_tx_hash":null,"team_runner_tx_balancer":null,"team_runner_tx_balancer_interval":-1,"team_runner_tx_balancer_interval_text":"unset","team_runner_active":"yes","team_runner_fast_rate":"no","team_runner_sys_prio":-1,"team_runner_sys_prio_text":"unset","team_runner_min_ports":-1,"team_runner_min_ports_text":"unset","team_runner_agg_select_policy":null,"team_link_watchers":"name=ethtool","team_port_config":{"queue_id":0,"prio":0,"lacp_prio":0,"lacp_key":0},"team_port_queue_id":0,"team_port_queue_id_text":"default","team_port_prio":0,"team_port_prio_text":"unset","team_port_sticky":"no","team_port_lacp_prio":0,"team_port_lacp_key":0,"team_port_lacp_key_text":"default","team_port_link_watchers":null,"proxy_method":"none","proxy_browser_only":"no","proxy_pac_url":null,"proxy_pac_script":null}]

View File

@@ -0,0 +1,116 @@
connection.id: Team connection 1
connection.uuid: 258e02c2-d9f9-44bb-8d27-887e11aa1828
connection.stable-id: --
connection.type: team
connection.interface-name: team0
connection.autoconnect: yes
connection.autoconnect-priority: 0
connection.autoconnect-retries: -1 (default)
connection.multi-connect: 0 (default)
connection.auth-retries: -1
connection.timestamp: 0
connection.read-only: no
connection.permissions: --
connection.zone: --
connection.master: --
connection.slave-type: --
connection.autoconnect-slaves: -1 (default)
connection.secondaries: --
connection.gateway-ping-timeout: 0
connection.metered: unknown
connection.lldp: default
connection.mdns: -1 (default)
connection.llmnr: -1 (default)
connection.dns-over-tls: -1 (default)
connection.wait-device-timeout: -1
ipv4.method: auto
ipv4.dns: --
ipv4.dns-search: --
ipv4.dns-options: --
ipv4.dns-priority: 0
ipv4.addresses: --
ipv4.gateway: --
ipv4.routes: --
ipv4.route-metric: -1
ipv4.route-table: 0 (unspec)
ipv4.routing-rules: --
ipv4.ignore-auto-routes: no
ipv4.ignore-auto-dns: no
ipv4.dhcp-client-id: --
ipv4.dhcp-iaid: --
ipv4.dhcp-timeout: 0 (default)
ipv4.dhcp-send-hostname: yes
ipv4.dhcp-hostname: --
ipv4.dhcp-fqdn: --
ipv4.dhcp-hostname-flags: 0x0 (none)
ipv4.never-default: no
ipv4.may-fail: yes
ipv4.required-timeout: -1 (default)
ipv4.dad-timeout: -1 (default)
ipv4.dhcp-vendor-class-identifier: --
ipv4.dhcp-reject-servers: --
ipv6.method: auto
ipv6.dns: --
ipv6.dns-search: --
ipv6.dns-options: --
ipv6.dns-priority: 0
ipv6.addresses: --
ipv6.gateway: --
ipv6.routes: --
ipv6.route-metric: -1
ipv6.route-table: 0 (unspec)
ipv6.routing-rules: --
ipv6.ignore-auto-routes: no
ipv6.ignore-auto-dns: no
ipv6.never-default: no
ipv6.may-fail: yes
ipv6.required-timeout: -1 (default)
ipv6.ip6-privacy: -1 (unknown)
ipv6.addr-gen-mode: stable-privacy
ipv6.ra-timeout: 0 (default)
ipv6.dhcp-duid: --
ipv6.dhcp-iaid: --
ipv6.dhcp-timeout: 0 (default)
ipv6.dhcp-send-hostname: yes
ipv6.dhcp-hostname: --
ipv6.dhcp-hostname-flags: 0x0 (none)
ipv6.token: --
team.config: {
"runner": {
"name": "roundrobin"
},
"link_watch": {
"name": "ethtool"
}
}
team.notify-peers-count: -1 (unset)
team.notify-peers-interval: -1 (unset)
team.mcast-rejoin-count: -1 (unset)
team.mcast-rejoin-interval: -1 (unset)
team.runner: roundrobin
team.runner-hwaddr-policy: --
team.runner-tx-hash: --
team.runner-tx-balancer: --
team.runner-tx-balancer-interval: -1 (unset)
team.runner-active: yes
team.runner-fast-rate: no
team.runner-sys-prio: -1 (unset)
team.runner-min-ports: -1 (unset)
team.runner-agg-select-policy: --
team.link-watchers: name=ethtool
team-port.config: {
"queue_id": 0,
"prio": 0,
"lacp_prio": 0,
"lacp_key": 0
}
team-port.queue-id: 0 (default)
team-port.prio: 0 (unset)
team-port.sticky: no
team-port.lacp-prio: 0
team-port.lacp-key: 0 (default)
team-port.link-watchers: --
proxy.method: none
proxy.browser-only: no
proxy.pac-url: --
proxy.pac-script: --

View File

@@ -0,0 +1 @@
[{"connection_id":"Team connection 1","connection_uuid":"258e02c2-d9f9-44bb-8d27-887e11aa1828","connection_stable_id":null,"connection_type":"team","connection_interface_name":"team0","connection_autoconnect":"yes","connection_autoconnect_priority":0,"connection_autoconnect_retries":-1,"connection_autoconnect_retries_text":"default","connection_multi_connect":0,"connection_multi_connect_text":"default","connection_auth_retries":-1,"connection_timestamp":0,"connection_read_only":"no","connection_permissions":null,"connection_zone":null,"connection_master":null,"connection_slave_type":null,"connection_autoconnect_slaves":-1,"connection_autoconnect_slaves_text":"default","connection_secondaries":null,"connection_gateway_ping_timeout":0,"connection_metered":"unknown","connection_lldp":"default","connection_mdns":-1,"connection_mdns_text":"default","connection_llmnr":-1,"connection_llmnr_text":"default","connection_dns_over_tls":-1,"connection_dns_over_tls_text":"default","connection_wait_device_timeout":-1,"ipv4_method":"auto","ipv4_dns":null,"ipv4_dns_search":null,"ipv4_dns_options":null,"ipv4_dns_priority":0,"ipv4_addresses":null,"ipv4_gateway":null,"ipv4_routes":null,"ipv4_route_metric":-1,"ipv4_route_table":0,"ipv4_route_table_text":"unspec","ipv4_routing_rules":null,"ipv4_ignore_auto_routes":"no","ipv4_ignore_auto_dns":"no","ipv4_dhcp_client_id":null,"ipv4_dhcp_iaid":null,"ipv4_dhcp_timeout":0,"ipv4_dhcp_timeout_text":"default","ipv4_dhcp_send_hostname":"yes","ipv4_dhcp_hostname":null,"ipv4_dhcp_fqdn":null,"ipv4_dhcp_hostname_flags":"0x0","ipv4_dhcp_hostname_flags_text":"none","ipv4_never_default":"no","ipv4_may_fail":"yes","ipv4_required_timeout":-1,"ipv4_required_timeout_text":"default","ipv4_dad_timeout":-1,"ipv4_dad_timeout_text":"default","ipv4_dhcp_vendor_class_identifier":null,"ipv4_dhcp_reject_servers":null,"ipv6_method":"auto","ipv6_dns":null,"ipv6_dns_search":null,"ipv6_dns_options":null,"ipv6_dns_priority":0,"ipv6_addresses":null,"ipv6_gateway":null,"ipv6_routes":null,"ipv6_route_metric":-1,"ipv6_route_table":0,"ipv6_route_table_text":"unspec","ipv6_routing_rules":null,"ipv6_ignore_auto_routes":"no","ipv6_ignore_auto_dns":"no","ipv6_never_default":"no","ipv6_may_fail":"yes","ipv6_required_timeout":-1,"ipv6_required_timeout_text":"default","ipv6_ip6_privacy":-1,"ipv6_ip6_privacy_text":"unknown","ipv6_addr_gen_mode":"stable-privacy","ipv6_ra_timeout":0,"ipv6_ra_timeout_text":"default","ipv6_dhcp_duid":null,"ipv6_dhcp_iaid":null,"ipv6_dhcp_timeout":0,"ipv6_dhcp_timeout_text":"default","ipv6_dhcp_send_hostname":"yes","ipv6_dhcp_hostname":null,"ipv6_dhcp_hostname_flags":"0x0","ipv6_dhcp_hostname_flags_text":"none","ipv6_token":null,"team_config":null,"team_notify_peers_count":-1,"team_notify_peers_count_text":"unset","team_notify_peers_interval":-1,"team_notify_peers_interval_text":"unset","team_mcast_rejoin_count":-1,"team_mcast_rejoin_count_text":"unset","team_mcast_rejoin_interval":-1,"team_mcast_rejoin_interval_text":"unset","team_runner":"roundrobin","team_runner_hwaddr_policy":null,"team_runner_tx_hash":null,"team_runner_tx_balancer":null,"team_runner_tx_balancer_interval":-1,"team_runner_tx_balancer_interval_text":"unset","team_runner_active":"yes","team_runner_fast_rate":"no","team_runner_sys_prio":-1,"team_runner_sys_prio_text":"unset","team_runner_min_ports":-1,"team_runner_min_ports_text":"unset","team_runner_agg_select_policy":null,"team_link_watchers":"name=ethtool","proxy_method":"none","proxy_browser_only":"no","proxy_pac_url":null,"proxy_pac_script":null}]

View File

@@ -0,0 +1,97 @@
connection.id: Team connection 1
connection.uuid: 258e02c2-d9f9-44bb-8d27-887e11aa1828
connection.stable-id: --
connection.type: team
connection.interface-name: team0
connection.autoconnect: yes
connection.autoconnect-priority: 0
connection.autoconnect-retries: -1 (default)
connection.multi-connect: 0 (default)
connection.auth-retries: -1
connection.timestamp: 0
connection.read-only: no
connection.permissions: --
connection.zone: --
connection.master: --
connection.slave-type: --
connection.autoconnect-slaves: -1 (default)
connection.secondaries: --
connection.gateway-ping-timeout: 0
connection.metered: unknown
connection.lldp: default
connection.mdns: -1 (default)
connection.llmnr: -1 (default)
connection.dns-over-tls: -1 (default)
connection.wait-device-timeout: -1
ipv4.method: auto
ipv4.dns: --
ipv4.dns-search: --
ipv4.dns-options: --
ipv4.dns-priority: 0
ipv4.addresses: --
ipv4.gateway: --
ipv4.routes: --
ipv4.route-metric: -1
ipv4.route-table: 0 (unspec)
ipv4.routing-rules: --
ipv4.ignore-auto-routes: no
ipv4.ignore-auto-dns: no
ipv4.dhcp-client-id: --
ipv4.dhcp-iaid: --
ipv4.dhcp-timeout: 0 (default)
ipv4.dhcp-send-hostname: yes
ipv4.dhcp-hostname: --
ipv4.dhcp-fqdn: --
ipv4.dhcp-hostname-flags: 0x0 (none)
ipv4.never-default: no
ipv4.may-fail: yes
ipv4.required-timeout: -1 (default)
ipv4.dad-timeout: -1 (default)
ipv4.dhcp-vendor-class-identifier: --
ipv4.dhcp-reject-servers: --
ipv6.method: auto
ipv6.dns: --
ipv6.dns-search: --
ipv6.dns-options: --
ipv6.dns-priority: 0
ipv6.addresses: --
ipv6.gateway: --
ipv6.routes: --
ipv6.route-metric: -1
ipv6.route-table: 0 (unspec)
ipv6.routing-rules: --
ipv6.ignore-auto-routes: no
ipv6.ignore-auto-dns: no
ipv6.never-default: no
ipv6.may-fail: yes
ipv6.required-timeout: -1 (default)
ipv6.ip6-privacy: -1 (unknown)
ipv6.addr-gen-mode: stable-privacy
ipv6.ra-timeout: 0 (default)
ipv6.dhcp-duid: --
ipv6.dhcp-iaid: --
ipv6.dhcp-timeout: 0 (default)
ipv6.dhcp-send-hostname: yes
ipv6.dhcp-hostname: --
ipv6.dhcp-hostname-flags: 0x0 (none)
ipv6.token: --
team.config: --
team.notify-peers-count: -1 (unset)
team.notify-peers-interval: -1 (unset)
team.mcast-rejoin-count: -1 (unset)
team.mcast-rejoin-interval: -1 (unset)
team.runner: roundrobin
team.runner-hwaddr-policy: --
team.runner-tx-hash: --
team.runner-tx-balancer: --
team.runner-tx-balancer-interval: -1 (unset)
team.runner-active: yes
team.runner-fast-rate: no
team.runner-sys-prio: -1 (unset)
team.runner-min-ports: -1 (unset)
team.runner-agg-select-policy: --
team.link-watchers: name=ethtool
proxy.method: none
proxy.browser-only: no
proxy.pac-url: --
proxy.pac-script: --

View File

@@ -0,0 +1 @@
[{"connection_id":"Team connection 1","connection_uuid":"258e02c2-d9f9-44bb-8d27-887e11aa1828","connection_stable_id":null,"connection_type":"team","connection_interface_name":"team0","connection_autoconnect":"yes","connection_autoconnect_priority":0,"connection_autoconnect_retries":-1,"connection_autoconnect_retries_text":"default","connection_multi_connect":0,"connection_multi_connect_text":"default","connection_auth_retries":-1,"connection_timestamp":0,"connection_read_only":"no","connection_permissions":null,"connection_zone":null,"connection_master":null,"connection_slave_type":null,"connection_autoconnect_slaves":-1,"connection_autoconnect_slaves_text":"default","connection_secondaries":null,"connection_gateway_ping_timeout":0,"connection_metered":"unknown","connection_lldp":"default","connection_mdns":-1,"connection_mdns_text":"default","connection_llmnr":-1,"connection_llmnr_text":"default","connection_dns_over_tls":-1,"connection_dns_over_tls_text":"default","connection_wait_device_timeout":-1,"ipv4_method":"auto","ipv4_dns":null,"ipv4_dns_search":null,"ipv4_dns_options":null,"ipv4_dns_priority":0,"ipv4_addresses":null,"ipv4_gateway":null,"ipv4_routes":null,"ipv4_route_metric":-1,"ipv4_route_table":0,"ipv4_route_table_text":"unspec","ipv4_routing_rules":null,"ipv4_ignore_auto_routes":"no","ipv4_ignore_auto_dns":"no","ipv4_dhcp_client_id":null,"ipv4_dhcp_iaid":null,"ipv4_dhcp_timeout":0,"ipv4_dhcp_timeout_text":"default","ipv4_dhcp_send_hostname":"yes","ipv4_dhcp_hostname":null,"ipv4_dhcp_fqdn":null,"ipv4_dhcp_hostname_flags":"0x0","ipv4_dhcp_hostname_flags_text":"none","ipv4_never_default":"no","ipv4_may_fail":"yes","ipv4_required_timeout":-1,"ipv4_required_timeout_text":"default","ipv4_dad_timeout":-1,"ipv4_dad_timeout_text":"default","ipv4_dhcp_vendor_class_identifier":null,"ipv4_dhcp_reject_servers":null,"ipv6_method":"auto","ipv6_dns":null,"ipv6_dns_search":null,"ipv6_dns_options":null,"ipv6_dns_priority":0,"ipv6_addresses":null,"ipv6_gateway":null,"ipv6_routes":null,"ipv6_route_metric":-1,"ipv6_route_table":0,"ipv6_route_table_text":"unspec","ipv6_routing_rules":null,"ipv6_ignore_auto_routes":"no","ipv6_ignore_auto_dns":"no","ipv6_never_default":"no","ipv6_may_fail":"yes","ipv6_required_timeout":-1,"ipv6_required_timeout_text":"default","ipv6_ip6_privacy":-1,"ipv6_ip6_privacy_text":"unknown","ipv6_addr_gen_mode":"stable-privacy","ipv6_ra_timeout":0,"ipv6_ra_timeout_text":"default","ipv6_dhcp_duid":null,"ipv6_dhcp_iaid":null,"ipv6_dhcp_timeout":0,"ipv6_dhcp_timeout_text":"default","ipv6_dhcp_send_hostname":"yes","ipv6_dhcp_hostname":null,"ipv6_dhcp_hostname_flags":"0x0","ipv6_dhcp_hostname_flags_text":"none","ipv6_token":null,"team_config":{"runner":{"name":"roundrobin"},"link_watch":{"name":"ethtool"}},"team_notify_peers_count":-1,"team_notify_peers_count_text":"unset","team_notify_peers_interval":-1,"team_notify_peers_interval_text":"unset","team_mcast_rejoin_count":-1,"team_mcast_rejoin_count_text":"unset","team_mcast_rejoin_interval":-1,"team_mcast_rejoin_interval_text":"unset","team_runner":"roundrobin","team_runner_hwaddr_policy":null,"team_runner_tx_hash":null,"team_runner_tx_balancer":null,"team_runner_tx_balancer_interval":-1,"team_runner_tx_balancer_interval_text":"unset","team_runner_active":"yes","team_runner_fast_rate":"no","team_runner_sys_prio":-1,"team_runner_sys_prio_text":"unset","team_runner_min_ports":-1,"team_runner_min_ports_text":"unset","team_runner_agg_select_policy":null,"team_link_watchers":"name=ethtool","proxy_method":"none","proxy_browser_only":"no","proxy_pac_url":null,"proxy_pac_script":null}]

View File

@@ -0,0 +1,104 @@
connection.id: Team connection 1
connection.uuid: 258e02c2-d9f9-44bb-8d27-887e11aa1828
connection.stable-id: --
connection.type: team
connection.interface-name: team0
connection.autoconnect: yes
connection.autoconnect-priority: 0
connection.autoconnect-retries: -1 (default)
connection.multi-connect: 0 (default)
connection.auth-retries: -1
connection.timestamp: 0
connection.read-only: no
connection.permissions: --
connection.zone: --
connection.master: --
connection.slave-type: --
connection.autoconnect-slaves: -1 (default)
connection.secondaries: --
connection.gateway-ping-timeout: 0
connection.metered: unknown
connection.lldp: default
connection.mdns: -1 (default)
connection.llmnr: -1 (default)
connection.dns-over-tls: -1 (default)
connection.wait-device-timeout: -1
ipv4.method: auto
ipv4.dns: --
ipv4.dns-search: --
ipv4.dns-options: --
ipv4.dns-priority: 0
ipv4.addresses: --
ipv4.gateway: --
ipv4.routes: --
ipv4.route-metric: -1
ipv4.route-table: 0 (unspec)
ipv4.routing-rules: --
ipv4.ignore-auto-routes: no
ipv4.ignore-auto-dns: no
ipv4.dhcp-client-id: --
ipv4.dhcp-iaid: --
ipv4.dhcp-timeout: 0 (default)
ipv4.dhcp-send-hostname: yes
ipv4.dhcp-hostname: --
ipv4.dhcp-fqdn: --
ipv4.dhcp-hostname-flags: 0x0 (none)
ipv4.never-default: no
ipv4.may-fail: yes
ipv4.required-timeout: -1 (default)
ipv4.dad-timeout: -1 (default)
ipv4.dhcp-vendor-class-identifier: --
ipv4.dhcp-reject-servers: --
ipv6.method: auto
ipv6.dns: --
ipv6.dns-search: --
ipv6.dns-options: --
ipv6.dns-priority: 0
ipv6.addresses: --
ipv6.gateway: --
ipv6.routes: --
ipv6.route-metric: -1
ipv6.route-table: 0 (unspec)
ipv6.routing-rules: --
ipv6.ignore-auto-routes: no
ipv6.ignore-auto-dns: no
ipv6.never-default: no
ipv6.may-fail: yes
ipv6.required-timeout: -1 (default)
ipv6.ip6-privacy: -1 (unknown)
ipv6.addr-gen-mode: stable-privacy
ipv6.ra-timeout: 0 (default)
ipv6.dhcp-duid: --
ipv6.dhcp-iaid: --
ipv6.dhcp-timeout: 0 (default)
ipv6.dhcp-send-hostname: yes
ipv6.dhcp-hostname: --
ipv6.dhcp-hostname-flags: 0x0 (none)
ipv6.token: --
team.config: {
"runner": {
"name": "roundrobin"
},
"link_watch": {
"name": "ethtool"
}
}
team.notify-peers-count: -1 (unset)
team.notify-peers-interval: -1 (unset)
team.mcast-rejoin-count: -1 (unset)
team.mcast-rejoin-interval: -1 (unset)
team.runner: roundrobin
team.runner-hwaddr-policy: --
team.runner-tx-hash: --
team.runner-tx-balancer: --
team.runner-tx-balancer-interval: -1 (unset)
team.runner-active: yes
team.runner-fast-rate: no
team.runner-sys-prio: -1 (unset)
team.runner-min-ports: -1 (unset)
team.runner-agg-select-policy: --
team.link-watchers: name=ethtool
proxy.method: none
proxy.browser-only: no
proxy.pac-url: --
proxy.pac-script: --

View File

@@ -0,0 +1 @@
[{"connection_id":"team1","connection_uuid":"a85e0eba-7140-4963-963d-ca9a0f6516ed","connection_stable_id":null,"connection_type":"802-3-ethernet","connection_interface_name":null,"connection_autoconnect":"yes","connection_autoconnect_priority":0,"connection_autoconnect_retries":-1,"connection_autoconnect_retries_text":"default","connection_multi_connect":0,"connection_multi_connect_text":"default","connection_auth_retries":-1,"connection_timestamp":0,"connection_read_only":"no","connection_permissions":null,"connection_zone":null,"connection_master":"d229f048-5c75-40f4-a7ff-61174546c506","connection_slave_type":"team","connection_autoconnect_slaves":-1,"connection_autoconnect_slaves_text":"default","connection_secondaries":null,"connection_gateway_ping_timeout":0,"connection_metered":"unknown","connection_lldp":"default","connection_mdns":-1,"connection_mdns_text":"default","connection_llmnr":-1,"connection_llmnr_text":"default","connection_dns_over_tls":-1,"connection_dns_over_tls_text":"default","connection_wait_device_timeout":-1,"802_3_ethernet_port":null,"802_3_ethernet_speed":0,"802_3_ethernet_duplex":null,"802_3_ethernet_auto_negotiate":"no","802_3_ethernet_mac_address":null,"802_3_ethernet_cloned_mac_address":null,"802_3_ethernet_generate_mac_address_mask":null,"802_3_ethernet_mac_address_blacklist":null,"802_3_ethernet_mtu":"auto","802_3_ethernet_s390_subchannels":null,"802_3_ethernet_s390_nettype":null,"802_3_ethernet_s390_options":null,"802_3_ethernet_wake_on_lan":"default","802_3_ethernet_wake_on_lan_password":null,"802_3_ethernet_accept_all_mac_addresses":-1,"802_3_ethernet_accept_all_mac_addresses_text":"default","team_port_config":null,"team_port_queue_id":0,"team_port_queue_id_text":"default","team_port_prio":0,"team_port_prio_text":"unset","team_port_sticky":"no","team_port_lacp_prio":0,"team_port_lacp_key":0,"team_port_lacp_key_text":"default","team_port_link_watchers":null}]

View File

@@ -0,0 +1,47 @@
connection.id: team1
connection.uuid: a85e0eba-7140-4963-963d-ca9a0f6516ed
connection.stable-id: --
connection.type: 802-3-ethernet
connection.interface-name: --
connection.autoconnect: yes
connection.autoconnect-priority: 0
connection.autoconnect-retries: -1 (default)
connection.multi-connect: 0 (default)
connection.auth-retries: -1
connection.timestamp: 0
connection.read-only: no
connection.permissions: --
connection.zone: --
connection.master: d229f048-5c75-40f4-a7ff-61174546c506
connection.slave-type: team
connection.autoconnect-slaves: -1 (default)
connection.secondaries: --
connection.gateway-ping-timeout: 0
connection.metered: unknown
connection.lldp: default
connection.mdns: -1 (default)
connection.llmnr: -1 (default)
connection.dns-over-tls: -1 (default)
connection.wait-device-timeout: -1
802-3-ethernet.port: --
802-3-ethernet.speed: 0
802-3-ethernet.duplex: --
802-3-ethernet.auto-negotiate: no
802-3-ethernet.mac-address: --
802-3-ethernet.cloned-mac-address: --
802-3-ethernet.generate-mac-address-mask:--
802-3-ethernet.mac-address-blacklist: --
802-3-ethernet.mtu: auto
802-3-ethernet.s390-subchannels: --
802-3-ethernet.s390-nettype: --
802-3-ethernet.s390-options: --
802-3-ethernet.wake-on-lan: default
802-3-ethernet.wake-on-lan-password: --
802-3-ethernet.accept-all-mac-addresses:-1 (default)
team-port.config: --
team-port.queue-id: 0 (default)
team-port.prio: 0 (unset)
team-port.sticky: no
team-port.lacp-prio: 0
team-port.lacp-key: 0 (default)
team-port.link-watchers: --

View File

@@ -0,0 +1 @@
[{"connection_id":"team1","connection_uuid":"a85e0eba-7140-4963-963d-ca9a0f6516ed","connection_stable_id":null,"connection_type":"802-3-ethernet","connection_interface_name":null,"connection_autoconnect":"yes","connection_autoconnect_priority":0,"connection_autoconnect_retries":-1,"connection_autoconnect_retries_text":"default","connection_multi_connect":0,"connection_multi_connect_text":"default","connection_auth_retries":-1,"connection_timestamp":0,"connection_read_only":"no","connection_permissions":null,"connection_zone":null,"connection_master":"d229f048-5c75-40f4-a7ff-61174546c506","connection_slave_type":"team","connection_autoconnect_slaves":-1,"connection_autoconnect_slaves_text":"default","connection_secondaries":null,"connection_gateway_ping_timeout":0,"connection_metered":"unknown","connection_lldp":"default","connection_mdns":-1,"connection_mdns_text":"default","connection_llmnr":-1,"connection_llmnr_text":"default","connection_dns_over_tls":-1,"connection_dns_over_tls_text":"default","connection_wait_device_timeout":-1,"802_3_ethernet_port":null,"802_3_ethernet_speed":0,"802_3_ethernet_duplex":null,"802_3_ethernet_auto_negotiate":"no","802_3_ethernet_mac_address":null,"802_3_ethernet_cloned_mac_address":null,"802_3_ethernet_generate_mac_address_mask":null,"802_3_ethernet_mac_address_blacklist":null,"802_3_ethernet_mtu":"auto","802_3_ethernet_s390_subchannels":null,"802_3_ethernet_s390_nettype":null,"802_3_ethernet_s390_options":null,"802_3_ethernet_wake_on_lan":"default","802_3_ethernet_wake_on_lan_password":null,"802_3_ethernet_accept_all_mac_addresses":-1,"802_3_ethernet_accept_all_mac_addresses_text":"default","team_port_config":{"queue_id":0,"prio":0,"lacp_prio":0,"lacp_key":0},"team_port_queue_id":0,"team_port_queue_id_text":"default","team_port_prio":0,"team_port_prio_text":"unset","team_port_sticky":"no","team_port_lacp_prio":0,"team_port_lacp_key":0,"team_port_lacp_key_text":"default","team_port_link_watchers":null}]

View File

@@ -0,0 +1,52 @@
connection.id: team1
connection.uuid: a85e0eba-7140-4963-963d-ca9a0f6516ed
connection.stable-id: --
connection.type: 802-3-ethernet
connection.interface-name: --
connection.autoconnect: yes
connection.autoconnect-priority: 0
connection.autoconnect-retries: -1 (default)
connection.multi-connect: 0 (default)
connection.auth-retries: -1
connection.timestamp: 0
connection.read-only: no
connection.permissions: --
connection.zone: --
connection.master: d229f048-5c75-40f4-a7ff-61174546c506
connection.slave-type: team
connection.autoconnect-slaves: -1 (default)
connection.secondaries: --
connection.gateway-ping-timeout: 0
connection.metered: unknown
connection.lldp: default
connection.mdns: -1 (default)
connection.llmnr: -1 (default)
connection.dns-over-tls: -1 (default)
connection.wait-device-timeout: -1
802-3-ethernet.port: --
802-3-ethernet.speed: 0
802-3-ethernet.duplex: --
802-3-ethernet.auto-negotiate: no
802-3-ethernet.mac-address: --
802-3-ethernet.cloned-mac-address: --
802-3-ethernet.generate-mac-address-mask:--
802-3-ethernet.mac-address-blacklist: --
802-3-ethernet.mtu: auto
802-3-ethernet.s390-subchannels: --
802-3-ethernet.s390-nettype: --
802-3-ethernet.s390-options: --
802-3-ethernet.wake-on-lan: default
802-3-ethernet.wake-on-lan-password: --
802-3-ethernet.accept-all-mac-addresses:-1 (default)
team-port.config: {
"queue_id": 0,
"prio": 0,
"lacp_prio": 0,
"lacp_key": 0
}
team-port.queue-id: 0 (default)
team-port.prio: 0 (unset)
team-port.sticky: no
team-port.lacp-prio: 0
team-port.lacp-key: 0 (default)
team-port.link-watchers: --

View File

@@ -0,0 +1 @@
[{"total_files":23784,"regular_files":23191,"dir_files":593,"total_created_files":2651,"created_regular_files":2611,"created_dir_files":40,"deleted_files":0,"transferred_files":2629,"transferred_file_size":6880000000000,"literal_data":0,"matched_data":0,"file_list_size":98100,"file_list_generation_time":0.001,"file_list_transfer_time":0.0,"type":"summary","sent":8990,"received":1290000,"bytes_sec":370210.0,"total_size":6880000000000,"speedup":5311650.06}]

View File

@@ -0,0 +1 @@
[{"summary":{"total_files":23784,"regular_files":23191,"dir_files":593,"total_created_files":2651,"created_regular_files":2611,"created_dir_files":40,"deleted_files":0,"transferred_files":2629,"transferred_file_size":6880000000000,"literal_data":0,"matched_data":0,"file_list_size":98100,"file_list_generation_time":0.001,"file_list_transfer_time":0.0,"sent":8990,"received":1290000,"bytes_sec":370210.0,"total_size":6880000000000,"speedup":5311650.06},"files":[]}]

View File

@@ -0,0 +1,56 @@
rsync[1817530] (server sender) heap statistics:
arena: 1204224 (bytes from sbrk)
ordblks: 46 (chunks not in use)
rsync[1007426] (receiver) heap statistics:
arena: 9244672 (bytes from sbrk)
ordblks: 57 (chunks not in use)
smblks: 1 (free fastbin blocks)
hblks: 1 (chunks from mmap)
hblkhd: 266240 (bytes from mmap)
allmem: 9510912 (bytes from sbrk + mmap)
usmblks: 0 (always 0)
fsmblks: 96 (bytes in freed fastbin blocks)
uordblks: 486480 (bytes used)
fordblks: 8758192 (bytes free)
keepcost: 133856 (bytes in releasable chunk)
smblks: 2 (free fastbin blocks)
hblks: 1 (chunks from mmap)
hblkhd: 266240 (bytes from mmap)
allmem: 1470464 (bytes from sbrk + mmap)
usmblks: 0 (always 0)
fsmblks: 192 (bytes in freed fastbin blocks)
uordblks: 478288 (bytes used)
fordblks: 725936 (bytes free)
keepcost: 427216 (bytes in releasable chunk)
rsync[1007424] (generator) heap statistics:
arena: 1384448 (bytes from sbrk)
ordblks: 6 (chunks not in use)
smblks: 1 (free fastbin blocks)
hblks: 1 (chunks from mmap)
hblkhd: 266240 (bytes from mmap)
allmem: 1650688 (bytes from sbrk + mmap)
usmblks: 0 (always 0)
fsmblks: 96 (bytes in freed fastbin blocks)
uordblks: 486160 (bytes used)
fordblks: 898288 (bytes free)
keepcost: 132272 (bytes in releasable chunk)
Number of files: 23,784 (reg: 23,191, dir: 593)
Number of created files: 2,651 (reg: 2,611, dir: 40)
Number of deleted files: 0
Number of regular files transferred: 2,629
Total file size: 6.88T bytes
Total transferred file size: 759.17G bytes
Literal data: 0 bytes
Matched data: 0 bytes
File list size: 98.10K
File list generation time: 0.001 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 8.99K
Total bytes received: 1.29M
sent 8.99K bytes received 1.29M bytes 370.21K bytes/sec
total size is 6.88T speedup is 5,311,650.06 (DRY RUN)

View File

@@ -0,0 +1,78 @@
[
{
"type": "header",
"destination_ip": "2a04:4e42:200::323",
"destination_name": "turner-tls.map.fastly.net",
"max_hops": 5,
"data_bytes": 12
},
{
"type": "hop",
"hop": 1,
"probes": []
},
{
"type": "hop",
"hop": 2,
"probes": [
{
"annotation": null,
"asn": null,
"ip": null,
"name": null,
"rtt": 27.635
},
{
"annotation": null,
"asn": null,
"ip": null,
"name": null,
"rtt": 20.383
},
{
"annotation": null,
"asn": null,
"ip": null,
"name": null,
"rtt": 23.438
}
]
},
{
"type": "hop",
"hop": 3,
"probes": []
},
{
"type": "hop",
"hop": 4,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2001:1890:ff:ff08:12:242:117:16",
"name": null,
"rtt": 20.118
},
{
"annotation": null,
"asn": null,
"ip": "2001:1890:ff:ff08:12:242:117:16",
"name": null,
"rtt": 20.327
},
{
"annotation": null,
"asn": null,
"ip": "2001:1890:ff:ff08:12:242:117:16",
"name": null,
"rtt": 21.213
}
]
},
{
"type": "hop",
"hop": 5,
"probes": []
}
]

View File

@@ -0,0 +1 @@
{"destination_ip":"2a04:4e42:200::323","destination_name":"turner-tls.map.fastly.net","max_hops":5,"data_bytes":12,"hops":[{"hop":1,"probes":[]},{"hop":2,"probes":[{"annotation":null,"asn":null,"ip":null,"name":null,"rtt":27.635},{"annotation":null,"asn":null,"ip":null,"name":null,"rtt":20.383},{"annotation":null,"asn":null,"ip":null,"name":null,"rtt":23.438}]},{"hop":3,"probes":[]},{"hop":4,"probes":[{"annotation":null,"asn":null,"ip":"2001:1890:ff:ff08:12:242:117:16","name":null,"rtt":20.118},{"annotation":null,"asn":null,"ip":"2001:1890:ff:ff08:12:242:117:16","name":null,"rtt":20.327},{"annotation":null,"asn":null,"ip":"2001:1890:ff:ff08:12:242:117:16","name":null,"rtt":21.213}]},{"hop":5,"probes":[]}]}

View File

@@ -0,0 +1,6 @@
traceroute6 to turner-tls.map.fastly.net (2a04:4e42:200::323) from 2600:1700:bab0:d40:985:f00a:98bd:f142, 5 hops max, 12 byte packets
1 * * *
2 ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 27.635 ms 20.383 ms 23.438 ms
3 * * *
4 2001:1890:ff:ff08:12:242:117:16 20.118 ms 20.327 ms 21.213 ms
5 * * *

View File

@@ -0,0 +1,225 @@
[
{
"type": "header",
"destination_ip": "199.58.80.40",
"destination_name": "www.koumbit.org",
"max_hops": 30,
"data_bytes": 60
},
{
"type": "hop",
"hop": 1,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "192.168.2.1",
"name": null,
"rtt": 0.967
},
{
"annotation": null,
"asn": null,
"ip": "192.168.2.1",
"name": null,
"rtt": 1.022
},
{
"annotation": null,
"asn": null,
"ip": "192.168.2.1",
"name": null,
"rtt": 1.204
}
]
},
{
"type": "hop",
"hop": 2,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "24.212.242.17",
"name": null,
"rtt": 10.176
},
{
"annotation": null,
"asn": null,
"ip": "24.212.242.17",
"name": null,
"rtt": 18.136
},
{
"annotation": null,
"asn": null,
"ip": "24.212.242.17",
"name": null,
"rtt": 18.244
}
]
},
{
"type": "hop",
"hop": 3,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "10.170.192.58",
"name": null,
"rtt": 19.396
},
{
"annotation": null,
"asn": null,
"ip": "10.170.192.58",
"name": null,
"rtt": 19.575
},
{
"annotation": null,
"asn": null,
"ip": "10.170.192.58",
"name": null,
"rtt": 19.572
}
]
},
{
"type": "hop",
"hop": 4,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "192.171.61.61",
"name": null,
"rtt": 23.072
},
{
"annotation": null,
"asn": null,
"ip": "206.248.155.109",
"name": null,
"rtt": 17.073
},
{
"annotation": null,
"asn": null,
"ip": "192.171.63.17",
"name": null,
"rtt": 23.308
}
]
},
{
"type": "hop",
"hop": 5,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "206.248.189.97",
"name": null,
"rtt": 20.521
},
{
"annotation": null,
"asn": null,
"ip": "206.248.189.97",
"name": null,
"rtt": 22.837
},
{
"annotation": null,
"asn": null,
"ip": "206.248.189.97",
"name": null,
"rtt": 23.194
}
]
},
{
"type": "hop",
"hop": 6,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "198.179.18.41",
"name": null,
"rtt": 18.334
},
{
"annotation": null,
"asn": null,
"ip": "198.179.18.41",
"name": null,
"rtt": 17.894
},
{
"annotation": null,
"asn": null,
"ip": "198.179.18.41",
"name": null,
"rtt": 17.792
}
]
},
{
"type": "hop",
"hop": 7,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "64.15.69.54",
"name": null,
"rtt": 17.056
},
{
"annotation": null,
"asn": null,
"ip": "64.15.69.54",
"name": null,
"rtt": 14.033
},
{
"annotation": null,
"asn": null,
"ip": "64.15.69.54",
"name": null,
"rtt": 12.351
}
]
},
{
"type": "hop",
"hop": 8,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "199.58.80.40",
"name": null,
"rtt": 18.203
},
{
"annotation": null,
"asn": null,
"ip": "199.58.80.40",
"name": null,
"rtt": 18.789
},
{
"annotation": null,
"asn": null,
"ip": "199.58.80.40",
"name": null,
"rtt": 18.906
}
]
}
]

View File

@@ -1 +1 @@
{"destination_ip":"199.58.80.40","destination_name":"www.koumbit.org","hops":[{"hop":1,"probes":[{"annotation":null,"asn":null,"ip":"192.168.2.1","name":null,"rtt":0.967},{"annotation":null,"asn":null,"ip":"192.168.2.1","name":null,"rtt":1.022},{"annotation":null,"asn":null,"ip":"192.168.2.1","name":null,"rtt":1.204}]},{"hop":2,"probes":[{"annotation":null,"asn":null,"ip":"24.212.242.17","name":null,"rtt":10.176},{"annotation":null,"asn":null,"ip":"24.212.242.17","name":null,"rtt":18.136},{"annotation":null,"asn":null,"ip":"24.212.242.17","name":null,"rtt":18.244}]},{"hop":3,"probes":[{"annotation":null,"asn":null,"ip":"10.170.192.58","name":null,"rtt":19.396},{"annotation":null,"asn":null,"ip":"10.170.192.58","name":null,"rtt":19.575},{"annotation":null,"asn":null,"ip":"10.170.192.58","name":null,"rtt":19.572}]},{"hop":4,"probes":[{"annotation":null,"asn":null,"ip":"192.171.61.61","name":null,"rtt":23.072},{"annotation":null,"asn":null,"ip":"206.248.155.109","name":null,"rtt":17.073},{"annotation":null,"asn":null,"ip":"192.171.63.17","name":null,"rtt":23.308}]},{"hop":5,"probes":[{"annotation":null,"asn":null,"ip":"206.248.189.97","name":null,"rtt":20.521},{"annotation":null,"asn":null,"ip":"206.248.189.97","name":null,"rtt":22.837},{"annotation":null,"asn":null,"ip":"206.248.189.97","name":null,"rtt":23.194}]},{"hop":6,"probes":[{"annotation":null,"asn":null,"ip":"198.179.18.41","name":null,"rtt":18.334},{"annotation":null,"asn":null,"ip":"198.179.18.41","name":null,"rtt":17.894},{"annotation":null,"asn":null,"ip":"198.179.18.41","name":null,"rtt":17.792}]},{"hop":7,"probes":[{"annotation":null,"asn":null,"ip":"64.15.69.54","name":null,"rtt":17.056},{"annotation":null,"asn":null,"ip":"64.15.69.54","name":null,"rtt":14.033},{"annotation":null,"asn":null,"ip":"64.15.69.54","name":null,"rtt":12.351}]},{"hop":8,"probes":[{"annotation":null,"asn":null,"ip":"199.58.80.40","name":null,"rtt":18.203},{"annotation":null,"asn":null,"ip":"199.58.80.40","name":null,"rtt":18.789},{"annotation":null,"asn":null,"ip":"199.58.80.40","name":null,"rtt":18.906}]}]}
{"destination_ip":"199.58.80.40","destination_name":"www.koumbit.org","max_hops":30,"data_bytes":60,"hops":[{"hop":1,"probes":[{"annotation":null,"asn":null,"ip":"192.168.2.1","name":null,"rtt":0.967},{"annotation":null,"asn":null,"ip":"192.168.2.1","name":null,"rtt":1.022},{"annotation":null,"asn":null,"ip":"192.168.2.1","name":null,"rtt":1.204}]},{"hop":2,"probes":[{"annotation":null,"asn":null,"ip":"24.212.242.17","name":null,"rtt":10.176},{"annotation":null,"asn":null,"ip":"24.212.242.17","name":null,"rtt":18.136},{"annotation":null,"asn":null,"ip":"24.212.242.17","name":null,"rtt":18.244}]},{"hop":3,"probes":[{"annotation":null,"asn":null,"ip":"10.170.192.58","name":null,"rtt":19.396},{"annotation":null,"asn":null,"ip":"10.170.192.58","name":null,"rtt":19.575},{"annotation":null,"asn":null,"ip":"10.170.192.58","name":null,"rtt":19.572}]},{"hop":4,"probes":[{"annotation":null,"asn":null,"ip":"192.171.61.61","name":null,"rtt":23.072},{"annotation":null,"asn":null,"ip":"206.248.155.109","name":null,"rtt":17.073},{"annotation":null,"asn":null,"ip":"192.171.63.17","name":null,"rtt":23.308}]},{"hop":5,"probes":[{"annotation":null,"asn":null,"ip":"206.248.189.97","name":null,"rtt":20.521},{"annotation":null,"asn":null,"ip":"206.248.189.97","name":null,"rtt":22.837},{"annotation":null,"asn":null,"ip":"206.248.189.97","name":null,"rtt":23.194}]},{"hop":6,"probes":[{"annotation":null,"asn":null,"ip":"198.179.18.41","name":null,"rtt":18.334},{"annotation":null,"asn":null,"ip":"198.179.18.41","name":null,"rtt":17.894},{"annotation":null,"asn":null,"ip":"198.179.18.41","name":null,"rtt":17.792}]},{"hop":7,"probes":[{"annotation":null,"asn":null,"ip":"64.15.69.54","name":null,"rtt":17.056},{"annotation":null,"asn":null,"ip":"64.15.69.54","name":null,"rtt":14.033},{"annotation":null,"asn":null,"ip":"64.15.69.54","name":null,"rtt":12.351}]},{"hop":8,"probes":[{"annotation":null,"asn":null,"ip":"199.58.80.40","name":null,"rtt":18.203},{"annotation":null,"asn":null,"ip":"199.58.80.40","name":null,"rtt":18.789},{"annotation":null,"asn":null,"ip":"199.58.80.40","name":null,"rtt":18.906}]}]}

View File

@@ -0,0 +1,333 @@
[
{
"type": "header",
"destination_ip": "2607:f8b0:4020:806::2004",
"destination_name": "www.google.com",
"max_hops": 30,
"data_bytes": 80
},
{
"type": "hop",
"hop": 1,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2605:9000:402:6a01::1",
"name": null,
"rtt": 4.181
},
{
"annotation": null,
"asn": null,
"ip": "2605:9000:402:6a01::1",
"name": null,
"rtt": 4.294
},
{
"annotation": null,
"asn": null,
"ip": "2605:9000:402:6a01::1",
"name": null,
"rtt": 4.253
}
]
},
{
"type": "hop",
"hop": 2,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2605:9000:0:400a::f1",
"name": null,
"rtt": 0.354
},
{
"annotation": null,
"asn": null,
"ip": "2605:9000:0:400a::f1",
"name": null,
"rtt": 0.532
},
{
"annotation": null,
"asn": null,
"ip": "2605:9000:0:400a::f1",
"name": null,
"rtt": 0.484
}
]
},
{
"type": "hop",
"hop": 3,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:40:100::51",
"name": null,
"rtt": 15.284
},
{
"annotation": null,
"asn": null,
"ip": "2605:9000:0:101::1",
"name": null,
"rtt": 4.864
},
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:40:100::51",
"name": null,
"rtt": 15.415
}
]
},
{
"type": "hop",
"hop": 4,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:40:100::51",
"name": null,
"rtt": 15.379
},
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:300:200::202",
"name": null,
"rtt": 12.709
},
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:40:100::51",
"name": null,
"rtt": 15.289
}
]
},
{
"type": "hop",
"hop": 5,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:1900:100::12",
"name": null,
"rtt": 10.02
},
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:1900:100::12",
"name": null,
"rtt": 10.212
},
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:1900:100::12",
"name": null,
"rtt": 10.163
}
]
},
{
"type": "hop",
"hop": 6,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:1900:100::12",
"name": null,
"rtt": 10.113
},
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:400:700::17",
"name": null,
"rtt": 8.399
},
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:1900:100::12",
"name": null,
"rtt": 10.215
}
]
},
{
"type": "hop",
"hop": 7,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2001:4860:0:1127::2",
"name": null,
"rtt": 9.11
},
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:400:700::17",
"name": null,
"rtt": 8.476
},
{
"annotation": null,
"asn": null,
"ip": "2001:5a0:400:700::17",
"name": null,
"rtt": 8.38
}
]
},
{
"type": "hop",
"hop": 8,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2001:4860::8:4000:cd80",
"name": null,
"rtt": 9.428
},
{
"annotation": null,
"asn": null,
"ip": "2001:4860:0:1128::14",
"name": null,
"rtt": 9.36
},
{
"annotation": null,
"asn": null,
"ip": "2001:4860::8:4000:cd80",
"name": null,
"rtt": 9.229
}
]
},
{
"type": "hop",
"hop": 9,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2001:4860::9:4001:d508",
"name": null,
"rtt": 9.376
},
{
"annotation": null,
"asn": null,
"ip": "2001:4860::c:4002:652a",
"name": null,
"rtt": 9.105
},
{
"annotation": null,
"asn": null,
"ip": "2001:4860::c:4002:6523",
"name": null,
"rtt": 9.384
}
]
},
{
"type": "hop",
"hop": 10,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2001:4860:0:11da::1",
"name": null,
"rtt": 8.489
},
{
"annotation": null,
"asn": null,
"ip": "2001:4860::9:4001:d508",
"name": null,
"rtt": 8.978
},
{
"annotation": null,
"asn": null,
"ip": "2001:4860::1c:4000:f5eb",
"name": null,
"rtt": 9.64
}
]
},
{
"type": "hop",
"hop": 11,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2001:4860:0:1::c73",
"name": null,
"rtt": 9.596
},
{
"annotation": null,
"asn": null,
"ip": "2001:4860:0:1::c73",
"name": null,
"rtt": 9.077
},
{
"annotation": null,
"asn": null,
"ip": "2001:4860:0:1::c73",
"name": null,
"rtt": 9.724
}
]
},
{
"type": "hop",
"hop": 12,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "2607:f8b0:4020:806::2004",
"name": null,
"rtt": 8.086
},
{
"annotation": null,
"asn": null,
"ip": "2607:f8b0:4020:806::2004",
"name": null,
"rtt": 8.091
},
{
"annotation": null,
"asn": null,
"ip": "2607:f8b0:4020:806::2004",
"name": null,
"rtt": 8.436
}
]
}
]

View File

@@ -1 +1 @@
{"destination_ip":"2607:f8b0:4020:806::2004","destination_name":"www.google.com","hops":[{"hop":1,"probes":[{"annotation":null,"asn":null,"ip":"2605:9000:402:6a01::1","name":null,"rtt":4.181},{"annotation":null,"asn":null,"ip":"2605:9000:402:6a01::1","name":null,"rtt":4.294},{"annotation":null,"asn":null,"ip":"2605:9000:402:6a01::1","name":null,"rtt":4.253}]},{"hop":2,"probes":[{"annotation":null,"asn":null,"ip":"2605:9000:0:400a::f1","name":null,"rtt":0.354},{"annotation":null,"asn":null,"ip":"2605:9000:0:400a::f1","name":null,"rtt":0.532},{"annotation":null,"asn":null,"ip":"2605:9000:0:400a::f1","name":null,"rtt":0.484}]},{"hop":3,"probes":[{"annotation":null,"asn":null,"ip":"2001:5a0:40:100::51","name":null,"rtt":15.284},{"annotation":null,"asn":null,"ip":"2605:9000:0:101::1","name":null,"rtt":4.864},{"annotation":null,"asn":null,"ip":"2001:5a0:40:100::51","name":null,"rtt":15.415}]},{"hop":4,"probes":[{"annotation":null,"asn":null,"ip":"2001:5a0:40:100::51","name":null,"rtt":15.379},{"annotation":null,"asn":null,"ip":"2001:5a0:300:200::202","name":null,"rtt":12.709},{"annotation":null,"asn":null,"ip":"2001:5a0:40:100::51","name":null,"rtt":15.289}]},{"hop":5,"probes":[{"annotation":null,"asn":null,"ip":"2001:5a0:1900:100::12","name":null,"rtt":10.02},{"annotation":null,"asn":null,"ip":"2001:5a0:1900:100::12","name":null,"rtt":10.212},{"annotation":null,"asn":null,"ip":"2001:5a0:1900:100::12","name":null,"rtt":10.163}]},{"hop":6,"probes":[{"annotation":null,"asn":null,"ip":"2001:5a0:1900:100::12","name":null,"rtt":10.113},{"annotation":null,"asn":null,"ip":"2001:5a0:400:700::17","name":null,"rtt":8.399},{"annotation":null,"asn":null,"ip":"2001:5a0:1900:100::12","name":null,"rtt":10.215}]},{"hop":7,"probes":[{"annotation":null,"asn":null,"ip":"2001:4860:0:1127::2","name":null,"rtt":9.11},{"annotation":null,"asn":null,"ip":"2001:5a0:400:700::17","name":null,"rtt":8.476},{"annotation":null,"asn":null,"ip":"2001:5a0:400:700::17","name":null,"rtt":8.38}]},{"hop":8,"probes":[{"annotation":null,"asn":null,"ip":"2001:4860::8:4000:cd80","name":null,"rtt":9.428},{"annotation":null,"asn":null,"ip":"2001:4860:0:1128::14","name":null,"rtt":9.36},{"annotation":null,"asn":null,"ip":"2001:4860::8:4000:cd80","name":null,"rtt":9.229}]},{"hop":9,"probes":[{"annotation":null,"asn":null,"ip":"2001:4860::9:4001:d508","name":null,"rtt":9.376},{"annotation":null,"asn":null,"ip":"2001:4860::c:4002:652a","name":null,"rtt":9.105},{"annotation":null,"asn":null,"ip":"2001:4860::c:4002:6523","name":null,"rtt":9.384}]},{"hop":10,"probes":[{"annotation":null,"asn":null,"ip":"2001:4860:0:11da::1","name":null,"rtt":8.489},{"annotation":null,"asn":null,"ip":"2001:4860::9:4001:d508","name":null,"rtt":8.978},{"annotation":null,"asn":null,"ip":"2001:4860::1c:4000:f5eb","name":null,"rtt":9.64}]},{"hop":11,"probes":[{"annotation":null,"asn":null,"ip":"2001:4860:0:1::c73","name":null,"rtt":9.596},{"annotation":null,"asn":null,"ip":"2001:4860:0:1::c73","name":null,"rtt":9.077},{"annotation":null,"asn":null,"ip":"2001:4860:0:1::c73","name":null,"rtt":9.724}]},{"hop":12,"probes":[{"annotation":null,"asn":null,"ip":"2607:f8b0:4020:806::2004","name":null,"rtt":8.086},{"annotation":null,"asn":null,"ip":"2607:f8b0:4020:806::2004","name":null,"rtt":8.091},{"annotation":null,"asn":null,"ip":"2607:f8b0:4020:806::2004","name":null,"rtt":8.436}]}]}
{"destination_ip":"2607:f8b0:4020:806::2004","destination_name":"www.google.com","max_hops":30,"data_bytes":80,"hops":[{"hop":1,"probes":[{"annotation":null,"asn":null,"ip":"2605:9000:402:6a01::1","name":null,"rtt":4.181},{"annotation":null,"asn":null,"ip":"2605:9000:402:6a01::1","name":null,"rtt":4.294},{"annotation":null,"asn":null,"ip":"2605:9000:402:6a01::1","name":null,"rtt":4.253}]},{"hop":2,"probes":[{"annotation":null,"asn":null,"ip":"2605:9000:0:400a::f1","name":null,"rtt":0.354},{"annotation":null,"asn":null,"ip":"2605:9000:0:400a::f1","name":null,"rtt":0.532},{"annotation":null,"asn":null,"ip":"2605:9000:0:400a::f1","name":null,"rtt":0.484}]},{"hop":3,"probes":[{"annotation":null,"asn":null,"ip":"2001:5a0:40:100::51","name":null,"rtt":15.284},{"annotation":null,"asn":null,"ip":"2605:9000:0:101::1","name":null,"rtt":4.864},{"annotation":null,"asn":null,"ip":"2001:5a0:40:100::51","name":null,"rtt":15.415}]},{"hop":4,"probes":[{"annotation":null,"asn":null,"ip":"2001:5a0:40:100::51","name":null,"rtt":15.379},{"annotation":null,"asn":null,"ip":"2001:5a0:300:200::202","name":null,"rtt":12.709},{"annotation":null,"asn":null,"ip":"2001:5a0:40:100::51","name":null,"rtt":15.289}]},{"hop":5,"probes":[{"annotation":null,"asn":null,"ip":"2001:5a0:1900:100::12","name":null,"rtt":10.02},{"annotation":null,"asn":null,"ip":"2001:5a0:1900:100::12","name":null,"rtt":10.212},{"annotation":null,"asn":null,"ip":"2001:5a0:1900:100::12","name":null,"rtt":10.163}]},{"hop":6,"probes":[{"annotation":null,"asn":null,"ip":"2001:5a0:1900:100::12","name":null,"rtt":10.113},{"annotation":null,"asn":null,"ip":"2001:5a0:400:700::17","name":null,"rtt":8.399},{"annotation":null,"asn":null,"ip":"2001:5a0:1900:100::12","name":null,"rtt":10.215}]},{"hop":7,"probes":[{"annotation":null,"asn":null,"ip":"2001:4860:0:1127::2","name":null,"rtt":9.11},{"annotation":null,"asn":null,"ip":"2001:5a0:400:700::17","name":null,"rtt":8.476},{"annotation":null,"asn":null,"ip":"2001:5a0:400:700::17","name":null,"rtt":8.38}]},{"hop":8,"probes":[{"annotation":null,"asn":null,"ip":"2001:4860::8:4000:cd80","name":null,"rtt":9.428},{"annotation":null,"asn":null,"ip":"2001:4860:0:1128::14","name":null,"rtt":9.36},{"annotation":null,"asn":null,"ip":"2001:4860::8:4000:cd80","name":null,"rtt":9.229}]},{"hop":9,"probes":[{"annotation":null,"asn":null,"ip":"2001:4860::9:4001:d508","name":null,"rtt":9.376},{"annotation":null,"asn":null,"ip":"2001:4860::c:4002:652a","name":null,"rtt":9.105},{"annotation":null,"asn":null,"ip":"2001:4860::c:4002:6523","name":null,"rtt":9.384}]},{"hop":10,"probes":[{"annotation":null,"asn":null,"ip":"2001:4860:0:11da::1","name":null,"rtt":8.489},{"annotation":null,"asn":null,"ip":"2001:4860::9:4001:d508","name":null,"rtt":8.978},{"annotation":null,"asn":null,"ip":"2001:4860::1c:4000:f5eb","name":null,"rtt":9.64}]},{"hop":11,"probes":[{"annotation":null,"asn":null,"ip":"2001:4860:0:1::c73","name":null,"rtt":9.596},{"annotation":null,"asn":null,"ip":"2001:4860:0:1::c73","name":null,"rtt":9.077},{"annotation":null,"asn":null,"ip":"2001:4860:0:1::c73","name":null,"rtt":9.724}]},{"hop":12,"probes":[{"annotation":null,"asn":null,"ip":"2607:f8b0:4020:806::2004","name":null,"rtt":8.086},{"annotation":null,"asn":null,"ip":"2607:f8b0:4020:806::2004","name":null,"rtt":8.091},{"annotation":null,"asn":null,"ip":"2607:f8b0:4020:806::2004","name":null,"rtt":8.436}]}]}

View File

@@ -0,0 +1,113 @@
[
{
"type": "header",
"destination_ip": "199.58.80.40",
"destination_name": "www.koumbit.org",
"max_hops": 30,
"data_bytes": 60
},
{
"type": "hop",
"hop": 1,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "192.168.2.1",
"name": null,
"rtt": 3.425
}
]
},
{
"type": "hop",
"hop": 2,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "24.212.242.17",
"name": null,
"rtt": 16.153
}
]
},
{
"type": "hop",
"hop": 3,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "10.170.192.58",
"name": null,
"rtt": 17.231
}
]
},
{
"type": "hop",
"hop": 4,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "192.171.61.161",
"name": null,
"rtt": 25.393
}
]
},
{
"type": "hop",
"hop": 5,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "206.248.189.97",
"name": null,
"rtt": 25.322
}
]
},
{
"type": "hop",
"hop": 6,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "198.179.18.41",
"name": null,
"rtt": 23.755
}
]
},
{
"type": "hop",
"hop": 7,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "64.15.69.54",
"name": null,
"rtt": 25.091
}
]
},
{
"type": "hop",
"hop": 8,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "199.58.80.40",
"name": null,
"rtt": 25.196
}
]
}
]

View File

@@ -1 +1 @@
{"destination_ip":"199.58.80.40","destination_name":"www.koumbit.org","hops":[{"hop":1,"probes":[{"annotation":null,"asn":null,"ip":"192.168.2.1","name":null,"rtt":3.425}]},{"hop":2,"probes":[{"annotation":null,"asn":null,"ip":"24.212.242.17","name":null,"rtt":16.153}]},{"hop":3,"probes":[{"annotation":null,"asn":null,"ip":"10.170.192.58","name":null,"rtt":17.231}]},{"hop":4,"probes":[{"annotation":null,"asn":null,"ip":"192.171.61.161","name":null,"rtt":25.393}]},{"hop":5,"probes":[{"annotation":null,"asn":null,"ip":"206.248.189.97","name":null,"rtt":25.322}]},{"hop":6,"probes":[{"annotation":null,"asn":null,"ip":"198.179.18.41","name":null,"rtt":23.755}]},{"hop":7,"probes":[{"annotation":null,"asn":null,"ip":"64.15.69.54","name":null,"rtt":25.091}]},{"hop":8,"probes":[{"annotation":null,"asn":null,"ip":"199.58.80.40","name":null,"rtt":25.196}]}]}
{"destination_ip":"199.58.80.40","destination_name":"www.koumbit.org","max_hops":30,"data_bytes":60,"hops":[{"hop":1,"probes":[{"annotation":null,"asn":null,"ip":"192.168.2.1","name":null,"rtt":3.425}]},{"hop":2,"probes":[{"annotation":null,"asn":null,"ip":"24.212.242.17","name":null,"rtt":16.153}]},{"hop":3,"probes":[{"annotation":null,"asn":null,"ip":"10.170.192.58","name":null,"rtt":17.231}]},{"hop":4,"probes":[{"annotation":null,"asn":null,"ip":"192.171.61.161","name":null,"rtt":25.393}]},{"hop":5,"probes":[{"annotation":null,"asn":null,"ip":"206.248.189.97","name":null,"rtt":25.322}]},{"hop":6,"probes":[{"annotation":null,"asn":null,"ip":"198.179.18.41","name":null,"rtt":23.755}]},{"hop":7,"probes":[{"annotation":null,"asn":null,"ip":"64.15.69.54","name":null,"rtt":25.091}]},{"hop":8,"probes":[{"annotation":null,"asn":null,"ip":"199.58.80.40","name":null,"rtt":25.196}]}]}

View File

@@ -0,0 +1,414 @@
[
{
"type": "header",
"destination_ip": "173.207.22.152",
"destination_name": "http://google.es",
"max_hops": 30,
"data_bytes": 60
},
{
"type": "hop",
"hop": 1,
"probes": [
{
"annotation": "!P",
"asn": 1739,
"ip": "131.240.100.12",
"name": "131.240.100.12",
"rtt": 0.676
},
{
"annotation": "!",
"asn": 1739,
"ip": "131.240.100.12",
"name": "131.240.100.12",
"rtt": 0.763
},
{
"annotation": "!<500>",
"asn": 1739,
"ip": "131.240.100.12",
"name": "131.240.100.12",
"rtt": 0.91
}
]
},
{
"type": "hop",
"hop": 2,
"probes": [
{
"annotation": null,
"asn": 1739,
"ip": "131.232.1.26",
"name": "http://tut1-fw-vlan558.av.tut.fi",
"rtt": 0.266
},
{
"annotation": null,
"asn": 1739,
"ip": "131.232.1.26",
"name": "http://tut1-fw-vlan558.av.tut.fi",
"rtt": 0.404
},
{
"annotation": null,
"asn": 1739,
"ip": "131.232.1.26",
"name": "http://tut1-fw-vlan558.av.tut.fi",
"rtt": 0.493
}
]
},
{
"type": "hop",
"hop": 3,
"probes": [
{
"annotation": null,
"asn": 1739,
"ip": "131.232.1.20",
"name": "http://surf-gw-vlan557.av.tut.fi",
"rtt": 0.967
},
{
"annotation": null,
"asn": 1739,
"ip": "131.232.1.20",
"name": "http://surf-gw-vlan557.av.tut.fi",
"rtt": 0.961
},
{
"annotation": null,
"asn": 1739,
"ip": "131.232.1.20",
"name": "http://surf-gw-vlan557.av.tut.fi",
"rtt": 1.085
}
]
},
{
"type": "hop",
"hop": 4,
"probes": [
{
"annotation": null,
"asn": 1739,
"ip": "130.230.1.237",
"name": "http://funet-tut6-rtr-xe-0-0-0.cc.tut.fi",
"rtt": 1.096
},
{
"annotation": null,
"asn": 1739,
"ip": "130.230.1.237",
"name": "http://funet-tut6-rtr-xe-0-0-0.cc.tut.fi",
"rtt": 1.086
},
{
"annotation": null,
"asn": 1739,
"ip": "130.230.1.237",
"name": "http://funet-tut6-rtr-xe-0-0-0.cc.tut.fi",
"rtt": 1.049
}
]
},
{
"type": "hop",
"hop": 5,
"probes": [
{
"annotation": null,
"asn": 1741,
"ip": "86.50.255.220",
"name": "http://hameenlinna2-et-0-0-0-1.ip.funet.fi",
"rtt": 3.81
},
{
"annotation": null,
"asn": 1741,
"ip": "86.50.255.220",
"name": "http://hameenlinna2-et-0-0-0-1.ip.funet.fi",
"rtt": 3.845
},
{
"annotation": null,
"asn": 1741,
"ip": "86.50.255.220",
"name": "http://hameenlinna2-et-0-0-0-1.ip.funet.fi",
"rtt": 3.82
}
]
},
{
"type": "hop",
"hop": 6,
"probes": [
{
"annotation": null,
"asn": 1741,
"ip": "86.50.255.224",
"name": "http://hameenlinna1-et-0-0-1-1.ip.funet.fi",
"rtt": 29.055
},
{
"annotation": null,
"asn": 1741,
"ip": "86.50.255.224",
"name": "http://hameenlinna1-et-0-0-1-1.ip.funet.fi",
"rtt": 29.013
},
{
"annotation": null,
"asn": 1741,
"ip": "86.50.255.224",
"name": "http://hameenlinna1-et-0-0-1-1.ip.funet.fi",
"rtt": 28.977
}
]
},
{
"type": "hop",
"hop": 7,
"probes": [
{
"annotation": null,
"asn": 1741,
"ip": "86.50.255.223",
"name": "http://espoo2-et-0-1-2-1.ip.funet.fi",
"rtt": 3.468
},
{
"annotation": null,
"asn": 1741,
"ip": "86.50.255.223",
"name": "http://espoo2-et-0-1-2-1.ip.funet.fi",
"rtt": 8.007
},
{
"annotation": null,
"asn": 1741,
"ip": "86.50.255.223",
"name": "http://espoo2-et-0-1-2-1.ip.funet.fi",
"rtt": 7.89
}
]
},
{
"type": "hop",
"hop": 8,
"probes": [
{
"annotation": null,
"asn": 1741,
"ip": "86.50.255.232",
"name": "http://espoo1-et-0-1-7-1.ip.funet.fi",
"rtt": 13.498
},
{
"annotation": null,
"asn": 1741,
"ip": "86.50.255.232",
"name": "http://espoo1-et-0-1-7-1.ip.funet.fi",
"rtt": 13.307
},
{
"annotation": null,
"asn": 1741,
"ip": "86.50.255.232",
"name": "http://espoo1-et-0-1-7-1.ip.funet.fi",
"rtt": 13.399
}
]
},
{
"type": "hop",
"hop": 9,
"probes": [
{
"annotation": null,
"asn": 2603,
"ip": "109.105.102.168",
"name": "http://fi-csc2.nordu.net",
"rtt": 3.25
},
{
"annotation": null,
"asn": 2603,
"ip": "109.105.102.168",
"name": "http://fi-csc2.nordu.net",
"rtt": 3.268
},
{
"annotation": null,
"asn": 2603,
"ip": "109.105.102.168",
"name": "http://fi-csc2.nordu.net",
"rtt": 3.236
}
]
},
{
"type": "hop",
"hop": 10,
"probes": [
{
"annotation": null,
"asn": 2603,
"ip": "109.105.97.93",
"name": "http://se-fre.nordu.net",
"rtt": 9.418
},
{
"annotation": null,
"asn": 2603,
"ip": "109.105.97.93",
"name": "http://se-fre.nordu.net",
"rtt": 9.41
},
{
"annotation": null,
"asn": 2603,
"ip": "109.105.97.93",
"name": "http://se-fre.nordu.net",
"rtt": 9.369
}
]
},
{
"type": "hop",
"hop": 11,
"probes": [
{
"annotation": null,
"asn": 2603,
"ip": "109.105.97.27",
"name": "http://se-kst2.nordu.net",
"rtt": 9.617
},
{
"annotation": null,
"asn": 2603,
"ip": "109.105.97.27",
"name": "http://se-kst2.nordu.net",
"rtt": 9.594
},
{
"annotation": null,
"asn": 2603,
"ip": "109.105.97.27",
"name": "http://se-kst2.nordu.net",
"rtt": 9.603
}
]
},
{
"type": "hop",
"hop": 12,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "192.121.80.47",
"name": "http://as15169-10g-sk1.sthix.net",
"rtt": 10.01
},
{
"annotation": null,
"asn": 15169,
"ip": "72.14.196.42",
"name": "72.14.196.42",
"rtt": 9.182
},
{
"annotation": null,
"asn": 15169,
"ip": "72.14.196.42",
"name": "72.14.196.42",
"rtt": 44.983
}
]
},
{
"type": "hop",
"hop": 13,
"probes": [
{
"annotation": null,
"asn": 15169,
"ip": "108.170.254.49",
"name": "108.170.254.49",
"rtt": 10.852
},
{
"annotation": null,
"asn": 15169,
"ip": "108.170.254.33",
"name": "108.170.254.33",
"rtt": 11.185
},
{
"annotation": null,
"asn": 15169,
"ip": "108.170.254.49",
"name": "108.170.254.49",
"rtt": 10.876
}
]
},
{
"type": "hop",
"hop": 14,
"probes": [
{
"annotation": null,
"asn": 15169,
"ip": "209.85.242.11",
"name": "209.85.242.11",
"rtt": 10.192
},
{
"annotation": null,
"asn": 15169,
"ip": "209.85.242.11",
"name": "209.85.242.11",
"rtt": 10.471
},
{
"annotation": null,
"asn": 15169,
"ip": "209.85.242.11",
"name": "209.85.242.11",
"rtt": 10.502
}
]
},
{
"type": "hop",
"hop": 15,
"probes": [
{
"annotation": null,
"asn": 15169,
"ip": "172.217.21.163",
"name": "http://arn11s03-in-f3.1e100.net",
"rtt": 9.652
},
{
"annotation": null,
"asn": 15169,
"ip": "172.217.21.163",
"name": "http://arn11s03-in-f3.1e100.net",
"rtt": 9.664
},
{
"annotation": null,
"asn": 15169,
"ip": "172.217.21.163",
"name": "http://arn11s03-in-f3.1e100.net",
"rtt": 9.777
}
]
}
]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,260 @@
[
{
"type": "header",
"destination_ip": "216.58.194.46",
"destination_name": "google.com",
"max_hops": 30,
"data_bytes": 40
},
{
"type": "hop",
"hop": 1,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": 198.574
},
{
"annotation": null,
"asn": null,
"ip": "216.230.231.141",
"name": "216-230-231-141.static.houston.tx.oplink.net",
"rtt": 198.65
}
]
},
{
"type": "hop",
"hop": 2,
"probes": []
},
{
"type": "hop",
"hop": 3,
"probes": []
},
{
"type": "hop",
"hop": 4,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "72.14.242.34",
"name": "72.14.242.34",
"rtt": 4.932
},
{
"annotation": null,
"asn": null,
"ip": "72.14.242.34",
"name": "72.14.242.34",
"rtt": 4.945
},
{
"annotation": null,
"asn": null,
"ip": "72.14.242.34",
"name": "72.14.242.34",
"rtt": 4.951
}
]
},
{
"type": "hop",
"hop": 5,
"probes": []
},
{
"type": "hop",
"hop": 6,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "108.170.230.116",
"name": "108.170.230.116",
"rtt": 4.687
},
{
"annotation": null,
"asn": null,
"ip": "108.170.230.116",
"name": "108.170.230.116",
"rtt": 4.798
},
{
"annotation": null,
"asn": null,
"ip": "108.170.230.116",
"name": "108.170.230.116",
"rtt": 4.688
}
]
},
{
"type": "hop",
"hop": 7,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "108.170.252.130",
"name": "108.170.252.130",
"rtt": 4.825
},
{
"annotation": null,
"asn": null,
"ip": "108.170.252.130",
"name": "108.170.252.130",
"rtt": 4.844
},
{
"annotation": null,
"asn": null,
"ip": "108.170.252.130",
"name": "108.170.252.130",
"rtt": 4.797
}
]
},
{
"type": "hop",
"hop": 8,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "108.170.233.117",
"name": "108.170.233.117",
"rtt": 5.386
},
{
"annotation": null,
"asn": null,
"ip": "108.170.233.117",
"name": "108.170.233.117",
"rtt": 5.288
},
{
"annotation": null,
"asn": null,
"ip": "108.170.233.117",
"name": "108.170.233.117",
"rtt": 5.324
}
]
},
{
"type": "hop",
"hop": 9,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "216.239.63.250",
"name": "216.239.63.250",
"rtt": 5.305
},
{
"annotation": null,
"asn": null,
"ip": "216.239.63.250",
"name": "216.239.63.250",
"rtt": 5.369
},
{
"annotation": null,
"asn": null,
"ip": "216.239.63.250",
"name": "216.239.63.250",
"rtt": 5.406
}
]
},
{
"type": "hop",
"hop": 10,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "108.170.240.129",
"name": "108.170.240.129",
"rtt": 6.005
},
{
"annotation": null,
"asn": null,
"ip": "108.170.240.129",
"name": "108.170.240.129",
"rtt": 5.93
},
{
"annotation": null,
"asn": null,
"ip": "108.170.240.129",
"name": "108.170.240.129",
"rtt": 5.983
}
]
},
{
"type": "hop",
"hop": 11,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "209.85.242.53",
"name": "209.85.242.53",
"rtt": 4.973
},
{
"annotation": null,
"asn": null,
"ip": "209.85.242.53",
"name": "209.85.242.53",
"rtt": 4.973
},
{
"annotation": null,
"asn": null,
"ip": "209.85.242.53",
"name": "209.85.242.53",
"rtt": 4.979
}
]
},
{
"type": "hop",
"hop": 12,
"probes": [
{
"annotation": null,
"asn": null,
"ip": "216.58.194.46",
"name": "dfw25s12-in-f46.1e100.net",
"rtt": 4.871
},
{
"annotation": null,
"asn": null,
"ip": "216.58.194.46",
"name": "dfw25s12-in-f46.1e100.net",
"rtt": 4.884
},
{
"annotation": null,
"asn": null,
"ip": "216.58.194.46",
"name": "dfw25s12-in-f46.1e100.net",
"rtt": 4.863
}
]
}
]

View File

@@ -1 +1 @@
{"destination_ip": "216.58.194.46", "destination_name": "google.com", "hops": [{"hop": 1, "probes": [{"annotation": null, "asn": null, "ip": "216.230.231.141", "name": "216-230-231-141.static.houston.tx.oplink.net", "rtt": 198.574}, {"annotation": null, "asn": null, "ip": "216.230.231.141", "name": "216-230-231-141.static.houston.tx.oplink.net", "rtt": 198.65}]}, {"hop": 2, "probes": []}, {"hop": 3, "probes": []}, {"hop": 4, "probes": [{"annotation": null, "asn": null, "ip": "72.14.242.34", "name": "72.14.242.34", "rtt": 4.932}, {"annotation": null, "asn": null, "ip": "72.14.242.34", "name": "72.14.242.34", "rtt": 4.945}, {"annotation": null, "asn": null, "ip": "72.14.242.34", "name": "72.14.242.34", "rtt": 4.951}]}, {"hop": 5, "probes": []}, {"hop": 6, "probes": [{"annotation": null, "asn": null, "ip": "108.170.230.116", "name": "108.170.230.116", "rtt": 4.687}, {"annotation": null, "asn": null, "ip": "108.170.230.116", "name": "108.170.230.116", "rtt": 4.798}, {"annotation": null, "asn": null, "ip": "108.170.230.116", "name": "108.170.230.116", "rtt": 4.688}]}, {"hop": 7, "probes": [{"annotation": null, "asn": null, "ip": "108.170.252.130", "name": "108.170.252.130", "rtt": 4.825}, {"annotation": null, "asn": null, "ip": "108.170.252.130", "name": "108.170.252.130", "rtt": 4.844}, {"annotation": null, "asn": null, "ip": "108.170.252.130", "name": "108.170.252.130", "rtt": 4.797}]}, {"hop": 8, "probes": [{"annotation": null, "asn": null, "ip": "108.170.233.117", "name": "108.170.233.117", "rtt": 5.386}, {"annotation": null, "asn": null, "ip": "108.170.233.117", "name": "108.170.233.117", "rtt": 5.288}, {"annotation": null, "asn": null, "ip": "108.170.233.117", "name": "108.170.233.117", "rtt": 5.324}]}, {"hop": 9, "probes": [{"annotation": null, "asn": null, "ip": "216.239.63.250", "name": "216.239.63.250", "rtt": 5.305}, {"annotation": null, "asn": null, "ip": "216.239.63.250", "name": "216.239.63.250", "rtt": 5.369}, {"annotation": null, "asn": null, "ip": "216.239.63.250", "name": "216.239.63.250", "rtt": 5.406}]}, {"hop": 10, "probes": [{"annotation": null, "asn": null, "ip": "108.170.240.129", "name": "108.170.240.129", "rtt": 6.005}, {"annotation": null, "asn": null, "ip": "108.170.240.129", "name": "108.170.240.129", "rtt": 5.93}, {"annotation": null, "asn": null, "ip": "108.170.240.129", "name": "108.170.240.129", "rtt": 5.983}]}, {"hop": 11, "probes": [{"annotation": null, "asn": null, "ip": "209.85.242.53", "name": "209.85.242.53", "rtt": 4.973}, {"annotation": null, "asn": null, "ip": "209.85.242.53", "name": "209.85.242.53", "rtt": 4.973}, {"annotation": null, "asn": null, "ip": "209.85.242.53", "name": "209.85.242.53", "rtt": 4.979}]}, {"hop": 12, "probes": [{"annotation": null, "asn": null, "ip": "216.58.194.46", "name": "dfw25s12-in-f46.1e100.net", "rtt": 4.871}, {"annotation": null, "asn": null, "ip": "216.58.194.46", "name": "dfw25s12-in-f46.1e100.net", "rtt": 4.884}, {"annotation": null, "asn": null, "ip": "216.58.194.46", "name": "dfw25s12-in-f46.1e100.net", "rtt": 4.863}]}]}
{"destination_ip":"216.58.194.46","destination_name":"google.com","max_hops":30,"data_bytes":40,"hops":[{"hop":1,"probes":[{"annotation":null,"asn":null,"ip":"216.230.231.141","name":"216-230-231-141.static.houston.tx.oplink.net","rtt":198.574},{"annotation":null,"asn":null,"ip":"216.230.231.141","name":"216-230-231-141.static.houston.tx.oplink.net","rtt":198.65}]},{"hop":2,"probes":[]},{"hop":3,"probes":[]},{"hop":4,"probes":[{"annotation":null,"asn":null,"ip":"72.14.242.34","name":"72.14.242.34","rtt":4.932},{"annotation":null,"asn":null,"ip":"72.14.242.34","name":"72.14.242.34","rtt":4.945},{"annotation":null,"asn":null,"ip":"72.14.242.34","name":"72.14.242.34","rtt":4.951}]},{"hop":5,"probes":[]},{"hop":6,"probes":[{"annotation":null,"asn":null,"ip":"108.170.230.116","name":"108.170.230.116","rtt":4.687},{"annotation":null,"asn":null,"ip":"108.170.230.116","name":"108.170.230.116","rtt":4.798},{"annotation":null,"asn":null,"ip":"108.170.230.116","name":"108.170.230.116","rtt":4.688}]},{"hop":7,"probes":[{"annotation":null,"asn":null,"ip":"108.170.252.130","name":"108.170.252.130","rtt":4.825},{"annotation":null,"asn":null,"ip":"108.170.252.130","name":"108.170.252.130","rtt":4.844},{"annotation":null,"asn":null,"ip":"108.170.252.130","name":"108.170.252.130","rtt":4.797}]},{"hop":8,"probes":[{"annotation":null,"asn":null,"ip":"108.170.233.117","name":"108.170.233.117","rtt":5.386},{"annotation":null,"asn":null,"ip":"108.170.233.117","name":"108.170.233.117","rtt":5.288},{"annotation":null,"asn":null,"ip":"108.170.233.117","name":"108.170.233.117","rtt":5.324}]},{"hop":9,"probes":[{"annotation":null,"asn":null,"ip":"216.239.63.250","name":"216.239.63.250","rtt":5.305},{"annotation":null,"asn":null,"ip":"216.239.63.250","name":"216.239.63.250","rtt":5.369},{"annotation":null,"asn":null,"ip":"216.239.63.250","name":"216.239.63.250","rtt":5.406}]},{"hop":10,"probes":[{"annotation":null,"asn":null,"ip":"108.170.240.129","name":"108.170.240.129","rtt":6.005},{"annotation":null,"asn":null,"ip":"108.170.240.129","name":"108.170.240.129","rtt":5.93},{"annotation":null,"asn":null,"ip":"108.170.240.129","name":"108.170.240.129","rtt":5.983}]},{"hop":11,"probes":[{"annotation":null,"asn":null,"ip":"209.85.242.53","name":"209.85.242.53","rtt":4.973},{"annotation":null,"asn":null,"ip":"209.85.242.53","name":"209.85.242.53","rtt":4.973},{"annotation":null,"asn":null,"ip":"209.85.242.53","name":"209.85.242.53","rtt":4.979}]},{"hop":12,"probes":[{"annotation":null,"asn":null,"ip":"216.58.194.46","name":"dfw25s12-in-f46.1e100.net","rtt":4.871},{"annotation":null,"asn":null,"ip":"216.58.194.46","name":"dfw25s12-in-f46.1e100.net","rtt":4.884},{"annotation":null,"asn":null,"ip":"216.58.194.46","name":"dfw25s12-in-f46.1e100.net","rtt":4.863}]}]}

Some files were not shown because too many files have changed in this diff Show More