1

in python3 i invoke a parent shell with subprocess.run:

output=subprocess.run(['parent.sh', *cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

then i check the returncode:

print("retcode =", output.returncode)
print("stdout =", output.stdout)
print("stderr =", output.stderr)

all good so far i catch the exitcode but what i am currently trying to catch are exitcodes from any sub/child shell scripts within the parent

the parent is generic and looks like this:

#!/usr/bin/env bash

set -ea

OUT="$("$@"; printf :%s "${PIPESTATUS[*]}")"

set +ea

so it will invoke any given .sh script and "should" return any exit codes even from nested child .sh scripts

so i tested by a nested level of 3:

parent.sh 
         -> child_1.sh
                      -> child_2.sh

i purposefully removed "child_2" so it would throw an error because it cant find it and while the stderr shows the error message "child_2.sh no such file or directory" the returncode of "output.returncode" is zero any suggestions how to catch all exitcodes? no matter how nested a parent shell is

5
  • how to catch all exitcodes? so exit with proper exit code of child from parents. What is PIPESTATUS doing there? There is no pipe. and "should" return any exit codes even from nested No, it will always exit with 0 - the exit status of last command set +ea will be 0. Your parent script is just invalid and ignores child exit status. I do not understand. Just remove your parent script, it is masking exit status and removing stdout, and just do subprocess.run(cmd) from the start. Commented May 10, 2023 at 10:37
  • catch are exitcodes from any sub/child shell scripts within the parent This is OS specific. On linux you can ptrace PTRACE_O_TRACEFORK the program and capture PTRACE_EVENT_EXIT. Note that your "parent.sh" is at least 3 processes - the $(..) is a subshell, which is a separate process. $(...) exits with 0 exit status, because printf exits with 0. Overall, that is a workaround - the proper solution is to use proper shell scripts that exit with nonzero on errors. Commented May 10, 2023 at 10:41
  • I believe, the person who wrote the parent.sh script is most probably not aware that set -e does not transfer to the subshell, and counted on early script termination in case "$@" exits with non-zero exit status. This does not happen, as set -e is not inherited in the subshell. Related mywiki.wooledge.org/BashFAQ/105 . However, I do not understand what is OUT= and printf and set -a doing there, serving no purpose. Commented May 10, 2023 at 10:49
  • @KamilCuk i tried your suggestion with subprocess.run([*cmd], stdout=subprocess.PIPE, stderr=subprocess.PIPE) but again the child .sh throws an error that it could not be found but the returncode is still 0 Commented May 10, 2023 at 11:59
  • MCVE - Then post child.sh. You can write a shell script like invalid_command; echo and shell will always exit with 0 exit code. Commented May 10, 2023 at 12:08

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.