Get exit status of background processes in bash
PIDS+=$!
...doesn't do what you think it does. Consider:
PIDS=( )
PIDS+=11
PIDS+=22
PIDS+=33
declare -p PIDS
...if what you expect this to output is:
declare -a PIDS='([0]="11" [1]="22" [2]="33")
...you'd be mistaken, because what it actually emits is:
declare -a PIDS='([0]="112233")'
...because +=
only appends a new array element when the thing on the right-hand side is an array.
Thus, you get a not a child of this shell
error because the result of concatenating all your PIDs together into a single string isn't a PID that actually exists.
To fix it, use parens: PIDS+=( "$!" )
To provide an end-to-end example:
#!/usr/bin/env bash
# run four different processes; two exit status 0, one exits status 1, on exits status 2
# ...exits happen at delays ranging between 2-5 seconds.
delays=( 5 3 2 4 )
exits=( 0 0 1 2 )
for idx in "${!delays[@]}"; do
(sleep "${delays[$idx]}"; exit "${exits[$idx]}") &
pids+=( "$!" )
done
exit_status=0
for pid in "${pids[@]}"; do
wait "$pid"; (( exit_status |= $? ))
done
echo "Combined exit status is $exit_status"
exit "$exit_status"
...properly exits after 5 seconds with:
Combined exit status is 3
Bash: How to get exit code of a command while using a spinner?
wait
will tell you what exit status a child PID exited with (by setting that program's exit status as its own), when given that PID as an argument.
sleep 2 & sleep_pid=$!
spinner "$sleep_pid"
wait "$sleep_pid"; exitCode=$?
echo "exitcode: $exitCode"
Note that combining multiple commands onto a line when collecting $!
or $?
in the second half is a practice I strongly recommend -- it prevents the value you're trying to collect from being changed by mistake (as by someone adding a new log line to your code later and not realizing it has side effects).
Get exit status of child process on background
After the child process has been spawned, the parent will need to call waitpid
periodically with the WNOHANG
flag. Using this flag will cause the function to return immediately, after which you need to check the status to see if the process actually exited or not.
For example:
int child_done;
do {
// do something useful
child_done=0;
if (waitpid(pid,&status,WNOHANG) > 0) {
if (WIFEXITED(status)) {
printf("child exited with status %d\n", WEXITSTATUS(status));
child_done = 1;
}
if (WIFSIGNALED(status)) {
printf("child terminated by signal %d\n", WTERMSIG(status));
child_done = 1;
}
}
} while (!child_done);
Related Topics
How to Change the Output Color of Echo in Linux
How to Search For a Multiline Pattern in a File
Merge/Convert Multiple Pdf Files into One Pdf
Ld Cannot Find an Existing Library
Why Does a Jvm Report More Committed Memory Than the Linux Process Resident Set Size
Setting the Umask of the Apache User
What's the Difference Between "Statically Linked" and "Not a Dynamic Executable" from Linux Ldd
How to Configure Qt For Cross-Compilation from Linux to Windows Target
Shell/Bash Shortcut For Bulk Renaming of Files in a Folder
Using the Passwd Command from Within a Shell Script
Argument List Too Long Error For Rm, Cp, Mv Commands
What's the Difference of Section and Segment in Elf File Format
Exploring Docker Container'S File System
How to Remove ^[, and All of the Escape Sequences in a File Using Linux Shell Scripting
How to Loop Over the Output of a Shell Command