0

I'm trying to watch and output the progress of a longer script. (Later I want to use the Progress to calculate a progress bar).

Here is a shortened example:

#!/bin/bash

PROGRESS=0

updateprogress () {
    PROGRESS=$((PROGRESS + 1))
    echo $PROGRESS
}

<do something>
updateprogress

sudo cat /root/.virtualMachines | while read -r name ipAddr        # <-7 lines 
do
    <do something>
    updateprogress
done

sudo cat /root/.virtualServices | while read -r name ipAddr        # <-3 lines
do
    <do something>
    updateprogress
done

What I would expect now would be an Output like

1    <-# before the first while)
2
3
4
5
6
7
8    <-# end of first while)
9
10
11   <-# end of second while)

But what I get is

1    <-# before first while)
2
3
4
5
6
7
8    <-# end of first while
2
3
4    <-# end of second while

So the issue has to be something about the global/local scope but how can I use only the global variable $PROGRESS I defined at the top for all function calls?

derHugo
  • 83,094
  • 9
  • 75
  • 115

1 Answers1

0

The pipe creates a new context to execute the insctuctions passed to it. If you add the following line to your code, you'll see the caveat :

#beggining of your code ...
#second while loop
sudo cat /root/.virtualServices | while read -r name ipAddr (3 times)
do
    <do something>
    updateprogress
done
echo $PROGRESS #will display '2'

To address this issue, you should refactor your while loops without the pipe, as follow :

while read -r name ipAddr
do
    #some instructions
done < "path/to/the/file"

Using the stream redirection will not create a new context, and will produce the results you expect

Aserre
  • 4,916
  • 5
  • 33
  • 56
  • 1
    Hey thanks :) I only had to modify a detail: Since I have to use sudo I did it like this `done <<< $(sudo cat /root/.virtualMachines)` – derHugo Jul 27 '17 at 11:21
  • That works fine as a workaround. Otherwise, you could keep my version and call the whole script with sudo, it should work fine. Keep your version if you only want the file access to be executed with elevated permissions and not the rest of the script though. – Aserre Jul 27 '17 at 11:25
  • Ok so mabay I'll use it like this later. I'm still writing it and deleting some files and so on and prefer not to run the whole thing as root. Butanyway thanks for your help! It works fine now – derHugo Jul 27 '17 at 11:28
  • Use `done; < <(sudo cat ...)` instead, especially if the files are of any significant length. This avoids reading the entire file into memory at once. – chepner Jul 27 '17 at 12:45