Trap all commands in function

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
0
down vote

favorite












I'm working with a set of scripts with functions treated as readonly.
The functions are more than just a list of commands, for example, there can be loops and change directories and even calls to other functions:



func() 
cd folder/
run command1
mkdir folder2/ ; cd folder2/
run command2



For a moment, pretending that I could change the scripts, to show you what I want one might look like this:



func() 
cd folder/
string[0]="command1" ; run command1


So, for commands which can be piped, but not for cd or loops, I want to store a string, store the stdout (stderr), store the exit code, and run another command afterwards. However, I cannot add this in, it must be done in my script which is invoking the one with func().



To just get the post command call functionality alone, I've tried copying the function and running it from my script with a trap foo debug, but that doesn't seem to propagate into functions. I don't think literally copying line by line will work because the cd and loops can't really be isolated since they are control statements rather than subshell commands.



If the strings can just be a function of the commands themselves, that's still useful.







share|improve this question

















  • 1




    From the bash manual: "the DEBUG and RETURN traps are not inherited unless [...] the -o functrace option has been enabled with the set builtin, (in which case all functions inherit the DEBUG and RETURN traps)"
    – muru
    Apr 24 at 12:23











  • @muru I used functrace to come up with an answer.
    – Timothy Swan
    May 1 at 22:16














up vote
0
down vote

favorite












I'm working with a set of scripts with functions treated as readonly.
The functions are more than just a list of commands, for example, there can be loops and change directories and even calls to other functions:



func() 
cd folder/
run command1
mkdir folder2/ ; cd folder2/
run command2



For a moment, pretending that I could change the scripts, to show you what I want one might look like this:



func() 
cd folder/
string[0]="command1" ; run command1


So, for commands which can be piped, but not for cd or loops, I want to store a string, store the stdout (stderr), store the exit code, and run another command afterwards. However, I cannot add this in, it must be done in my script which is invoking the one with func().



To just get the post command call functionality alone, I've tried copying the function and running it from my script with a trap foo debug, but that doesn't seem to propagate into functions. I don't think literally copying line by line will work because the cd and loops can't really be isolated since they are control statements rather than subshell commands.



If the strings can just be a function of the commands themselves, that's still useful.







share|improve this question

















  • 1




    From the bash manual: "the DEBUG and RETURN traps are not inherited unless [...] the -o functrace option has been enabled with the set builtin, (in which case all functions inherit the DEBUG and RETURN traps)"
    – muru
    Apr 24 at 12:23











  • @muru I used functrace to come up with an answer.
    – Timothy Swan
    May 1 at 22:16












up vote
0
down vote

favorite









up vote
0
down vote

favorite











I'm working with a set of scripts with functions treated as readonly.
The functions are more than just a list of commands, for example, there can be loops and change directories and even calls to other functions:



func() 
cd folder/
run command1
mkdir folder2/ ; cd folder2/
run command2



For a moment, pretending that I could change the scripts, to show you what I want one might look like this:



func() 
cd folder/
string[0]="command1" ; run command1


So, for commands which can be piped, but not for cd or loops, I want to store a string, store the stdout (stderr), store the exit code, and run another command afterwards. However, I cannot add this in, it must be done in my script which is invoking the one with func().



To just get the post command call functionality alone, I've tried copying the function and running it from my script with a trap foo debug, but that doesn't seem to propagate into functions. I don't think literally copying line by line will work because the cd and loops can't really be isolated since they are control statements rather than subshell commands.



If the strings can just be a function of the commands themselves, that's still useful.







share|improve this question













I'm working with a set of scripts with functions treated as readonly.
The functions are more than just a list of commands, for example, there can be loops and change directories and even calls to other functions:



func() 
cd folder/
run command1
mkdir folder2/ ; cd folder2/
run command2



For a moment, pretending that I could change the scripts, to show you what I want one might look like this:



func() 
cd folder/
string[0]="command1" ; run command1


So, for commands which can be piped, but not for cd or loops, I want to store a string, store the stdout (stderr), store the exit code, and run another command afterwards. However, I cannot add this in, it must be done in my script which is invoking the one with func().



To just get the post command call functionality alone, I've tried copying the function and running it from my script with a trap foo debug, but that doesn't seem to propagate into functions. I don't think literally copying line by line will work because the cd and loops can't really be isolated since they are control statements rather than subshell commands.



