Skip to content

Instantly share code, notes, and snippets.

@xfgusta
Created October 12, 2021 18:36
Show Gist options
  • Save xfgusta/c5b6b69458460676d454438e40257ecb to your computer and use it in GitHub Desktop.
Save xfgusta/c5b6b69458460676d454438e40257ecb to your computer and use it in GitHub Desktop.
View process information
#!/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