13

I want to synchronize between processes. My computer has two cores. User can enter the simulation number from command line. If input is greater than 2, the 3rd and other processes have to wait until one of the earlier processes is finished. If one of them is finished, the next process should be started. For example, say the first two processes are already running. The first process finishes before the 2nd. Now the 3rd process should be start.

I am new in bash, I figured out. It is seen that anywait: command not found. How can I do that? Here is my script:

#!/bin/bash
# My first script

count=2
echo -n "Please enter the number of simulation :"
read number
echo "Please enter the algorithm type  "
printf "0 for NNA\n1 for SPA\n2 for EEEA :"

while read type; do
    case $type in
        0 ) cd /home/cea/Desktop/simulation/wsnfuture 
        taskset -c 0 ./wsnfuture -u Cmdenv omnetpp.ini > /home/cea/Desktop/simulation/RESULTS/NNA/NNA0/0 &
        taskset -c 1 ./wsnfuture -u Cmdenv omnetpp.ini > /home/cea/Desktop/simulation/RESULTS/NNA/NNA0/1 &
        while [ $count -lt $number ]; do
        anywait
            cd /home/cea/Desktop/simulation/wsnfuture 
        mkdir /home/cea/Desktop/simulation/RESULTS/NNA/NNA$count
        taskset -c $((count % 2)) ./wsnfuture -u Cmdenv omnetpp.ini > /home/cea/Desktop/simulation/RESULTS/NNA/NNA$count/$count &
            count=$((count + 1))
        done 
        ;;
        1 ) while [ $count -lt $number ]; do
            cd /home/cea/Desktop/simulation/wsnfuture1
        taskset -c $((count % 2)) ./wsnfuture -u Cmdenv omnetpp.ini > /home/cea/Desktop/simulation/RESULTS/SPA/$count &
            count=$((count + 1))
        done 
        ;;
        2 ) while [ $count -lt $number ]; do
            cd /home/cea/Desktop/simulation/wsnfuture2
        taskset -c $((count % 2)) ./wsnfuture -u Cmdenv omnetpp.ini > /home/cea/Desktop/simulation/RESULTS/EEEA/$count &
            count=$((count + 1))
        done 
        ;;
        * ) echo "You did not enter a number"
        echo "between 0 and 2."
        echo "Please enter the algorithm type  "
        printf "0 for NNA\n1 for SPA\n2 for EEEA :"

    esac

done

function anywait(){
 while ps axg | grep -v grep | grep wsnfuture> /dev/null; do sleep 1; done
} 
Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
eakn
  • 311
  • 1
  • 2
  • 15
  • 1
    you can use a select statment for user response, wait for the wait, if you still needed the ps, then pgrep is better. – SaintHax May 13 '16 at 18:47
  • In general, it's _never_ good practice to use `ps` from a shell script. When you do that you're scanning the whole process table, but you should be just checking your own children directly. There are a bunch of optimizations the operating system provides for checking your children: there's the `waitpid()` function, used by the `wait` shell builtin, that can wait for a specific PID to exit and return its exit status (which `ps` can't tell you); `wait` can also be run in non-blocking mode, or in wait-for-everything mode. – Charles Duffy Dec 11 '22 at 22:20

2 Answers2

18

You can achieve a simple way of process synchronization in bash using wait which waits for one or more number of background jobs to complete before running the next.

You generally run jobs in the background by appending the & operator to the end of a command. At that point the PID (process ID) of the newly created background process is stored in a special bash variable: $! and wait command allows this process to be terminate before running the next instruction.

This can be demonstrated by a simple example

$ cat mywaitscript.sh

#!/bin/bash

sleep 3 &

wait $!     # Can also be stored in a variable as pid=$!

# Waits until the process 'sleep 3' is completed. Here the wait on a single process is done by capturing its process id

echo "I am waking up"

sleep 4 &
sleep 5 &

wait                    # Without specifying the id, just 'wait' waits until all jobs started on the background is complete.

echo "I woke up again"

Command ouput

$ time ./mywaitscript.sh
I am waking up
I woke up again

real    0m8.012s
user    0m0.004s
sys     0m0.006s

You can see the script has taken ~8s to run to completion. The breakdown on the time is

  1. sleep 3 will take full 3s to complete its execution

  2. sleep 4 and sleep 5 are both started sequentially one after next and it has taken the max(4,5) which is approximately ~5s to run.

You can apply the similar logic to your question above. Hope this answers your question.

Inian
  • 80,270
  • 14
  • 142
  • 161
  • @Camusensei: updated! I had to do that to demonstrate how the special variable can be stored in another variable too. – Inian May 13 '16 at 09:19
  • Thanks for the edit. Now if only you can change the comment from `pid=$(echo $!)` to `pid=$!` ... :) – Camusensei May 13 '16 at 09:20
  • This does not answer the actual question OP has, which is, how can I wait for any one process to be done before starting the next process. With PIDs, it's rather complicated. bash has a simple solution: `wait -n` (as in wait **next**). See https://stackoverflow.com/questions/37620703/wait-for-1-of-many-process-to-finish#answer-37621260 – Alexis Wilke Dec 11 '22 at 22:51
0

Your code has many other problems, but the answer is that you should declare anywait before using it (so moving it up in your script).

Please consider using http://www.shellcheck.net/ to at least suppress the most obvious errors/mistakes in your script.

Camusensei
  • 1,475
  • 12
  • 20