If the strings can just be a function of the commands themselves, that's still useful.









share|improve this question












share|improve this question




share|improve this question








edited Apr 23 at 17:15
























asked Apr 20 at 22:31









Timothy Swan

816




816







  • 1




    From the bash manual: "the DEBUG and RETURN traps are not inherited unless [...] the -o functrace option has been enabled with the set builtin, (in which case all functions inherit the DEBUG and RETURN traps)"
    – muru
    Apr 24 at 12:23











  • @muru I used functrace to come up with an answer.
    – Timothy Swan
    May 1 at 22:16












  • 1




    From the bash manual: "the DEBUG and RETURN traps are not inherited unless [...] the -o functrace option has been enabled with the set builtin, (in which case all functions inherit the DEBUG and RETURN traps)"
    – muru
    Apr 24 at 12:23











  • @muru I used functrace to come up with an answer.
    – Timothy Swan
    May 1 at 22:16







1




1




From the bash manual: "the DEBUG and RETURN traps are not inherited unless [...] the -o functrace option has been enabled with the set builtin, (in which case all functions inherit the DEBUG and RETURN traps)"
– muru
Apr 24 at 12:23





From the bash manual: "the DEBUG and RETURN traps are not inherited unless [...] the -o functrace option has been enabled with the set builtin, (in which case all functions inherit the DEBUG and RETURN traps)"
– muru
Apr 24 at 12:23













@muru I used functrace to come up with an answer.
– Timothy Swan
May 1 at 22:16




@muru I used functrace to come up with an answer.
– Timothy Swan
May 1 at 22:16










2 Answers
2






active

oldest

votes

















up vote
1
down vote













If I'm reading your question correctly, you're looking for a way to:



  • Capture stdout and stderr independently from the outputs of a function call

  • Preserve the current working directory against any changes to it in the course of a function's execution

This can be done rather simply:



#!/bin/bash
stdout=/path/to/output.std
stderr=/path/to/output.err

somefunc()
: Do things


( somefunc arg1 arg2 ) >> $stdout 2>> $stderr


Running the function in a subshell will allow it to do whatever it needs to with respect to changing the working directory, and outputting to both stdout and stderr as normal. When the subshell exits, the working directory of the script is unchanged, and all of the stdout and stderr outputs are caught and redirected into your log files.



Adding a (global or otherwise) array in which to capture exit codes of commands is trivial:



declare -a exitcodes
( exit 0 )
exitcodes+=( $? )
( exit 2 )
exitcodes+=( $? )
( exit 0 )
exitcodes+=( $? )

echo $exitcodes[@]





share|improve this answer





















  • No, I'm not looking to preserve the working directory. That can be reset to whatever I want when I call the function after each command. I want to 1. store a string for each command. 2. store the output 3. store the exit code and 4. run a function afterwards. Because of number 4. I can reset the directory but obviously I prefer not to because otherwise the script can't be ran standalone. It seems like you didn't understand my question. If you truly did, then show an example of a script which can be ran both standalone and with the 4 attributes listed.
    – Timothy Swan
    Apr 23 at 13:12






  • 1




    Perhaps, then, you should outline this more clearly in your question rather than in a comment on an answer.
    – DopeGhoti
    Apr 23 at 15:33










  • No. In the question, it is clear, even with an example that 4 things need to occur: string[1]="command2" ; run command1 |& tee out1.log ; result[1]="$?" ; finished_command_number 1 Obviously running cd folder/ inside a pipe will not even syntactically work out well and won't do any good, so it's fundamentally different than running a command which does syntactically work out in that situation and does perform its function inside of a pipe.
    – Timothy Swan
    Apr 23 at 17:04

















up vote
1
down vote



accepted










#!/bin/bash
# test.sh
post()
echo "post [$BASH_COMMAND] [$?]"
echo "== $RANDOM =="

set -o functrace
trap post debug
func() & tee out.txt

func


The output can be filtered by the lines marked with random. I should test this further to see how well it works with multiple processes, but it seems to work just fine with short lived commands. Notice the exit code lags by one command since debug is apparently called first.



#!/bin/bash
# check.sh
tryme()
echo "one"
echo "two"
mkdir -p hello
cd hello/
echo "three"
false
echo "four"



===



