LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   bash scripting (http://www.linuxquestions.org/questions/programming-9/bash-scripting-930558/)

Ronayn 02-21-2012 03:08 PM

bash scripting
 
Hello,

I am working on a bash script that does some initial setup for, then launches several applications (in the background). These applications (4 in total) execute simultaneously and coordinate with each other. The all continue to execute until closed by the user.

What I'd like to know is if it is possible to program the bash script that launches these apps to "lie and wait" for all of them to exit? (So that some cleanup can be done.)

Here's what my script looks like...

Code:

#!/bin/bash

< Setup code is here>


gnome-terminal -t "$BUILD_NAME: App #1" -e "$APP1 $BUILD_NAME $HOST_NAME $RUN_DIR" &
sleep 1

COMMAND="mpiexec -machinefile ../cfg/machine-file.txt -n 4 $APP2"
gnome-terminal -t "$BUILD_NAME: App #2"  -e "$COMMAND" &
sleep 1

COMMAND="$APP3 -display $(hostname):0"
gnome-terminal -t "$BUILD_NAME: App #3"  -e "$COMMAND" &
sleep 1

COMMAND="$APP4 -display $(hostname):0"
gnome-terminal -t "$BUILD_NAME: App #4"  -e "$COMMAND" &
sleep 1


jhwilliams 02-21-2012 03:14 PM

Absolutely.

Something like this would work:
Code:

pid_list=''

command_foo &
pid_list="$pid_list $!"

comand_bar &
pid_list="$pid_list $!"

# Process Barrier
while [ -n "$pid_list" ]; do
    echo "Waiting for processes to terminate: $pid_list"
    sleep 5
done

# Everything's done now.


GamezR2EZ 02-21-2012 03:52 PM

jhwilliams has a great solution. Another is making use of the wait command.

Code:

command_foo &
fooprocess=$!

wait $fooprocess

EDIT: corrected code

jhwilliams 02-21-2012 04:01 PM

Quote:

Originally Posted by GamezR2EZ (Post 4608543)
jhwilliams has a great solution. Another is making use of the wait command.

Code:

command_foo &
fooprocess="$pid_list $!"

wait $fooprocess


I like this better.

Dark_Helmet 02-21-2012 04:55 PM

I know jhwilliams said "something like this" but I just wanted to point out that his example, as written, would be an infinite loop. Specifically:
Code:

[ -n "$pid_list" ]
would never evaluate to false once the loop is entered. In other words, there is nothing inside the loop to change the value of the pid_list variable.

I would also vote for wait. Though, perhaps a merger of the efforts of jhwilliams and GamezR2EZ:
Code:

#!/bin/bash

# < Setup code is here>

# A variable containing a space-separated list of all process IDs spawned
pid_list=''

# Process #1
gnome-terminal -t "$BUILD_NAME: App #1" -e "$APP1 $BUILD_NAME $HOST_NAME $RUN_DIR" &
pid_list="$pid_list $!"
sleep 1

# Process #2
COMMAND="mpiexec -machinefile ../cfg/machine-file.txt -n 4 $APP2"
gnome-terminal -t "$BUILD_NAME: App #2"  -e "$COMMAND" &
pid_list="$pid_list $!"
sleep 1

# Process #3
COMMAND="$APP3 -display $(hostname):0"
gnome-terminal -t "$BUILD_NAME: App #3"  -e "$COMMAND" &
pid_list="$pid_list $!"
sleep 1

# Process #4
COMMAND="$APP4 -display $(hostname):0"
gnome-terminal -t "$BUILD_NAME: App #4"  -e "$COMMAND" &
pid_list="$pid_list $!"
sleep 1

for processID in ${pid_list} ; do
  wait ${processID}
done

# < Cleanup code is here>

NOTE: The pid_list assignment statements must come before the sleep command. Otherwise, you'll get the process ID of the sleep command and not the gnome-terminal.

It waits for each process ID in sequence. There is a danger in this approach. Say process #1 runs for days, but process 4 runs for a few seconds. There is a chance that process 4's process ID will be re-used by the system. So, it's possible that the script would end up waiting on a process it did not spawn itself.

To avoid that, you probably need to use a polling loop (like in jhwilliams original post) that checks each process ID in the list once every X seconds/minutes/hours. Then, if the process is gone, remove that ID from your checklist.

EDIT:
Corrected a few things... I referenced "waitpid" instead of "wait" which is incorrect. "waitpid" is a function in C... not a shell command. :)

Ronayn 02-22-2012 06:02 AM

Wow! Thanks to all for the replies!

Reuti 02-23-2012 10:17 AM

Is there any reason not to use wait without any process ID? It will wait for all spawned processes if none is given.

NB: There is the command jobs to list all spawned background processes and jobs -p to list all process IDs at once.

s4sandeep 03-16-2012 06:13 AM

word count program help
 
Hi,

I have recently started working in bash script and currently creating short programs and I could not find the path to create a new thread, I just tried to create the program for counting the words in a file but its not running successfully.

program:

#!/bin/bash
num=`wc -l test1.sh`
echo $num
if
[ "$num" -gt "1" ]
then
echo "this is gt 1"
fi

other information:
the number of lines in test1.sh file is 3.

error:
verma@verma-Lenovo-G560:~/shell-scripts$ sh test.sh
3 test1.sh
[: 8: Illegal number: 3 test1.sh


Could someone please help on same,thanks in advance.

Regards
Sandeep Verma

Reuti 03-16-2012 06:46 AM

Please check the output of the wc command, this needs to be trimmed.

NB: In the forum overview “Forum Tools” (near the right side) => “Post New Thread”

s4sandeep 03-20-2012 04:33 AM

Quote:

Originally Posted by Reuti (Post 4628239)
Please check the output of the wc command, this needs to be trimmed.

NB: In the forum overview “Forum Tools” (near the right side) => “Post New Thread”

The issue is still pending, can you tell me how can I trim this?

Reuti 03-20-2012 04:59 AM

The output of wc includes the filename, and there is no option to leave it out, hence a reference to the plain line count could be:
Code:

${num%% *}
This will remove the blank and anything behind.

Instead of wc you could also use awk to get the number of line directly without a filename:
Code:

awk 'END {print NR}' test1.sh

s4sandeep 03-20-2012 05:46 AM

Quote:

Originally Posted by Reuti (Post 4631331)
The output of wc includes the filename, and there is no option to leave it out, hence a reference to the plain line count could be:
Code:

${num%% *}
This will remove the blank and anything behind.

Instead of wc you could also use awk to get the number of line directly without a filename:
Code:

awk 'END {print NR}' test1.sh


Many thanks reuti! This resolved the problem!!


All times are GMT -5. The time now is 08:47 PM.