Get exit code of a background process Get exit code of a background process unix unix

Get exit code of a background process


1: In bash, $! holds the PID of the last background process that was executed. That will tell you what process to monitor, anyway.

4: wait <n> waits until the process with PID <n> is complete (it will block until the process completes, so you might not want to call this until you are sure the process is done), and then returns the exit code of the completed process.

2, 3: ps or ps | grep " $! " can tell you whether the process is still running. It is up to you how to understand the output and decide how close it is to finishing. (ps | grep isn't idiot-proof. If you have time you can come up with a more robust way to tell whether the process is still running).

Here's a skeleton script:

# simulate a long process that will have an identifiable exit code(sleep 15 ; /bin/false) &my_pid=$!while   ps | grep " $my_pid "     # might also need  | grep -v grep  heredo    echo $my_pid is still in the ps output. Must still be running.    sleep 3doneecho Oh, it looks like the process is done.wait $my_pid# The variable $? always holds the exit code of the last command to finish.# Here it holds the exit code of $my_pid, since wait exits with that code. my_status=$?echo The exit status of the process was $my_status


This is how I solved it when I had a similar need:

# Some function that takes a long time to processlongprocess() {        # Sleep up to 14 seconds        sleep $((RANDOM % 15))        # Randomly exit with 0 or 1        exit $((RANDOM % 2))}pids=""# Run five concurrent processesfor i in {1..5}; do        ( longprocess ) &        # store PID of process        pids+=" $!"done# Wait for all processes to finish, will take max 14s# as it waits in order of launch, not order of finishingfor p in $pids; do        if wait $p; then                echo "Process $p success"        else                echo "Process $p fail"        fidone


The pid of a backgrounded child process is stored in $!.You can store all child processes' pids into an array, e.g. PIDS[].

wait [-n] [jobspec or pid …]

Wait until the child process specified by each process ID pid or job specification jobspec exits and return the exit status of the last command waited for. If a job spec is given, all processes in the job are waited for. If no arguments are given, all currently active child processes are waited for, and the return status is zero. If the -n option is supplied, wait waits for any job to terminate and returns its exit status. If neither jobspec nor pid specifies an active child process of the shell, the return status is 127.

Use wait command you can wait for all child processes finish, meanwhile you can get exit status of each child processes via $? and store status into STATUS[]. Then you can do something depending by status.

I have tried the following 2 solutions and they run well. solution01 is more concise, while solution02 is a little complicated.

solution01

#!/bin/bash# start 3 child processes concurrently, and store each pid into array PIDS[].process=(a.sh b.sh c.sh)for app in ${process[@]}; do  ./${app} &  PIDS+=($!)done# wait for all processes to finish, and store each process's exit code into array STATUS[].for pid in ${PIDS[@]}; do  echo "pid=${pid}"  wait ${pid}  STATUS+=($?)done# after all processed finish, check their exit codes in STATUS[].i=0for st in ${STATUS[@]}; do  if [[ ${st} -ne 0 ]]; then    echo "$i failed"  else    echo "$i finish"  fi  ((i+=1))done

solution02

#!/bin/bash# start 3 child processes concurrently, and store each pid into array PIDS[].i=0process=(a.sh b.sh c.sh)for app in ${process[@]}; do  ./${app} &  pid=$!  PIDS[$i]=${pid}  ((i+=1))done# wait for all processes to finish, and store each process's exit code into array STATUS[].i=0for pid in ${PIDS[@]}; do  echo "pid=${pid}"  wait ${pid}  STATUS[$i]=$?  ((i+=1))done# after all processed finish, check their exit codes in STATUS[].i=0for st in ${STATUS[@]}; do  if [[ ${st} -ne 0 ]]; then    echo "$i failed"  else    echo "$i finish"  fi  ((i+=1))done