Rotem Bar Rotem Bar - 1 month ago 12
Bash Question

using awk and bash for monitoring exec output to log

I am looking for some help with awk and bash commands,
my project have an embedded (so very limited) hardware,
i need to run a specific command called "digitalio show"
the command output is:

Input=0x50ff <-- last char only change
Output=0x7f

OR

Input=0x50fd <-- last char only change
Output=0x7f


i need to extract the input parameter and convert it into either Active or Passive and log them to a file with timestamp.

the log file should look like this:

YYMMDDhhmmss;Active
YYMMDDhhmmss;Passive
YYMMDDhhmmss;Active
YYMMDDhhmmss;Passive


while logging only changes

The command "digitalio show" is an embedded specific command that give the I/O state at the time of the execution, so i basically need to log every change in the I/O into a file using a minimal tools i have in the embedded H/W.

i can run the command for every 500msec, but if i will log all the outputs i can finish the flash very quickly, so i need only log changes.

in the end this will run as a background deamon.

Thanks !

Rotem.

Answer

As far as I understand, a single run of digitalio show command outputs two lines in the following format:

Input=HEX_NUMBER
Output=0x7f

where HEX_NUMBER is either 0x50ff, or 0x50fd. Suppose, the former stands for "Active", the latter for "Passive".

Running the command once per 500 milliseconds requires keeping the state. The most obvious implementation is a loop with a sleep.

However, sleep implementations vary. Some of them support a floating point argument (fractional seconds), and some don't. For example, the GNU implementation accepts arbitrary floating point numbers, but the standard UNIX implementation guarantees to suspend execution for at least the integral number of seconds. There are many alternatives, though. For instance, usleep from killproc accepts microseconds. Alternatively, you can write your own utility.

Let's pick the usleep command. Then the Bash script may look like the following:

#!/bin/bash -

last_state=
while true ; do
  i=$(digitalio show | awk -F= '/Input=0x[a-zA-Z0-9]+/ {print $2}')

  if test "$i" = "0x50ff" ; then
    state="Active"
  else
    state="Passive"
  fi

  if test "$state" != "$last_state" ; then
    printf '%s;%s\n' $(date '+%Y%m%d%H%M%S') "$state"
  fi

  last_state="$state"
  usleep 500000
done

Sample output

20161019103534;Active
20161019103555;Passive

The script launches digitalio show command in an infinite loop, then extracts the hex part from Input lines with awk.

The $state variable is assigned to whether "Active", or "Passive" depending on the value of hex string.

The $last_state variable keeps the value of $state in the last iteration. If $state is not equal to $last_state, then the state is printed to the standard output in the specific format.

Comments