Last active
October 28, 2020 05:56
-
-
Save aberezin/a0cdec3c125851a96d4281183b6dd427 to your computer and use it in GitHub Desktop.
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 bash | |
# Use at own risk. License CC0 see https://creativecommons.org/publicdomain/mark/1.0/ | |
# alanberezin.com | |
OPTIND=1 # Reset in case getopts has been used previously in the shell. | |
opt_stripclasspath=false | |
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 | |
Examples: | |
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 https://stedolan.github.io/jq/manual/v1.4/ | |
EOF | |
exit 0 | |
;; | |
-c ) | |
opt_stripclasspath=true | |
shift | |
;; | |
esac | |
done | |
#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 | |
tmpfile=$(mktemp) | |
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 | |
header="CONTAINER_ID IMAGE COMMAND CREATED STATUS PORTS NAMES" | |
sed -i '1s/^/'"$header"'\n/ | |
2d' $tmpfile | |
else | |
header="$(ps $@ | head -1)" | |
sed -i '1s;^;'"$header"'\n;' $tmpfile | |
fi | |
arg_separator='_-_-' #something unique bc we may need to split on it later | |
# Credit to https://unix.stackexchange.com/a/243485/103690 for the basic idea. | |
jq=' | |
[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 | |
jq=$jq' | |
| .[] | . as $process | keys[] | select($process[.] == "-cp") | |
| split("_-_-")[1] | tonumber as $argnumber | $process | |
| del( .["arg_-_-" + (($argnumber+1) | tostring)]) | [.]' | |
fi | |
echo $jq > jq.tmp | |
cat $tmpfile | jq -sR "$jq" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
convert ps output to JSON and tokenize the CMD column into separate key/val pairs.
This also works somewhat for docker ps