Sunday, May 28, 2017

Solaris' pargs, penv, pfiles, pmap, pstack, and pwdx on macOS

Three weeks ago I posted Solaris' pargs, penv, pfiles, pmap, and pstack on GNU/Linux and since I am also a Mac user, I thought it could be a good idea to have those commands also on macOS. Here we go ...

function pargs()  { L=$(ps ww $1 | tail -1); echo ${L:27}; }
function penv()   { L=$(pargs $1); C=${#L}; L=$(ps wwe $1 | tail -1); L=${L:27}; echo ${L:$C} | tr ' ' '\n'; }
function pfiles() { lsof -p $1; }
function pmap()   { vmmap $1; }
function pstack() { echo "thread backtrace all" | lldb -p $1; }
function pwdx()   { L=$(lsof -a  -d cwd -p $1 | tail -1); echo /${L#*/}; }

Since there is no access to a proc file system on macOS (at least not by default), both pargs and penv call the ps command and pmap calls vmmap. Furthermore pwdx calls lsof with the current working directory descriptor request in order to get the required info. Since "ps wwe" returns not only the environment variables for the given process but also the program arguments on macOS, we need to strip the program arguments from the output. This has been done by calling pargs, determining the length of that output and cutting that length from the string again before we pass it to the tr command that gives us an environment variable for each line. For blog purposes I have shortened the variable names, L stands for line and C for count.

References:
http://wiki.bash-hackers.org/syntax/pe
http://yongsun.me/2009/01/tips-the-equivalents-of-ldd1-and-pmap1-on-mac-os-x/

Sunday, May 7, 2017

Solaris' pargs, penv, pfiles, pmap, and pstack on GNU/Linux

I really like the p-commands on Sun/Oracle Solaris and I miss those on GNU/Linux. Therefore I have gathered/created rudimental equivalent one-liners that work on a PID.

I have added the following functions to my ~/.bash_aliases file that is being sourced by my ~/.bashrc. pargs, penv, and pmap are gathering the proc file system, while pfiles and pstack are calling lsof resp. gdb.

function pargs() { cat /proc/$1/cmdline | tr '\0' ' ' | sed 's/ $/\n/g'; }
function penv() { cat /proc/$1/environ | tr '\0' '\n'; }
function pfiles() { lsof -p $1; }

function pmap() { cat /proc/$1/maps; }
function pstack() { sudo gdb --pid=$1 --batch -ex "thread apply all bt"; }


Note that due to a kernel hardening (ptrace protection) on Ubuntu 10.10 and later you need to call gdb under the control of sudo, or alternatively modify the ptrace_scope property. See also https://wiki.ubuntu.com/SecurityTeam/Roadmap/KernelHardening#ptrace_Protection and https://askubuntu.com/questions/41629/after-upgrade-gdb-wont-attach-to-process