$ bash test.sh 
post [func] [0]
== 22542 ==
post [func] [0]
== 10758 ==
post [. check.sh] [0]
== 9115 ==
post [tryme 2>&1] [0]
== 11979 ==
post [tee out.txt] [0]
== 17814 ==
post [tryme 2>&1] [0]
== 22838 ==
post [echo "one"] [0]
== 5251 ==
one
post [echo "two"] [0]
== 18036 ==
two
post [mkdir -p hello] [0]
== 4247 ==
post [cd hello/] [0]
== 21611 ==
post [echo "three"] [0]
== 24685 ==
three
post [false] [0]
== 8557 ==
post [echo "four"] [1]
== 7565 ==
four





share|improve this answer





















    Your Answer







    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "106"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f439035%2ftrap-all-commands-in-function%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote













    If I'm reading your question correctly, you're looking for a way to:



    • Capture stdout and stderr independently from the outputs of a function call

    • Preserve the current working directory against any changes to it in the course of a function's execution

    This can be done rather simply:



    #!/bin/bash
    stdout=/path/to/output.std
    stderr=/path/to/output.err

    somefunc()
    : Do things


    ( somefunc arg1 arg2 ) >> $stdout 2>> $stderr


    Running the function in a subshell will allow it to do whatever it needs to with respect to changing the working directory, and outputting to both stdout and stderr as normal. When the subshell exits, the working directory of the script is unchanged, and all of the stdout and stderr outputs are caught and redirected into your log files.



    Adding a (global or otherwise) array in which to capture exit codes of commands is trivial:



    declare -a exitcodes
    ( exit 0 )
    exitcodes+=( $? )
    ( exit 2 )
    exitcodes+=( $? )
    ( exit 0 )
    exitcodes+=( $? )

    echo $exitcodes[@]





    share|improve this answer





















    • No, I'm not looking to preserve the working directory. That can be reset to whatever I want when I call the function after each command. I want to 1. store a string for each command. 2. store the output 3. store the exit code and 4. run a function afterwards. Because of number 4. I can reset the directory but obviously I prefer not to because otherwise the script can't be ran standalone. It seems like you didn't understand my question. If you truly did, then show an example of a script which can be ran both standalone and with the 4 attributes listed.
      – Timothy Swan
      Apr 23 at 13:12






    • 1




      Perhaps, then, you should outline this more clearly in your question rather than in a comment on an answer.
      – DopeGhoti
      Apr 23 at 15:33










    • No. In the question, it is clear, even with an example that 4 things need to occur: string[1]="command2" ; run command1 |& tee out1.log ; result[1]="$?" ; finished_command_number 1 Obviously running cd folder/ inside a pipe will not even syntactically work out well and won't do any good, so it's fundamentally different than running a command which does syntactically work out in that situation and does perform its function inside of a pipe.
      – Timothy Swan
      Apr 23 at 17:04














    up vote
    1
    down vote













    If I'm reading your question correctly, you're looking for a way to:



    • Capture stdout and stderr independently from the outputs of a function call

    • Preserve the current working directory against any changes to it in the course of a function's execution

    This can be done rather simply:



    #!/bin/bash
    stdout=/path/to/output.std
    stderr=/path/to/output.err

    somefunc()
    : Do things


    ( somefunc arg1 arg2 ) >> $stdout 2>> $stderr


    Running the function in a subshell will allow it to do whatever it needs to with respect to changing the working directory, and outputting to both stdout and stderr as normal. When the subshell exits, the working directory of the script is unchanged, and all of the stdout and stderr outputs are caught and redirected into your log files.



    Adding a (global or otherwise) array in which to capture exit codes of commands is trivial:



    declare -a exitcodes
    ( exit 0 )
    exitcodes+=( $? )
    ( exit 2 )
    exitcodes+=( $? )
    ( exit 0 )
    exitcodes+=( $? )

    echo $exitcodes[@]





    share|improve this answer





















    • No, I'm not looking to preserve the working directory. That can be reset to whatever I want when I call the function after each command. I want to 1. store a string for each command. 2. store the output 3. store the exit code and 4. run a function afterwards. Because of number 4. I can reset the directory but obviously I prefer not to because otherwise the script can't be ran standalone. It seems like you didn't understand my question. If you truly did, then show an example of a script which can be ran both standalone and with the 4 attributes listed.
      – Timothy Swan
      Apr 23 at 13:12






    • 1




      Perhaps, then, you should outline this more clearly in your question rather than in a comment on an answer.
      – DopeGhoti
      Apr 23 at 15:33










    • No. In the question, it is clear, even with an example that 4 things need to occur: string[1]="command2" ; run command1 |& tee out1.log ; result[1]="$?" ; finished_command_number 1 Obviously running cd folder/ inside a pipe will not even syntactically work out well and won't do any good, so it's fundamentally different than running a command which does syntactically work out in that situation and does perform its function inside of a pipe.
      – Timothy Swan
      Apr 23 at 17:04












    up vote
    1
    down vote










    up vote
    1
    down vote









    If I'm reading your question correctly, you're looking for a way to:



    • Capture stdout and stderr independently from the outputs of a function call

    • Preserve the current working directory against any changes to it in the course of a function's execution

    This can be done rather simply:



    #!/bin/bash
    stdout=/path/to/output.std
    stderr=/path/to/output.err

    somefunc()
    : Do things


    ( somefunc arg1 arg2 ) >> $stdout 2>> $stderr


    Running the function in a subshell will allow it to do whatever it needs to with respect to changing the working directory, and outputting to both stdout and stderr as normal. When the subshell exits, the working directory of the script is unchanged, and all of the stdout and stderr outputs are caught and redirected into your log files.



    Adding a (global or otherwise) array in which to capture exit codes of commands is trivial:



    declare -a exitcodes
    ( exit 0 )
    exitcodes+=( $? )
    ( exit 2 )
    exitcodes+=( $? )
    ( exit 0 )
    exitcodes+=( $? )

    echo $exitcodes[@]





    share|improve this answer













    If I'm reading your question correctly, you're looking for a way to:



    • Capture stdout and stderr independently from the outputs of a function call

    • Preserve the current working directory against any changes to it in the course of a function's execution

    This can be done rather simply:



    #!/bin/bash
    stdout=/path/to/output.std
    stderr=/path/to/output.err

    somefunc()
    : Do things


    ( somefunc arg1 arg2 ) >> $stdout 2>> $stderr


    Running the function in a subshell will allow it to do whatever it needs to with respect to changing the working directory, and outputting to both stdout and stderr as normal. When the subshell exits, the working directory of the script is unchanged, and all of the stdout and stderr outputs are caught and redirected into your log files.



    Adding a (global or otherwise) array in which to capture exit codes of commands is trivial:



    declare -a exitcodes
    ( exit 0 )
    exitcodes+=( $? )
    ( exit 2 )
    exitcodes+=( $? )
    ( exit 0 )
    exitcodes+=( $? )

    echo $exitcodes[@]






    share|improve this answer













    share|improve this answer



    share|improve this answer











    answered Apr 20 at 22:50









    DopeGhoti

    40k54779




    40k54779











    • No, I'm not looking to preserve the working directory. That can be reset to whatever I want when I call the function after each command. I want to 1. store a string for each command. 2. store the output 3. store the exit code and 4. run a function afterwards. Because of number 4. I can reset the directory but obviously I prefer not to because otherwise the script can't be ran standalone. It seems like you didn't understand my question. If you truly did, then show an example of a script which can be ran both standalone and with the 4 attributes listed.
      – Timothy Swan
      Apr 23 at 13:12






    • 1




      Perhaps, then, you should outline this more clearly in your question rather than in a comment on an answer.
      – DopeGhoti
      Apr 23 at 15:33










    • No. In the question, it is clear, even with an example that 4 things need to occur: string[1]="command2" ; run command1 |& tee out1.log ; result[1]="$?" ; finished_command_number 1 Obviously running cd folder/ inside a pipe will not even syntactically work out well and won't do any good, so it's fundamentally different than running a command which does syntactically work out in that situation and does perform its function inside of a pipe.
      – Timothy Swan
      Apr 23 at 17:04
















    • No, I'm not looking to preserve the working directory. That can be reset to whatever I want when I call the function after each command. I want to 1. store a string for each command. 2. store the output 3. store the exit code and 4. run a function afterwards. Because of number 4. I can reset the directory but obviously I prefer not to because otherwise the script can't be ran standalone. It seems like you didn't understand my question. If you truly did, then show an example of a script which can be ran both standalone and with the 4 attributes listed.
      – Timothy Swan
      Apr 23 at 13:12






    • 1




      Perhaps, then, you should outline this more clearly in your question rather than in a comment on an answer.
      – DopeGhoti
      Apr 23 at 15:33










    • No. In the question, it is clear, even with an example that 4 things need to occur: string[1]="command2" ; run command1 |& tee out1.log ; result[1]="$?" ; finished_command_number 1 Obviously running cd folder/ inside a pipe will not even syntactically work out well and won't do any good, so it's fundamentally different than running a command which does syntactically work out in that situation and does perform its function inside of a pipe.
      – Timothy Swan
      Apr 23 at 17:04















    No, I'm not looking to preserve the working directory. That can be reset to whatever I want when I call the function after each command. I want to 1. store a string for each command. 2. store the output 3. store the exit code and 4. run a function afterwards. Because of number 4. I can reset the directory but obviously I prefer not to because otherwise the script can't be ran standalone. It seems like you didn't understand my question. If you truly did, then show an example of a script which can be ran both standalone and with the 4 attributes listed.
    – Timothy Swan
    Apr 23 at 13:12




    No, I'm not looking to preserve the working directory. That can be reset to whatever I want when I call the function after each command. I want to 1. store a string for each command. 2. store the output 3. store the exit code and 4. run a function afterwards. Because of number 4. I can reset the directory but obviously I prefer not to because otherwise the script can't be ran standalone. It seems like you didn't understand my question. If you truly did, then show an example of a script which can be ran both standalone and with the 4 attributes listed.
    – Timothy Swan
    Apr 23 at 13:12




    1




    1




    Perhaps, then, you should outline this more clearly in your question rather than in a comment on an answer.
    – DopeGhoti
    Apr 23 at 15:33




    Perhaps, then, you should outline this more clearly in your question rather than in a comment on an answer.
    – DopeGhoti
    Apr 23 at 15:33












    No. In the question, it is clear, even with an example that 4 things need to occur: string[1]="command2" ; run command1 |& tee out1.log ; result[1]="$?" ; finished_command_number 1 Obviously running cd folder/ inside a pipe will not even syntactically work out well and won't do any good, so it's fundamentally different than running a command which does syntactically work out in that situation and does perform its function inside of a pipe.
    – Timothy Swan
    Apr 23 at 17:04




    No. In the question, it is clear, even with an example that 4 things need to occur: string[1]="command2" ; run command1 |& tee out1.log ; result[1]="$?" ; finished_command_number 1 Obviously running cd folder/ inside a pipe will not even syntactically work out well and won't do any good, so it's fundamentally different than running a command which does syntactically work out in that situation and does perform its function inside of a pipe.
    – Timothy Swan
    Apr 23 at 17:04












    up vote
    1
    down vote



    accepted










    #!/bin/bash
    # test.sh
    post()
    echo "post [$BASH_COMMAND] [$?]"
    echo "== $RANDOM =="

    set -o functrace
    trap post debug
    func() & tee out.txt

    func


    The output can be filtered by the lines marked with random. I should test this further to see how well it works with multiple processes, but it seems to work just fine with short lived commands. Notice the exit code lags by one command since debug is apparently called first.



    #!/bin/bash
    # check.sh
    tryme()
    echo "one"
    echo "two"
    mkdir -p hello
    cd hello/
    echo "three"
    false
    echo "four"



    ===



    $ bash test.sh 
    post [func] [0]
    == 22542 ==
    post [func] [0]
    == 10758 ==
    post [. check.sh] [0]
    == 9115 ==
    post [tryme 2>&1] [0]
    == 11979 ==
    post [tee out.txt] [0]
    == 17814 ==
    post [tryme 2>&1] [0]
    == 22838 ==
    post [echo "one"] [0]
    == 5251 ==
    one
    post [echo "two"] [0]
    == 18036 ==
    two
    post [mkdir -p hello] [0]
    == 4247 ==
    post [cd hello/] [0]
    == 21611 ==
    post [echo "three"] [0]
    == 24685 ==
    three
    post [false] [0]
    == 8557 ==
    post [echo "four"] [1]
    == 7565 ==
    four





    share|improve this answer

























      up vote
      1
      down vote



      accepted










      #!/bin/bash
      # test.sh
      post()
      echo "post [$BASH_COMMAND] [$?]"
      echo "== $RANDOM =="

      set -o functrace
      trap post debug
      func() & tee out.txt

      func


      The output can be filtered by the lines marked with random. I should test this further to see how well it works with multiple processes, but it seems to work just fine with short lived commands. Notice the exit code lags by one command since debug is apparently called first.



      #!/bin/bash
      # check.sh
      tryme()
      echo "one"
      echo "two"
      mkdir -p hello
      cd hello/
      echo "three"
      false
      echo "four"



      ===



      $ bash test.sh 
      post [func] [0]
      == 22542 ==
      post [func] [0]
      == 10758 ==
      post [. check.sh] [0]
      == 9115 ==
      post [tryme 2>&1] [0]
      == 11979 ==
      post [tee out.txt] [0]
      == 17814 ==
      post [tryme 2>&1] [0]
      == 22838 ==
      post [echo "one"] [0]
      == 5251 ==
      one
      post [echo "two"] [0]
      == 18036 ==
      two
      post [mkdir -p hello] [0]
      == 4247 ==
      post [cd hello/] [0]
      == 21611 ==
      post [echo "three"] [0]
      == 24685 ==
      three
      post [false] [0]
      == 8557 ==
      post [echo "four"] [1]
      == 7565 ==
      four





      share|improve this answer























        up vote
        1
        down vote



        accepted







        up vote
        1
        down vote



        accepted






        #!/bin/bash
        # test.sh
        post()
        echo "post [$BASH_COMMAND] [$?]"
        echo "== $RANDOM =="

        set -o functrace
        trap post debug
        func() & tee out.txt

        func


        The output can be filtered by the lines marked with random. I should test this further to see how well it works with multiple processes, but it seems to work just fine with short lived commands. Notice the exit code lags by one command since debug is apparently called first.



        #!/bin/bash
        # check.sh
        tryme()
        echo "one"
        echo "two"
        mkdir -p hello
        cd hello/
        echo "three"
        false
        echo "four"



        ===



        $ bash test.sh 
        post [func] [0]
        == 22542 ==
        post [func] [0]
        == 10758 ==
        post [. check.sh] [0]
        == 9115 ==
        post [tryme 2>&1] [0]
        == 11979 ==
        post [tee out.txt] [0]
        == 17814 ==
        post [tryme 2>&1] [0]
        == 22838 ==
        post [echo "one"] [0]
        == 5251 ==
        one
        post [echo "two"] [0]
        == 18036 ==
        two
        post [mkdir -p hello] [0]
        == 4247 ==
        post [cd hello/] [0]
        == 21611 ==
        post [echo "three"] [0]
        == 24685 ==
        three
        post [false] [0]
        == 8557 ==
        post [echo "four"] [1]
        == 7565 ==
        four





        share|improve this answer













        #!/bin/bash
        # test.sh
        post()
        echo "post [$BASH_COMMAND] [$?]"
        echo "== $RANDOM =="

        set -o functrace
        trap post debug
        func() & tee out.txt

        func


        The output can be filtered by the lines marked with random. I should test this further to see how well it works with multiple processes, but it seems to work just fine with short lived commands. Notice the exit code lags by one command since debug is apparently called first.



        #!/bin/bash
        # check.sh
        tryme()
        echo "one"
        echo "two"
        mkdir -p hello
        cd hello/
        echo "three"
        false
        echo "four"



        ===



        $ bash test.sh 
        post [func] [0]
        == 22542 ==
        post [func] [0]
        == 10758 ==
        post [. check.sh] [0]
        == 9115 ==
        post [tryme 2>&1] [0]
        == 11979 ==
        post [tee out.txt] [0]
        == 17814 ==
        post [tryme 2>&1] [0]
        == 22838 ==
        post [echo "one"] [0]
        == 5251 ==
        one
        post [echo "two"] [0]
        == 18036 ==
        two
        post [mkdir -p hello] [0]
        == 4247 ==
        post [cd hello/] [0]
        == 21611 ==
        post [echo "three"] [0]
        == 24685 ==
        three
        post [false] [0]
        == 8557 ==
        post [echo "four"] [1]
        == 7565 ==
        four






        share|improve this answer













        share|improve this answer



        share|improve this answer











        answered May 1 at 22:15









        Timothy Swan

        816




        816






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f439035%2ftrap-all-commands-in-function%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Peggy Mitchell

            Palaiologos

            The Forum (Inglewood, California)