Format the output of cputime for ps

This converts the first time to seconds:

ps -p $PROCID -o cputime,etimes | awk -F'[: ]+' '/:/ {t=$3+60*($2+60*$1); print t,$NF}'

As an example, the ps command produces:

$ ps -p 5403 -o cputime,etimes
    TIME ELAPSED
01:33:38 1128931

The awk command processes that and returns:

ps -p 5403 -o cputime,etimes | awk -F'[: ]+' '/:/ {t=$3+60*($2+60*$1); print t,$NF}'
5618 1128931

Explanation

  • -F'[: ]+'

    This tells awk to treat both colons and spaces as field separators. This way, the hours, minutes, and seconds appear as separate fields.

  • /:/ {t=$3+60*($2+60*$1); print t,$NF}

    The initial /:/ restricts the code to working only on lines that include a colon. This removes the header lines. The number of seconds is calculated from hours, minutes, seconds via t=$3+60*($2+60*$1). The resulting value for t is then printed along side with the elapsed time.

Handling days

If ps produces days,hours,minutes,seconds, as in:

2-03:01:33

Then, use this code instead:

ps -p $PROCID -o cputime,etimes | awk -F'[-: ]+' '/:/ {t=$4+60*($3+60*($2+24*$1)); print t,$NF}'

If days may or may not be prepended to the output, then use this combination command:

ps -p $PROCID -o cputime,etimes | awk -F'[-: ]+' '/:/ && NF==5 { t=$4+60*($3+60*($2+24*$1)); print t,$NF} /:/ && NF==4 {t=$3+60*($2+60*$1); print t,$NF}'

If you don't want to bring awk in the game, a pure bash solution (t_str contains the formated string, t_sec the decoded time in seconds):

# Decode the CPU time format [dd-]hh:mm:ss.
IFS="-:" read c1 c2 c3 c4 <<< "$t_str"
if [ -n "$c4" ]
then
  t_sec=$((10#$c4+60*(10#$c3+60*(10#$c2+24*10#$c1))))
else
  t_sec=$((10#$c3+60*(10#$c2+60*10#$c1)))
fi