Skip to content

Instantly share code, notes, and snippets.

Last active Oct 28, 2020
What would you like to do?
#! /usr/bin/env bash
# Use at own risk. License CC0 see
OPTIND=1 # Reset in case getopts has been used previously in the shell.
while getopts ":hc" opt; do
case "$1" in
-h | --help )
cat <<-EOF
Usage: ps [any-ps-options] | psjson [-c] [repeat-ps-options-see-below]
or: docker ps [any-docker-ps-options] | psjson [-c]
or: psjson -h
Reading the stdin, jsonify the output of ps (or docker ps). If you pipe the contents of "ps"
directly into psjson, then you do not need to repeat the ps options to psjon.
However, if you pipe the output of ps though grep, or anything else, that strips the
header off the output, then you need to repeat the ps options (like, -f) that would
have the effect of changing the default columns that are output Also, if you pipe
though grep or other commands that colorize, use the --color=never option to grep.
-c For ps(1) rows that have a "-cp" in the command string, remove the following
token. This effectively strips nuesance long java classpaths that clutter the output.
A nice feature of psjon is that it tokenizes the CMD column of ps. this is handy when, for example, the process is a java server with a mile long classpath.
For docker ps, the parsing of CREATED and STATUS needs work
Correct: ps -f | grep foo | psjson -f
Correct: ps -ef | grep foo | psjson -f #dont need to repeat the -e flag
#it doesnt effect the header
Correct: ps -f | psjson
Correct: ps -f | psjson -f #final -f is ignored
Incorrect: ps -f | grep --color=never foo | psjson #wrong unless foo was a column header in ps
marginal: ps | grep foo | psjson #should use grep --color=never to be safe
This cmd requires that jq be installed. See
exit 0
-c )
#In case output of ps has no header (like if it was grep'd out)
#Note: test for header is an imperfect test which relies on PID in the header, maybe improve
trap 'rm -f $tmpfile' EXIT
cat > $tmpfile
# read -e -p 'debug> ' < /dev/tty
if cat "$tmpfile" | head -1 | grep --color=never ' PID ' > /dev/null ; then
elif cat "$tmpfile" | head -1 | grep --color=never 'CONTAINER' > /dev/null ; then
# A docker ps output. Reqrite header to avoid whitespace.
#TODO ceated and status fields still have embedded whitespace
sed -i '1s/^/'"$header"'\n/
2d' $tmpfile
header="$(ps $@ | head -1)"
sed -i '1s;^;'"$header"'\n;' $tmpfile
arg_separator='_-_-' #something unique bc we may need to split on it later
# Credit to for the basic idea.
[sub("\n$";"") | splits("\n") | sub("^ +";"") | [splits(" +")]]
| .[0] as $orig_header
| [$orig_header[], (range(1000) | tostring | "arg'$arg_separator'"+.)] as $newheader
| .[1:] | [.[] | [. as $x | range($newheader | length)
| {"key": $newheader[.], "value": $x[.]}] | from_entries]
| del(.[][] | select(. == null))
if [ "$opt_stripclasspath" = true ] ; then
| .[] | . as $process | keys[] | select($process[.] == "-cp")
| split("_-_-")[1] | tonumber as $argnumber | $process
| del( .["arg_-_-" + (($argnumber+1) | tostring)]) | [.]'
echo $jq > jq.tmp
cat $tmpfile | jq -sR "$jq"
Copy link

aberezin commented Aug 22, 2018

convert ps output to JSON and tokenize the CMD column into separate key/val pairs.
This also works somewhat for docker ps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment