Created
January 14, 2020 16:11
-
-
Save timfoster/99282ce703671ae0ddc24562d0521afa to your computer and use it in GitHub Desktop.
pargs hack to keep timf sane
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/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