Bash script that shows changing real time values from commands

6,948

Solution 1

It might be tricky to implement a real time solution in bash.

There are many ways to run script once in X seconds you can use watch. I assume you already have myScript.sh available. Replace X with number of seconds you need.

  1. watch -n X ./myScript.sh

  2. while sleep X; do ./myScript.sh; done

    upd. to emulate watch you might want to clear the screen in between iterations. inside the script it will look this way:

    while sleep X; do 
       clear; 
       command1;
       command2;
    done
    
  3. add one of options above to the script itself.

Solution 2

You can use tput cup 0 0 to send the cursor up to the top left of the screen. clear once.

#!/bin/bash
clear
while sleep 1; do
    tput cup 0 0
    printf "%21s %6d    \n" \
      "Célula calibrada: "   $(npe ?AI1) \
      "Anemómetro: "         $(npe ?AI2) \
      "Célula temperatura: " $(npe ?AI3) \
      "Célula temperatura: " $(npe ?AI4)
done

Solution 3

I am assuming the flicker is because your commands take a moment to return their values. This is my usual workaround:

cmds(){
  echo "Célula calibrada: " $(npe ?AI1);
  echo "Anemómetro: " $(npe ?AI2);
  echo "Célula temperatura: " $(npe ?AI3);
  echo "Célula temperatura: " $(npe ?AI4);
}

while true; do
  out="$(cmds)"
  clear
  echo "$out"
  sleep 1
done

The idea being that we clear the screen at the last possible moment.

Solution 4

If you clear immediately after the sleep, rather than immediately before, you'll be able to read the output more easily:

#!/bin/sh
while sleep 1
do
   clear
   echo "Célula calibrada: " $(npe ?AI1)
   echo "Anemómetro: " $(npe ?AI2)
   echo "Célula temperatura: " $(npe ?AI3)
   echo "Célula temperatura: " $(npe ?AI4)
done

However, I'd remove the loop here, and use watch to run the script repeatedly. That's a more flexible composition of individual tools.

Solution 5

You can do it exactly in bash. If the text is still flashing, you have not read the previous answers completely.

You have to clear the screen before you echo the new values, not after.

Share:
6,948
balon
Author by

balon

Updated on September 18, 2022

Comments

  • balon
    balon over 1 year

    On a Linux machine I have a series of commands that offer numerical values of the state of different sensors.

    The call of these commands is something similar to the following:

    $ command1
    5647
    $ command2
    76
    $ command3
    8754
    

    These values change in real time, and every time I want to check the status of one of them, I have to re-launch the command... This doesn't do me any good since I need both hands to manipulate the hardware.

    My goal is to make a simple Bash Script that calls these commands and keeps the value updated (in real time asynchronously or refreshing the value every x seconds) like this:

    $ ./myScript.sh
    command1: x
    command2: y
    command3: z
    command4: v
    

    Where x, y, z and v are the changing values.

    Bash allows this simply and efficiently? or should I choose to do it in another language, like Python?

    UPDATE with more info:

    My current script is:

    #!/bin/bash
    echo "Célula calibrada: " $(npe ?AI1)
    echo "Anemómetro: " $(npe ?AI2)
    echo "Célula temperatura: " $(npe ?AI3)
    echo "Célula temperatura: " $(npe ?AI4)
    

    npe being an example command that returns the numeric value. I expect an output like this:

    enter image description here

    This output I get with the command watch -n x ./myScript.sh, where x is refresh value of seconds. If I edit my script like this:

    #!/bin/bash
    while sleep 1; do
       clear; # added to keep the information in the same line 
       echo "Célula calibrada: " $(npe ?AI1);
       echo "Anemómetro: " $(npe ?AI2);
       echo "Célula temperatura: " $(npe ?AI3);
       echo "Célula temperatura: " $(npe ?AI4);
    done
    

    I get my output with an annoying flicker:

    enter image description here

  • balon
    balon over 4 years
    It's a good solution, but depending on several factors, there may be 2 or 20 commands, and throwing one line behind another with so many commands may make it uncomfortable to see... That's why I'm looking for a solution that keeps your own line up to date, without adding new ones.
  • balon
    balon over 4 years
    An example of this can be APT's status line, which updates its values on the same line: 35% [3 Packages 3,155 kB/9,540 kB 33%
  • balon
    balon over 4 years
    The watch command is what I need, as it keeps the output on the same line updated! Hence my question: if I could do the same without using external tools; directly integrated such functionality into my script.
  • rush
    rush over 4 years
    You could modify the second option to emulate watch. Just add clear inside the loop. I added it to my answer.
  • balon
    balon over 4 years
    If I handle this the output of the script is illegible, they are blinking lines...
  • balon
    balon over 4 years
    I updated the post with more information and the problem I have with clear in the script
  • balon
    balon over 4 years
    This is my goal... that the output of the script is the same as the output with watch, and my question is whether this is possible without using wath or other external tools.
  • balon
    balon over 4 years
    I updated the post with the new changes, but this only slightly improves the visualization, the blinking persists.
  • Paul Sinclair
    Paul Sinclair over 4 years
    This needs modified to either print in a fixed width format, or clear the values before writing new ones (tput can do that as well). Otherwise if a value drops in size by a digit, the final digit from the previous value will not be overwritten, causing the number seen to be wrong.
  • Angel Todorov
    Angel Todorov over 4 years
    Good point. I'm on my phone now so can't test but I'll edit.
  • Olivier Dulac
    Olivier Dulac over 4 years
    @rush: you need to have the clear BEFORE the commands that displays results.. here: it display results, then immediately clear, then loop back to the sleep X (so the cleared screen is shown for X seconds).
  • rush
    rush over 4 years
    @OlivierDulac good point. fixed it. thx.
  • Paul_Pedant
    Paul_Pedant over 4 years
    If you are going to clear the screen every time, then it will be blank for a few milliseconds, the bottom longer than the top. I am doing 30 individual date commands per second, and the difference between line 1 and line 30 is 0.11 seconds. How many rows of output do you have? You could use tput commands to avoid clearing, and just modify the actual changed numbers. Minimise the window size to just fit the data, because clear has to wipe the whole window.
  • Paul_Pedant
    Paul_Pedant over 4 years
    Remove the "in situ" -- it's a typo that should be at the end of the first sentence.
  • M. Rostami
    M. Rostami over 3 years
    watch -n 0.1 [command] make it funnier. As an example: watch -n 0.1 df -m that will shows you the real-time storage size monitoring.