Rotem Bar Rotem Bar - 1 year ago 89
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


Input=0x50fd <-- last char only change

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:


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 !


Answer Source

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


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 -

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

  if test "$i" = "0x50ff" ; then

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

  usleep 500000

Sample output


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.