Created
October 12, 2021 18:36
-
-
Save xfgusta/c5b6b69458460676d454438e40257ecb to your computer and use it in GitHub Desktop.
View process information
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import sys | |
import argparse | |
import os | |
QUIET = False | |
def main(): | |
args = argparser() | |
pid = args.pid | |
del args.pid | |
global QUIET | |
QUIET = args.quiet | |
del args.quiet | |
options = vars(args) | |
if any(options.values()): | |
for option in options.keys(): | |
if getattr(args, option): | |
globals()[f'show_{option}'](pid) | |
else: | |
for option in options.keys(): | |
globals()[f'show_{option}'](pid) | |
def argparser(): | |
parser = argparse.ArgumentParser( | |
prog='vproc', | |
description='view process information' | |
) | |
parser.add_argument( | |
'pid', | |
metavar='PID', | |
type=int, | |
help='set the process id' | |
) | |
parser.add_argument( | |
'--quiet', | |
action='store_true', | |
help='ignore errors (don\'t exit)' | |
) | |
parser.add_argument( | |
'--exe', | |
action='store_true', | |
help='show the executable path' | |
) | |
parser.add_argument( | |
'--comm', | |
action='store_true', | |
help='show the command name' | |
) | |
parser.add_argument( | |
'--cmdline', | |
action='store_true', | |
help='show the command line' | |
) | |
parser.add_argument( | |
'--cwd', | |
action='store_true', | |
help='show the current working directory' | |
) | |
parser.add_argument( | |
'--environ', | |
action='store_true', | |
help='show the environment variables' | |
) | |
parser.add_argument( | |
'--fd', | |
action='store_true', | |
help='show the file descriptors' | |
) | |
parser.add_argument( | |
'--map_files', | |
action='store_true', | |
help='show the memory-mapped files' | |
) | |
parser.add_argument( | |
'--io', | |
action='store_true', | |
help='show IO statistics' | |
) | |
return parser.parse_args() | |
def show_exe(pid): | |
print('Executable path') | |
exe_path = f'/proc/{pid}/exe' | |
try: | |
exe = os.readlink(exe_path) | |
print(f'\t{exe}\n') | |
except OSError as err: | |
die(f'Cannot readlink {exe_path}: {err.strerror}') | |
def show_comm(pid): | |
print('Command name') | |
comm_path = f'/proc/{pid}/comm' | |
try: | |
with open(comm_path, 'r') as comm_file: | |
comm = comm_file.read().strip() | |
print(f'\t{comm}\n') | |
except OSError as err: | |
die(f'Cannot open {comm_path}: {err.strerror}') | |
def show_cmdline(pid): | |
print('Command line') | |
cmdline_path = f'/proc/{pid}/cmdline' | |
try: | |
with open(cmdline_path, 'r') as cmdline_file: | |
cmdline = cmdline_file.read().replace('\0', ' ') | |
print(f'\t{cmdline}\n') | |
except OSError as err: | |
die(f'Cannot open {cmdline_path}: {err.strerror}') | |
def show_cwd(pid): | |
print('Current working directory') | |
cwd_path = f'/proc/{pid}/cwd' | |
try: | |
cwd = os.readlink(cwd_path) | |
print(f'\t{cwd}\n') | |
except OSError as err: | |
die(f'Cannot readlink {cwd_path}: {err.strerror}') | |
def show_environ(pid): | |
print('Environment variables') | |
environ_path = f'/proc/{pid}/environ' | |
try: | |
with open(environ_path, 'r') as environ_file: | |
for env in environ_file.read().split('\0'): | |
print(f'\t{env}') | |
except OSError as err: | |
die(f'Cannot open {environ_path}: {err.strerror}') | |
def show_fd(pid): | |
print('File descriptors') | |
fd_path = f'/proc/{pid}/fd' | |
try: | |
files = [] | |
for fd in os.listdir(fd_path): | |
file_link_path = os.path.join(fd_path, fd) | |
try: | |
file_path = os.readlink(file_link_path) | |
files.append((fd, file_path)) | |
except OSError as err: | |
die(f'Cannot readlink {file_link_path}: {err.strerror}') | |
return | |
except OSError as err: | |
die(f'Cannot listdir {fd_path}: {err.strerror}') | |
return | |
max_len = len(max(map(lambda file: file[0], files), key=len)) | |
for fd, file in files: | |
fd = fd.rjust(max_len) | |
print(f'\t{fd} -> {file}') | |
print() | |
def show_map_files(pid): | |
print('Memory-mapped files') | |
map_files_path = f'/proc/{pid}/map_files' | |
try: | |
files = [] | |
for file in os.listdir(map_files_path): | |
file_link_path = os.path.join(map_files_path, file) | |
try: | |
file_path = os.readlink(file_link_path) | |
files.append((file, file_path)) | |
except OSError as err: | |
die(f'Cannot readlink {file_link_path}: {err.strerror}') | |
return | |
except OSError as err: | |
die(f'Cannot listdir {map_files_path}: {err.strerror}') | |
return | |
max_len = len(max(map(lambda file: file[0], files), key=len)) | |
for link, file in files: | |
link = link.rjust(max_len) | |
print(f'\t{link} -> {file}') | |
print() | |
def show_io(pid): | |
print('I/O statistics') | |
io_path = f'/proc/{pid}/io' | |
try: | |
with open(io_path, 'r') as io_file: | |
rchar, syscr, wchar, syscw = io_file.readlines()[:4] | |
read = int(rchar.split()[1]) | |
write = int(wchar.split()[1]) | |
syscr = syscr.split()[1] | |
syscw = syscw.split()[1] | |
except OSError as err: | |
die(f'Cannot open {io_path}: {err.strerror}') | |
return | |
read = humanize(read) | |
write = humanize(write) | |
readable_max_len = len(max(read, write, key=len)) | |
read = read.rjust(readable_max_len) | |
write = write.rjust(readable_max_len) | |
sysc_max_len = len(max(syscr, syscw, key=len)) | |
syscr = syscr.rjust(sysc_max_len) | |
syscw = syscw.rjust(sysc_max_len) | |
print(f'\t{read} read ({syscr} syscalls)') | |
print(f'\t{write} written ({syscw} syscalls)\n') | |
def humanize(num): | |
for unit in ['', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']: | |
if abs(num) < 1024.0: | |
return f'{num:3.1f} {unit}B' | |
num /= 1024.0 | |
return f'{num:.1f} YiB' | |
def die(message): | |
if not QUIET: | |
print(message, file=sys.stderr) | |
sys.exit(1) | |
if __name__ == '__main__': | |
try: | |
main() | |
except KeyboardInterrupt: | |
sys.exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment