Hi everybody!!

Here is the problem,

I'm trying to develop a script that can help me with the raid creation, but, till now, I have been dealing for more than a week and I still didn't achieve any satisfactory results. :icon_cry:

Here is the code to execute:

# mdadm --manage /dev/md0 --add /dev/sdb1
# mdadm --manage /dev/md1 --add /dev/sdb2
# mdadm --manage /dev/md2 --add /dev/sdb3
# mdadm --manage /dev/md3 --add /dev/sdb4

This wouldn't be difficult at all if this script was by itself but it comes after a partition disk operations and before I use grub for define the boot.

Here is how the structure of my global program looks like:

Global.sh
./Script for disk partition

./Mdadm script

./Grub script

The main problem is that the "grub script" must wait the "mdadm" one, otherwise it has no sense and it will return a mistake.

Because I'm a newbie in shell scripting I have been browsing around and I tried some of the things that look alike, but never I found a particular solution for this. :icon_confused:

Here is the last one I tried

mdadm --manage /dev/md0 --add /dev/sdb1 &
wait $!
until [ $? == "0" ]
do
clear
cat /proc/mdstat #I want to know the status of the procedure at any time
sleep 1
done
......
...... #The same for the rest of cases


It doesn't works even with the first one of them, It looks that doesn't goes inside the "until" and if I push a couple of times "enter" I can reach the prompt .

mdadm --manage /dev/md0 --add /dev/sdb1 &
mdadm --manage /dev/md1 --add /dev/sdb2 &
mdadm --manage /dev/md2 --add /dev/sdb3 &
mdadm --manage /dev/md3 --add /dev/sdb4 &
wait $!

This also doesn't works in the way I need, I can reach the prompt and grub doesn't wait.

Let's summarize:
*I would like to make an script with this commands inside

# mdadm --manage /dev/md0 --add /dev/sdb1
# mdadm --manage /dev/md1 --add /dev/sdb2
# mdadm --manage /dev/md2 --add /dev/sdb3
# mdadm --manage /dev/md3 --add /dev/sdb4

*The next script to execute (grub.sh) has to wait till all this processes are finished

Meanwhile the execution:
*In order to control the raid operations this command=> "cat /proc/mdstat" has to be execute with a little delay all the time
*The user cannot reach the prompt, thus is, the keyboard should be "blocked"

P.S.:I'm running Debian
P.S.2:Sorry for my English, I hope we can understand each other :icon_rolleyes:

Thanks for any collaboration :icon_idea:

Recommended Answers

All 10 Replies

If you ignore the "progress indicator" for the moment, does this actually work ?

# mdadm --manage /dev/md0 --add /dev/sdb1
# mdadm --manage /dev/md1 --add /dev/sdb2
# mdadm --manage /dev/md2 --add /dev/sdb3
# mdadm --manage /dev/md3 --add /dev/sdb4

Does /proc/mdstat exist before the first command starts, and after the last command exits?

Of course Salem, you should ignore this --> # :icon_wink:
I'm just using it for make a difference between the prompt line and the stuff inside the script. Did you see any "#" inside the script? Of course you did, it is used for comments. :icon_wink:

I might be wrong but I think that you completely missed the point. The process that has to wait it is not write down there (it is call "grub"), you don't need it.
The main problem is to make this mdadm process to wait till it is finish. Then the next process can begin.
Probably the problem is, that the mdadm is in the background and will move on to the next command while it is still executing in the background.

Maybe the solution is to control the mdadm processes.Therefore checking if mdadm processes (or any kind of processes) are still active it would be the best.
But, because I'm a newbie I don't how to design this stuff :icon_cry:

Run mdadm in the forground, hence sequentially.
Run your progress in the background, then kill it when you're done.

And thanks for the explanations :icon_rolleyes:

And,
how do you force them to run in the foreground? :icon_confused:

you could put a flag in a file in /tmp that the script could check for to make sure the last script completed before starting the next one!

Thanks for the idea chris5126 but due to the lack of knowledge in shell script I need something more than that, maybe some code would help a lot.

By the way, I think that the best option would be if someone show me how to control the PIDs.
Linux assigns a PID to every process, so then we have two possibilities:
1. To know which PID has be assigned and control it
2. To assign by ourselves a PID number so we can control everything from the beginning.

As a matter of fact I don't really know if any of the options are possible, but I hope someone can give a clear description.

Thx.

Hey there,

To run them in the foreground, as Salem suggested, just remove the trailing ampersand on all your mdadm commands, so:

mdadm --manage /dev/md0 --add /dev/sdb1 &

becomes

mdadm --manage /dev/md0 --add /dev/sdb1

and so forth. If you want to run all the mdadm commands at once in a script, but not have the next script execute until all of your backgrounded (&) mdadm processes form the mdadm script have completed, you can either manage your PID's by checking for each of them on each execution of mdadm (because you'll need to track them all) or put down /tmp/.lock files or something and have your mdadm script loop until the processes all die and it removes all the lock files. Something like:

while :
do
check for process pid and
remove lock file if not running
else
continue if still running
done

Pseudo code-ish

, Mike

ok a very simple way to do it would be at the start of the important script that the others have to wait for add the following line.

touch /tmp/wait

then at the end of the script do the following

rm /tmp/wait

Then in the script you need to wait for the first script to finish put the code thats needs to be executed after the following code

#!/bin/ksh
while [ -f /tmp/wait ]
do
  echo "waiting for other script to finish"
done
echo "first script finished running second script"

(you dont have to have the echos in there they are just for debug)

If you want to do it with PID then let me know and I can write you some similar code, but this is prob adequate for what you need.

To do it using PID which will just make your life more complicated!!!
In the first script (the important one/the one the others need to wait for) put the following code at the top.

PID=/var/run/(nameofprogram).pid
if [ -f $PID ]
  then
    if /usr/ucb/ps -auxww | grep `cat $PID` > $TMP
    then
      if grep (name of program) $TMP > /dev/null 2>&1
      then
        echo "im already running"
        exit 1
      else
        echo $$ > $PID
      fi
    else
      rm $PID
    fi
  else
    echo $$ > $PID
  fi

and this code at the bottom

rm $PID

This code above will check that two instances of the same script arent running. It does it by getting the pid of the current script and put it into a file $PID. You can then add the following code in other scripts to check if the process is running or finished

PID=/var/run/(nameofprogram).pid (must be the same file as used above)
if [ -f $PID ]
then
   if /usr/ucb/ps -auxww | grep `cat $PID` > $TMP
   then
       if grep (program name your waiting on) $TMP > /dev/null 2>&1
        then
           echo "the first script hasnt finished yet process id `cat $PID` still running"
           exit 1
         else
           #the process has finished but the PID file hasnt been removed
           rm $PID
           #you can then carry on executing the code from the second script as
           #the first script has finished
        fi
     else
          #again you can start your program here as the first script is done
    fi
else
   #again you can start your program here as the first script is done
fi

The code basically does the following:
check for a PID file if there isnt a PID file then run the next script.
If there is one check the PID still relates to the correct process if it does then exit as the first script is still running. If not run the next script

Thanks everybody for your help and specially to chris5126 for your efforts witting all that code, I think that it will definitely solve my problem and, despite complicated, it is what I was looking for all around.

Again thx. :)

P.S.: One more and last point. About eggi's suggestion, what Salem didn't understood is that I know the basic difference between background and foreground, thus is, the using of the "&" character after a command make it run into the background. But, in this case, I think that those mdadm commands are running from the beggining in the background by default, that's the reason I wanted to force them to move to the foreground. Ok, Maybe that question for another thread. :P

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.