Skip to content

Instantly share code, notes, and snippets.

@timfoster
Created Jan 14, 2020
Embed
What would you like to do?
pargs hack to keep timf sane
#!/usr/bin/env python
# Fake up a Solaris-like pargs(1) command to keep timf sane.
# We only implement the basic functionality, and -e. Tested
# on FreeBSD 11.1-RELEASE, ubuntu 16.04.3 LTS and (uh) Solaris 11.4
# with python 2.7.13+ and 3.x. Minimal error handling here.
import os
import subprocess
import sys
# intentionally not using the 'psutils' module since we can't
# guarantee that'll is installed everywhere, despite being much
# easier.
usage = "Usage: pargs [-e] pid ..."
def unix_pargs(pid, show_env):
proc_dir = "/proc/%s" % pid
if not os.path.exists(proc_dir):
print("No such process")
return 1
if show_env:
with open(os.path.join(proc_dir, "environ")) as env:
for line in sorted(env.read().split("\x00")):
if not line:
continue
print(line)
else:
with open(os.path.join(proc_dir, "cmdline"), "rb") as cmd:
arr = cmd.read().split("\x00")
print("%s: %s\n" % (pid, arr[0]))
for index, envvar in enumerate(arr[:-1]):
if not envvar:
continue
print("argv[%s]: %s" % (index, envvar))
return 0
def darwin_pargs(pid, show_env):
# ugh, using ps
darwin_ps = "/bin/ps"
cmd = [darwin_ps, "-H", "-o args", pid]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
ret = p.wait()
stdout, stderr = p.communicate()
if isinstance(stdout, bytes):
stdout = stdout.decode("utf-8")
if ret != 0:
return ret
arr = stdout.split()
print("%s:\t%s\n" % (arr[0], arr[1]))
print("\n".join(
"argv[%s]: %s" % i
for i in enumerate(arr[2:])))
return 0
def bsd_pargs(pid, show_env):
# using procstat is ugly, but good enough.
bsd_procstat = "/usr/bin/procstat"
if show_env:
cmd = [bsd_procstat, "-he", pid]
else:
cmd = [bsd_procstat, "-hc", pid]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
ret = p.wait()
stdout, stderr = p.communicate()
if isinstance(stdout, bytes):
stdout = stdout.decode("utf-8")
if ret != 0:
return ret
arr = stdout.split()
if show_env:
# there's no parseable output for procstat -e, so our split() will
# have broken any env vars containing spaces. Attempt to fix by
# recombining such entries.
last_eq = 0
for index, item in enumerate(arr):
if "=" in item:
last_eq = index
continue
arr[last_eq] += " %s" % item
arr[index] = ""
arr = [item for item in arr if item]
if show_env:
print("\n".join(arr[3:]))
else:
print("%s:\t%s\n" % (arr[0], arr[1]))
print("\n".join(
"argv[%s]: %s" % i
for i in enumerate(arr[2:])))
return 0
if __name__ == "__main__":
# Crude argument parsing for now.
show_env = "-e" in sys.argv
if (len(sys.argv) < 2):
print(usage)
sys.exit(2)
# don't care what we're called as
sys.argv.pop(0)
if show_env:
# remove the -e arg
sys.argv.pop(0)
uname = os.uname()[0].lower()
ret = 0
for index, pid in enumerate(sys.argv):
if uname in ["linux", "sunos"]:
ret += unix_pargs(pid, show_env)
elif uname == "bsd":
ret += bsd_pargs(pid, show_env)
elif uname == "darwin":
ret += darwin_pargs(pid, show_env)
else:
print("Error: pargs not implemented for %s" % uname)
ret = 1
break
if index != len(sys.argv) - 1:
print("")
if ret != 0:
print(usage)
sys.exit(ret)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment