Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for subshell process to complete

Tags:

linux

bash

processUsageFile()
{
    #sdate=`pin_virtual_time  | awk -F" " '{print $3}'`;

    #Get all new files to be loaded to brm staging data.
    count=`ls ${PRE_STAGING}/TWN* 2>/dev/null|grep -v reprocess|wc -l`
    if [ $count -ne 0 ];then
        # Fork subshell
        (./efx_omc_brm_rpt_process.sh -t TWN & )&
        exitOnError
    fi

    #Process Rapid Report files
    count=`ls $PRE_STAGING/RR* 2>/dev/null|grep -v  reprocess|wc -l`
    if [ $count -ne 0 ];then
        (./efx_omc_brm_rpt_process.sh -t RR &)&
        exitOnError
    fi
...
...
}
#Reprocessing. Process the reprocessed files.
#This method updates the records in the BRM staging table.
reprocessingUsageFile()
{
    #Process TWN fulfillment reprocess files
    count=`ls $PRE_STAGING/TWN*reprocess* 2>/dev/null|wc -l`
    if [ $count -ne 0 ];then
        # Fork subshell
        (./efx_omc_brm_rpt_reprocess.sh -t TWN & ) &
    fi

    #Process Rapid Report files
    count=`ls $PRE_STAGING/RR*reprocess* 2>/dev/null|wc -l`
    if [ $count -ne 0 ];then
        (./efx_omc_brm_rpt_reprocess.sh -t RR &) &
    fi
...
...
}

#Pre processing
PreProcessing

# Start processing usage files.
processUsageFile

processErrFile 

The idea of the above code is do parallel processing. All methods invoke multiple subshells and detach from tty. I would like to know if there is way to wait for first two methods to complete execution first and then run the last method.

Waiting for PIDs is somehow not accurate. Still trying...

waitPids() {
echo "Testing $pids -- ${#pids[@]}"
    while [ ${#pids[@]} -ne 0 ]; do
            local range=$(eval echo {0..$((${#pids[@]}-1))})
            local i
            for i in $range; do
                if ! kill -0 ${pids[$i]} 2> /dev/null; then
                    echo "Done -- ${pids[$i]}"
                     unset pids[$i]
                fi
            done
            pids=("${pids[@]}") 
            sleep 1
        done
    }
like image 640
user2570205 Avatar asked Dec 10 '22 17:12

user2570205


2 Answers

It seems that the main problem is, that you are using detached subshells.

Maybe the easiest solution would be to use a different mechanism to detach the subshells, so you can use wait.

e.g. via nohup

 nohup ./process1 &
 nohup ./process2 &
 wait
like image 183
umläute Avatar answered Jan 03 '23 03:01

umläute


Use Wait Builtin

$ help wait
wait: wait [-n] [id ...]
    Wait for job completion and return exit status.

    Waits for each process identified by an ID, which may be a process ID or a
    job specification, and reports its termination status.  If ID is not
    given, waits for all currently active child processes, and the return
    status is zero.  If ID is a a job specification, waits for all processes
    in that job's pipeline.

    If the -n option is supplied, waits for the next job to terminate and
    returns its exit status.

    Exit Status:
    Returns the status of the last ID; fails if ID is invalid or an invalid
    option is given.

Minimalist Example

$ wait -n; (sleep 3; false); echo $?
1

Your Code as Example

Background tasks return immediately. The trick for you will be to wrap your functions in a subshell so that you're waiting for the subshell (rather than background jobs) to complete. For example:

$ wait -n; (processUsageFile); echo $?

If you want to get more complicated than that, you're going to have to capture the PID of the background tasks you're spawning in variables so that you can wait for specific processes with a construct like wait $pidof_process_1 $pidof_process_2.

Wrapping the function in a subshell is just easier. However, your specific needs may vary.

like image 28
Todd A. Jacobs Avatar answered Jan 03 '23 05:01

Todd A. Jacobs