1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-07-13 01:20:24 +02:00

add proc-pid-fdinfo parser

This commit is contained in:
Kelly Brazil
2022-09-19 16:50:01 -07:00
parent c88bf3e94b
commit 8ffde41fa4
5 changed files with 359 additions and 9 deletions

View File

@ -0,0 +1,127 @@
[Home](https://kellyjonbrazil.github.io/jc/)
<a id="jc.parsers.proc_pid_fdinfo"></a>
# jc.parsers.proc\_pid\_fdinfo
jc - JSON Convert `/proc/<pid>/fdinfo` file parser
Usage (cli):
$ cat /proc/1/fdinfo/5 | jc --proc
or
$ jc /proc/1/fdinfo/5
or
$ cat /proc/1/fdinfo/5 | jc --proc-pid-fdinfo
Usage (module):
import jc
result = jc.parse('proc', proc_pid_fdinfo_file)
or
import jc
result = jc.parse('proc_pid_fdinfo', proc_pid_fdinfo_file)
Schema:
Any unspecified fields are strings.
{
"pos": integer,
"flags": integer,
"mnt_id": integer,
"scm_fds": string,
"ino": integer,
"lock": string,
"epoll": {
"tfd": integer,
"events": string,
"data": string,
"pos": integer,
"ino": string,
"sdev": string
},
"inotify": {
"wd": integer,
"ino": string,
"sdev": string,
"mask": string,
"ignored_mask": string,
"fhandle-bytes": string,
"fhandle-type": string,
"f_handle": string
},
"fanotify": {
"flags": string,
"event-flags": string,
"mnt_id": string,
"mflags": string,
"mask": string,
"ignored_mask": string,
"ino": string,
"sdev": string,
"fhandle-bytes": string,
"fhandle-type": string,
"f_handle": string
},
"clockid": integer,
"ticks": integer,
"settime flags": integer,
"it_value": [
integer
],
"it_interval": [
integer
]
}
Examples:
$ cat /proc/1/fdinfo/5 | jc --proc -p
{
"pos": 0,
"flags": 2,
"mnt_id": 9,
"ino": 63107,
"clockid": 0,
"ticks": 0,
"settime flags": 1,
"it_value": [
0,
49406829
],
"it_interval": [
1,
0
]
}
<a id="jc.parsers.proc_pid_fdinfo.parse"></a>
### parse
```python
def parse(data: str, raw: bool = False, quiet: bool = False) -> Dict
```
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
### Parser Information
Compatibility: linux
Version 1.0 by Kelly Brazil (kellyjonbrazil@gmail.com)

View File

@ -112,6 +112,7 @@ parsers = [
'proc-vmallocinfo',
'proc-vmstat',
'proc-zoneinfo',
'proc-pid-fdinfo',
'proc-pid-numa-maps',
'ps',
'route',

View File

@ -195,15 +195,15 @@ def parse(
net_route_p = re.compile(r'^Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT\s+\n')
net_unix_p = re.compile(r'^Num RefCount Protocol Flags Type St Inode Path\n')
pid_status_p = re.compile(r'^Name:\t.+\nUmask:\t\d+\nState:\t.+\nTgid:\t\d+\n')
pid_statm_p = re.compile(r'^\d+ \d+ \d+\s\d+\s\d+\s\d+\s\d+$')
pid_stat_p = re.compile(r'^\d+ \(.{1,16}\) \w \d+ \d+ \d+ \d+ -?\d+ (?:\d+ ){43}\d+$')
pid_smaps_p = re.compile(r'^[0-9a-f]{12}-[0-9a-f]{12} [rwxsp\-]{4} [0-9a-f]{8} [0-9a-f]{2}:[0-9a-f]{2} \d+ [^\n]+\nSize:\s+\d+ \S\S\n')
pid_maps_p = re.compile(r'^[0-9a-f]{12}-[0-9a-f]{12} [rwxsp\-]{4} [0-9a-f]{8} [0-9a-f]{2}:[0-9a-f]{2} \d+ ')
pid_numa_maps_p = re.compile(r'^[a-f0-9]{12} default [^\n]+\n')
pid_io_p = re.compile(r'^rchar: \d+\nwchar: \d+\nsyscr: \d+\n')
pid_mountinfo_p = re.compile(r'^\d+ \d+ \d+:\d+ /.+\n')
pid_fdinfo_p = re.compile(r'^pos:\t\d+\nflags:\t\d+\nmnt_id:\t\d+\n')
pid_io_p = re.compile(r'^rchar: \d+\nwchar: \d+\nsyscr: \d+\n')
pid_maps_p = re.compile(r'^[0-9a-f]{12}-[0-9a-f]{12} [rwxsp\-]{4} [0-9a-f]{8} [0-9a-f]{2}:[0-9a-f]{2} \d+ ')
pid_mountinfo_p = re.compile(r'^\d+ \d+ \d+:\d+ /.+\n')
pid_numa_maps_p = re.compile(r'^[a-f0-9]{12} default [^\n]+\n')
pid_smaps_p = re.compile(r'^[0-9a-f]{12}-[0-9a-f]{12} [rwxsp\-]{4} [0-9a-f]{8} [0-9a-f]{2}:[0-9a-f]{2} \d+ [^\n]+\nSize:\s+\d+ \S\S\n')
pid_statm_p = re.compile(r'^\d+ \d+ \d+\s\d+\s\d+\s\d+\s\d+$')
pid_status_p = re.compile(r'^Name:\t.+\nUmask:\t\d+\nState:\t.+\nTgid:\t\d+\n')
pid_stat_p = re.compile(r'^\d+ \(.{1,16}\) \w \d+ \d+ \d+ \d+ -?\d+ (?:\d+ ){43}\d+$')
scsi_device_info = re.compile(r"^'\w+' '.+' 0x\d+")
scsi_scsi_p = re.compile(r'^Attached devices:\nHost: \w+ ')

View File

@ -0,0 +1,217 @@
"""jc - JSON Convert `/proc/<pid>/fdinfo` file parser
Usage (cli):
$ cat /proc/1/fdinfo/5 | jc --proc
or
$ jc /proc/1/fdinfo/5
or
$ cat /proc/1/fdinfo/5 | jc --proc-pid-fdinfo
Usage (module):
import jc
result = jc.parse('proc', proc_pid_fdinfo_file)
or
import jc
result = jc.parse('proc_pid_fdinfo', proc_pid_fdinfo_file)
Schema:
Any unspecified fields are strings.
{
"pos": integer,
"flags": integer,
"mnt_id": integer,
"scm_fds": string,
"ino": integer,
"lock": string,
"epoll": {
"tfd": integer,
"events": string,
"data": string,
"pos": integer,
"ino": string,
"sdev": string
},
"inotify": {
"wd": integer,
"ino": string,
"sdev": string,
"mask": string,
"ignored_mask": string,
"fhandle-bytes": string,
"fhandle-type": string,
"f_handle": string
},
"fanotify": {
"flags": string,
"event-flags": string,
"mnt_id": string,
"mflags": string,
"mask": string,
"ignored_mask": string,
"ino": string,
"sdev": string,
"fhandle-bytes": string,
"fhandle-type": string,
"f_handle": string
},
"clockid": integer,
"ticks": integer,
"settime flags": integer,
"it_value": [
integer
],
"it_interval": [
integer
]
}
Examples:
$ cat /proc/1/fdinfo/5 | jc --proc -p
{
"pos": 0,
"flags": 2,
"mnt_id": 9,
"ino": 63107,
"clockid": 0,
"ticks": 0,
"settime flags": 1,
"it_value": [
0,
49406829
],
"it_interval": [
1,
0
]
}
"""
import re
from typing import Dict
import jc.utils
class info():
"""Provides parser metadata (version, author, etc.)"""
version = '1.0'
description = '`/proc/pid-fdinfo` file parser'
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
hidden = True
__version__ = info.version
def _process(proc_data: Dict) -> Dict:
"""
Final processing to conform to the schema.
Parameters:
proc_data: (List of Dictionaries) raw structured data to process
Returns:
Dictionary. Structured to conform to the schema.
"""
root_int_list = {'pos', 'flags', 'mnt_id', 'ino', 'clockid', 'ticks',
'settime flags', 'size', 'count'}
epoll_int_list = {'tfd', 'pos'}
inotify_int_list = {'wd'}
for key, val in proc_data.items():
if key in root_int_list:
proc_data[key] = int(val)
if 'epoll' in proc_data:
for key, val in proc_data['epoll'].items():
if key in epoll_int_list:
proc_data['epoll'][key] = int(val)
if 'inotify' in proc_data:
for key, val in proc_data['inotify'].items():
if key in inotify_int_list:
proc_data['inotify'][key] = int(val)
return proc_data
def parse(
data: str,
raw: bool = False,
quiet: bool = False
) -> Dict:
"""
Main text parsing function
Parameters:
data: (string) text data to parse
raw: (boolean) unprocessed output if True
quiet: (boolean) suppress warning messages if True
Returns:
Dictionary. Raw or processed structured data.
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
raw_output: Dict = {}
split_me = {'it_value:', 'it_interval:'}
if jc.utils.has_data(data):
for line in filter(None, data.splitlines()):
# epoll files
if line.startswith('tfd:'):
line_match = re.findall(r'(?P<key>\S+):(?:\s+)?(?P<val>\S+s*)', line)
if line_match:
raw_output.update({'epoll': {k.strip(): v.strip() for k, v in line_match}})
continue
# inotify files
if line.startswith('inotify'):
split_line = line[8:].split()
raw_output['inotify'] = {}
for item in split_line:
k, v = item.split(':', maxsplit=1)
raw_output['inotify'][k] = v
continue
# fanotify files
if line.startswith('fanotify'):
split_line = line[9:].split()
if not 'fanotify' in raw_output:
raw_output['fanotify'] = {}
for item in split_line:
k, v = item.split(':', maxsplit=1)
raw_output['fanotify'][k] = v
continue
# timerfd files
if line.split()[0] in split_me:
split_line = line.replace(':', '').replace('(', '').replace(')', '').replace(',', '').split()
raw_output[split_line[0]] = [int(x) for x in split_line[1:]]
continue
key, val = line.split(':', maxsplit=1)
raw_output[key.strip()] = val.strip()
continue
return raw_output if raw else _process(raw_output)

View File

@ -1,4 +1,4 @@
.TH jc 1 2022-09-17 1.21.2 "JSON Convert"
.TH jc 1 2022-09-19 1.21.2 "JSON Convert"
.SH NAME
\fBjc\fP \- JSON Convert JSONifies the output of many CLI tools, file-types, and strings
.SH SYNOPSIS
@ -545,6 +545,11 @@ PLIST file parser
\fB--proc-zoneinfo\fP
`/proc/zoneinfo` file parser
.TP
.B
\fB--proc-pid-fdinfo\fP
`/proc/pid-fdinfo` file parser
.TP
.B
\fB--proc-pid-numa-maps\fP