If you know N beforehand, you can use fifo as a semaphore.
mkfifo sem; exec 3<>sem rm -f sem
Then make each N>1 process read a byte from that &3. Since those bytes won't initially be available, it'll put them to sleep as well.
Once N==1 is done sleeping, it can write a N bytes into &3, waking up each process that has been waiting on a byte from &3.
#!/bin/bash -e mkfifo p exec 3<>p rm p main()( echo $FUNCNAME beg sleep 2 &>/dev/null printf '\n\n\n' >&3 echo $FUNCNAME end ) worker()( echo $FUNCNAME$1 beg read -n 1 <&3 echo $FUNCNAME$1 end ) main & worker 1 & worker 2 & worker 3 & wait
Output:
main beg worker1 beg worker2 beg worker3 beg main end worker2 end worker3 end worker1 end
Another way to do this might be with signals. If you can make sure your script is run as a terminal job with $$ (parent shell pid) being the process group id of the corresponding process group, then you can make your workers sleep indefinitely (ideally with processes calling the pause function; or with sleep $hugevalue if you can't do the former) and before that, make them establish a handler e.g., for SIGUSR1. The main process first worker should ignore the signal. The first worker can then singnal all other workers by kill -SIGUSR1 -$$, which will kill the indefinite sleepers, making the workers continue.
#!/bin/bash trap ' ' SIGUSR1 main()( trap - SIGUSR1 echo $FUNCNAME beg sleep 2 &>/dev/null echo $FUNCNAME end kill -s SIGUSR1 -$$ ) worker()( trap ' ' SIGUSR1 echo $FUNCNAME$1 beg sleep 10000000000 &>/dev/null echo $FUNCNAME$1 end ) main & worker 1 & worker 2 & worker 3 & wait
Output:
main beg worker2 beg worker1 beg worker3 beg main end User defined signal 1 worker1 end User defined signal 1 worker3 end User defined signal 1 [1] 31554 user-defined signal 1 ./scr1
(I don't know how to turn off the "user-defined signal 1" messages)
run.shforks N copies ofscript.shin parallel? Because if it's sequential then the second (and subsequent) instances ofscript.shwon't start until the previous one has completed. Unlessscript.shforks itself into the background, I suppose. Can you provide a (cut down) example of the code inrun.shthat starts upscript.shplease.script.shprocesses to do anything until the first one initializes, why start them at all? There are numerous ways you could signal the parent process to continue from the child. You couldwaitin the parent and have the child fork when ready. You couldkill -STOP $$from the parent andkill -CONT $PPIDfrom the child. You could share a pipe, have the parent block reading, and the child send something on it when ready. You could grab a lock on a file, and release the lock when ready. The list goes on.script.shand add at the beginning ofrun.sh?inotifywaitto wait for a specific action.