1

I'm writing a bash script which performs an installation of stuff.

I don't want the user to see the commands and their output, so I'll redirect them using 2>&1.

I do wish to print a progress bar for each section which finished installing, and a success/failed message according if there were errors, for example:

Installing OpenCv ..................... [Success]
Installing Qt     ..................... [Failed]

Here's my code:

#!/bin/bash

installOf="Installing OpenCv  "

function printProgressBar() 
{
    local progressBar="."
    printf "%s" "${progressBar}"
}

function InstEssent
{
    sudo apt-get -y install build-essential
    sleep 5
    echo "Done"
}

printf "%s" "${installOf}"

InstEssent  &

while [ "${InstEssent}" != "Done" ]
do
    printProgressBar 
    sleep 1
done

installStatus="Success"
printf " [%s]\n" "${installStatus}"
Idanis
  • 1,918
  • 6
  • 38
  • 69

1 Answers1

2

Well, as such there are no native tools in bash or other shells I can know of, but you can use this below printf & this custom function to achieve what you need. This small snippet will print the installation progress bar which you can print by just a normal function call printProgressBar at various places in the script where you would like to show it.

function printProgressBar() {
    local progressBar="."
    printf "%s" "${progressBar}"
}

Assuming you have n steps in your function call, insert this function call at places between. For the actual printing of error message, fill the installation header in variable installOf which assuming from your example could take either "Installing OpenCv " (or) "Installing Qt ", use it in this variable before the steps as

installOf="Installing OpenCv  "
printf "%s" "${installOf}"

and for the final status, since you didn't let us know how you get the overall status of the installation, assuming you find it depending upon success or failure, update it in another variable

installStatus="Success"
printf " [%s]\n" "${installStatus}"

So putting it all together, I have this simple while loop which runs the function for 20 calls, you can use a similar way to adopt your function call at various positions in your script.

installOf="Installing OpenCv  "

function printProgressBar() {
    local progressBar="."
    printf "%s" "${progressBar}"
}

printf "%s" "${installOf}"

while (( cnt < 20))
do
    ((cnt++))
    printProgressBar 
    sleep 1
done

# You can determine the status of your installation as your script demands

installStatus="Success"
printf " [%s]\n" "${installStatus}"

Running the script produces a result something similar to your requirement,

$ bash script.sh
Installing OpenCv  .................... [Success]

Observe that, each . represents each instance of a function call.

Update:-

Looking at your code logic, you are missing a point on how background jobs work. Your background function InstEssent in installing a certain module. To use the progress bar effectively, you need to constantly to poll the background job to see it is still running using the kill -0 "$pid" command and if it is running, print the install bar as indicated in the code below.

function InstEssent()
{
    sudo apt-get -y install build-essential
    sleep 5
}

printf "%s" "${installOf}"

InstEssent  &
pid_InstEssent="$!"

while kill -0 "$pid" 2> /dev/null
do
    printProgressBar 
    sleep 1
done
Inian
  • 80,270
  • 14
  • 142
  • 161
  • I tried to implement your solution. The printing of the dots works fine. However, seems like I can't change a global variable from within a function. Is that correct? I want my function to change a "stop" variable to indicate the progress bar to stop according to the progress of the installation. – Idanis Dec 22 '16 at 14:27
  • @Idanis: Appreciate you trying out my logic, can you explain more about the problem you are seeing with some actual code? Seems a bit trivial on first look. May be this page can help you sort issues you were facing, http://stackoverflow.com/questions/23564995/how-to-modify-a-global-variable-within-a-function-in-bash – Inian Dec 23 '16 at 07:05
  • Thanks to your reply. I updated my code above. When I run this code, I don't see any dots at all, the function finishes its run, prints "Done" and then the script quits with a "Success" message. Here's what I'm trying to achieve: I'm trying to run this function "in the background" and print dots until it finishes. When it's done, I wish to print the Success/Failed message. I'm missing something here, but I just don't know what.. – Idanis Dec 25 '16 at 08:35