0

I want to do parsing of Elapsed time in seconds .Time formats given below:

1) 3 day 18h
2) 3 day
3) 3h 15min
4) 3h 
5) 15min 10sec
6) 15min 
7) 10sec

i'm getting values from systemctl status cassandra | awk '/(Active: active)/{print $9, $10,$11}' Now storing it's value in variable A,like

A=$(systemctl status cassandra | awk '/(Active: active)/{print $9, $10,$11}'

now A has input as 3 day 18h or 3 day etc. More examples-

A=3 day 18h or 3 day or 3h 15min or 3h or 15min 10sec or 15min or 10sec

now take different values of A, and parse in seconds.

1
  • Would busctl get-property help instead?
    – ajeh
    Apr 25 '18 at 22:04
2

You can use the date command to parse those values as follows:

        adjusted_val="$(printf '%s' "$val" | sed 's/h/hour/')"
        result="$(date -d "$(date -d @0) + $adjusted_val" +%s)"

Curiously, date doesn’t recognize h (or even hr) as an abbreviation for “hour”, so, as a first step, we replace h in the string with hour.  Then we find “the epoch time” — the date/time from which Unix date/times count — by expanding @0 (Unix time 0) as a string.  (This well-known and documented to be “Jan 1, 1970 00:00:00 GMT”, so we could just hard-code that value.)  Then we add your string: for example, (Jan 1) + 3 day(s) is Jan 4.  We then use +%s to display that date/time as a Unix numeric date/time, which is the number of seconds after the epoch.  This corresponds to the interval (delta) value of your string.

If you want to do many values at once, you can optimize this by computing the epoch only once:

#!/bin/sh
epoch="$(date -d @0)"
for val
do
        adjusted_val="$(printf '%s' "$val" | sed 's/h/hour/')"
        if result="$(date -d "$epoch + $adjusted_val" +%s)"
        then
                printf '%-12s -> %6d\n' "$val" "$result"
        else
                printf '%-12s <- error\n' "$val"
        fi
done

results:

$ ./myscript '3 day 18h' '3 day' '3h 15min' '3h' '15min 10sec' '15min ' \
                                                       '10sec' 'a moment' '3 weeks'
3 day 18h    -> 324000
3 day        -> 259200
3h 15min     ->  11700
3h           ->  10800
15min 10sec  ->    910
15min        ->    900
10sec        ->     10
date: invalid date ‘Wed, Dec 31, 1969  7:00:00 PM + a moment’
a moment     <- error
3 weeks      -> 1814400

Note that date -d can handle the word “month”.  If there’s a possibility that you might get values containing that word, you’ll need to make the sed command smarter, so it doesn’t change the “h” in “month”.

But, if you do want to handle months, you should think hard about what a “month” is.  For example, I’m writing this on April 12, 2020.  A month from now will be May 12 — that’s 30 days away.  A month ago was March 12 — that was 31 days ago.  Two months ago was February 12, which was 60 (31+29) days ago.  But wait — in non-leap years, February has only 28 days, so February 12 and April 12 are only 59 days apart.  And there’s more: in the United States (at least), February 12 is in standard time and March 12 is in daylight saving time, so (in non-leap years) noon on February 12 and noon on March 12 are only 27 days and 23 hours apart.  It’s complicated.

1

We can't depend on days and hours parameters, because after 7 days we will get week parameter and after 30 days we will get month parameter.

So its better to calculate with Service start time.

#!/bin/bash
SERVICE=cassandra
SERVICE_START_TIME=`systemctl status $SERVICE | awk '/Active: active/{print $6" "$7}'`
SERVICE_UP_TIME=$(($(date +%s) - $(date -d "$SERVICE_START_TIME" +%s)))
echo "$SERVICE uptime : $SERVICE_UP_TIME"

you can try the following one-liner, but I suggest the above code to get the accurate result.

systemctl status cassandra | awk -F ';' '/Active: active/{print $2}' |  sed -e 's/s ago/ 1/; s/s//g; s/min/ 60/; s/h ago/ 3600/; s/day/86400/; s/week/606800/; s/month/2592000/; s/ago//' | awk '{a=$1*$2;b=$3*$4;c=$a+$b;print a" sec"}'
6
  • 2
    Don't pipe grep through awk. There is no need Apr 25 '18 at 9:11
  • There is no need to the TIMENOW variable either date +%s will suffice. Apr 25 '18 at 9:16
  • @RamanSailopal thanks.. updated my answer.
    – Siva
    Apr 25 '18 at 9:33
  • @SivaPrasath : actaully i dont want uptime, instead i want duration since uptime(for how long system is up). And doing so it's also a complex thing. first i have to save uptime & current time, and calculate difference between that in seconds. Apr 25 '18 at 10:20
  • 1) 3 day 18h 2) 3 day 3) 3h 15min 4) 3h 5) 15min 10sec 6) 15min 7) 10sec i only want to convert above format into seconds through a function or using awk Apr 25 '18 at 10:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.