0

I have this code:

     for job in `jobs -p`; do
         code=0;
         wait ${job} || code=$?
         if [[ "${code}" != "0" ]]; then
            echo "At least one job failed with exit code => ${code}" ;
            exit 1;
         fi
     done

right after the line: echo "At least one job failed with exit code => ${CODE}" ;

I want to add a line that logs the command that failed, something like this:

     for job in `jobs -p`; do
         code=0;
         wait ${job} || code=$?
         if [[ "${code}" != "0" ]]; then
            echo "At least one job failed with exit code => ${code}" ;
            echo "The job that failed was $(ps -p ${job})"
            exit 1;
         fi
     done

not that a job is just the pid of the subprocess. The problem is that this line:

echo "The job that failed was $(ps -p ${job})"

doesn't really about anything - I need the actually command that was run, given the pid=job.

3

At the point you're running the ps command, the process already exited (you're handling its return code, right?)

Just change the logic so you run the ps command earlier in the script, before the wait and store that in a variable:

for job in $(jobs -p); do
    process_info=$(ps -p "${job}" -o args=)
    wait "${job}" || {
        code=$?
        echo "Job running [${process_info}] failed with exit code ${code}." >&2
        exit 1
    }
done
  • thanks, seems like the right idea, but not sure if this works on MacOS though, got something x-platform? – Alexander Mills Mar 24 '18 at 5:11
  • I don't see why it wouldn't... – filbranden Mar 24 '18 at 5:26
  • I just get a blank line => $process_info is just empty...I tried a lot of things...nothing is working :( – Alexander Mills Mar 24 '18 at 5:28
  • @FilipeBrandenburger You can't do this either in case the jobs exit out of order. For example, if the last job in the output of jobs -p exits first. – Kusalananda Mar 24 '18 at 7:09
0

As pointed out, you can't use ps on a non-existing process.

If you have a bash that supports associative arrays:

declare -A jobinfo

# collect job information
joblist=( $(jobs -p) )
for pid in "${joblist[@]}"; do
    jobinfo["$pid"]="$( ps -p "$pid" -o args= )"
done

# later...

# wait for jobs
err=0
for pid in "${joblist[@]}"; do
    if ! { wait "$pid" || ! (( code=$? )); }; then
        printf 'Got non-zero exit status (%d) from PID %d: %s\n' \
            "$code" "$pid" "${jobinfo[$pid]}"
        err=1
    fi
done

# exit 0 if all was good, exit 1 otherwise
exit "$err"

Here I collect all the necessary data before starting to wait for jobs to exit. I also wait for all jobs to finish so that the user gets information about not just the first failing job.


Without using associative arrays (should work in the default bash on macOS):

# collect job information
joblist=( $(jobs -p) )
for pid in "${joblist[@]}"; do
    jobinfo+=( "$( ps -p "$pid" -o args= )" )
done

# later...

err=0
i=0
for pid in "${joblist[@]}"; do
    if ! { wait "$pid" || ! (( code=$? )); }; then
        printf 'Got non-zero exit status (%d) from PID %d: %s\n' \
            "$code" "$pid" "${jobinfo[$i]}"
        err=1
    fi

    i=$(( i + 1 ))
done

exit "$err"
0

If your OS (e.g. Linux) has a /proc directory, you can get every needed information from /proc/$PID

for PID in $(jobs -p); do
    dosomethingwith /proc/$PID/ # please take a look at what it contents ;-)
    done

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.