Trap both INT and ERR, but callback got executed multiple times

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











up vote
3
down vote

favorite












I'm trapping both INT and ERR with the following code



set -ex -o pipefail

dest=$(mktemp -d)
cd "$dest"

trap "echo; echo Clean up; rm -rf $dest" INT ERR
sleep 9999


When I press ^C the clean up callback is executed multiple times



++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
++ echo

++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516


Is that expected behavior? Is it possible to execute it only once?







share|improve this question





















  • @sourcejedi I'm trying to clean up the temp folder either when error happens or user manually stops the script. Never know the EXIT, it does work better :-)
    – daisy
    May 3 at 23:44














up vote
3
down vote

favorite












I'm trapping both INT and ERR with the following code



set -ex -o pipefail

dest=$(mktemp -d)
cd "$dest"

trap "echo; echo Clean up; rm -rf $dest" INT ERR
sleep 9999


When I press ^C the clean up callback is executed multiple times



++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
++ echo

++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516


Is that expected behavior? Is it possible to execute it only once?







share|improve this question





















  • @sourcejedi I'm trying to clean up the temp folder either when error happens or user manually stops the script. Never know the EXIT, it does work better :-)
    – daisy
    May 3 at 23:44












up vote
3
down vote

favorite









up vote
3
down vote

favorite











I'm trapping both INT and ERR with the following code



set -ex -o pipefail

dest=$(mktemp -d)
cd "$dest"

trap "echo; echo Clean up; rm -rf $dest" INT ERR
sleep 9999


When I press ^C the clean up callback is executed multiple times



++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
++ echo

++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516


Is that expected behavior? Is it possible to execute it only once?







share|improve this question













I'm trapping both INT and ERR with the following code



set -ex -o pipefail

dest=$(mktemp -d)
cd "$dest"

trap "echo; echo Clean up; rm -rf $dest" INT ERR
sleep 9999


When I press ^C the clean up callback is executed multiple times



++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
++ echo

++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516


Is that expected behavior? Is it possible to execute it only once?









share|improve this question












share|improve this question




share|improve this question








edited May 3 at 15:47









Jeff Schaller

31.1k846105




31.1k846105









asked May 3 at 15:31









daisy

27.3k45157289




27.3k45157289











  • @sourcejedi I'm trying to clean up the temp folder either when error happens or user manually stops the script. Never know the EXIT, it does work better :-)
    – daisy
    May 3 at 23:44
















  • @sourcejedi I'm trying to clean up the temp folder either when error happens or user manually stops the script. Never know the EXIT, it does work better :-)
    – daisy
    May 3 at 23:44















@sourcejedi I'm trying to clean up the temp folder either when error happens or user manually stops the script. Never know the EXIT, it does work better :-)
– daisy
May 3 at 23:44




@sourcejedi I'm trying to clean up the temp folder either when error happens or user manually stops the script. Never know the EXIT, it does work better :-)
– daisy
May 3 at 23:44










2 Answers
2






active

oldest

votes

















up vote
3
down vote



accepted










You're getting both the INT and ERR signals; SIGINT is handed to sleep, who exits with a non-zero return code. The non-zero return code then triggers the trap for SIGERR.




If a sigspec is ERR, the command arg is executed whenever a pipeline (which may consist of a single simple command), a list, or a compound command returns a non-zero exit status...




An example, to see the separate traps:



set -ex -o pipefail
trap "echo Clean up for INT" INT
trap "echo Clean up for ERR" ERR
sleep 9999


Executing, then Control-C:



+ trap 'echo Clean up for INT' INT
+ trap 'echo Clean up for ERR' ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ echo Clean up for ERR
Clean up for ERR


As for calling the trap only once, one option would be to reset the ERR trap while inside the INT trap:



...
trap "echo Clean up for INT; trap ERR" INT ERR
...


... which results in:



+ trap 'echo Clean up for INT; trap ERR' INT ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ trap ERR





share|improve this answer




























    up vote
    1
    down vote













    In bash, you can simply replace this with trap "my-cleanup-command" EXIT. This trap will be run when the script exits, including if it is sent SIGINT. In my opinion this is usually the more elegant approach...



    Except for the fact that it is bash-specific. EXIT traps are mentioned in POSIX, but the behaviour is not specified. In many other shells, the EXIT trap is not run if the shell exits because of a signal.



    https://unix.stackexchange.com/a/57960/29483



    Sometimes I really hate shell scripting :).




    Looking at the linked answer, I think a less bash-specific way to ensure no code gets run after the first trap would be to exit immediately. It seems there's different ways you might want to do this, but here's the simplest one I would try.



    cleanup() 
    echo "Clean up"
    rm -rf "$dest"

    trap cleanup EXIT
    trap "exit 1" INT ERR





    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%2f441580%2ftrap-both-int-and-err-but-callback-got-executed-multiple-times%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
      3
      down vote



      accepted










      You're getting both the INT and ERR signals; SIGINT is handed to sleep, who exits with a non-zero return code. The non-zero return code then triggers the trap for SIGERR.




      If a sigspec is ERR, the command arg is executed whenever a pipeline (which may consist of a single simple command), a list, or a compound command returns a non-zero exit status...




      An example, to see the separate traps:



      set -ex -o pipefail
      trap "echo Clean up for INT" INT
      trap "echo Clean up for ERR" ERR
      sleep 9999


      Executing, then Control-C:



      + trap 'echo Clean up for INT' INT
      + trap 'echo Clean up for ERR' ERR
      + sleep 9999
      ^C++ echo Clean up for INT
      Clean up for INT
      ++ echo Clean up for ERR
      Clean up for ERR


      As for calling the trap only once, one option would be to reset the ERR trap while inside the INT trap:



      ...
      trap "echo Clean up for INT; trap ERR" INT ERR
      ...


      ... which results in:



      + trap 'echo Clean up for INT; trap ERR' INT ERR
      + sleep 9999
      ^C++ echo Clean up for INT
      Clean up for INT
      ++ trap ERR





      share|improve this answer

























        up vote
        3
        down vote



        accepted










        You're getting both the INT and ERR signals; SIGINT is handed to sleep, who exits with a non-zero return code. The non-zero return code then triggers the trap for SIGERR.




        If a sigspec is ERR, the command arg is executed whenever a pipeline (which may consist of a single simple command), a list, or a compound command returns a non-zero exit status...




        An example, to see the separate traps:



        set -ex -o pipefail
        trap "echo Clean up for INT" INT
        trap "echo Clean up for ERR" ERR
        sleep 9999


        Executing, then Control-C:



        + trap 'echo Clean up for INT' INT
        + trap 'echo Clean up for ERR' ERR
        + sleep 9999
        ^C++ echo Clean up for INT
        Clean up for INT
        ++ echo Clean up for ERR
        Clean up for ERR


        As for calling the trap only once, one option would be to reset the ERR trap while inside the INT trap:



        ...
        trap "echo Clean up for INT; trap ERR" INT ERR
        ...


        ... which results in:



        + trap 'echo Clean up for INT; trap ERR' INT ERR
        + sleep 9999
        ^C++ echo Clean up for INT
        Clean up for INT
        ++ trap ERR





        share|improve this answer























          up vote
          3
          down vote



          accepted







          up vote
          3
          down vote



          accepted






          You're getting both the INT and ERR signals; SIGINT is handed to sleep, who exits with a non-zero return code. The non-zero return code then triggers the trap for SIGERR.




          If a sigspec is ERR, the command arg is executed whenever a pipeline (which may consist of a single simple command), a list, or a compound command returns a non-zero exit status...




          An example, to see the separate traps:



          set -ex -o pipefail
          trap "echo Clean up for INT" INT
          trap "echo Clean up for ERR" ERR
          sleep 9999


          Executing, then Control-C:



          + trap 'echo Clean up for INT' INT
          + trap 'echo Clean up for ERR' ERR
          + sleep 9999
          ^C++ echo Clean up for INT
          Clean up for INT
          ++ echo Clean up for ERR
          Clean up for ERR


          As for calling the trap only once, one option would be to reset the ERR trap while inside the INT trap:



          ...
          trap "echo Clean up for INT; trap ERR" INT ERR
          ...


          ... which results in:



          + trap 'echo Clean up for INT; trap ERR' INT ERR
          + sleep 9999
          ^C++ echo Clean up for INT
          Clean up for INT
          ++ trap ERR





          share|improve this answer













          You're getting both the INT and ERR signals; SIGINT is handed to sleep, who exits with a non-zero return code. The non-zero return code then triggers the trap for SIGERR.




          If a sigspec is ERR, the command arg is executed whenever a pipeline (which may consist of a single simple command), a list, or a compound command returns a non-zero exit status...




          An example, to see the separate traps:



          set -ex -o pipefail
          trap "echo Clean up for INT" INT
          trap "echo Clean up for ERR" ERR
          sleep 9999


          Executing, then Control-C:



          + trap 'echo Clean up for INT' INT
          + trap 'echo Clean up for ERR' ERR
          + sleep 9999
          ^C++ echo Clean up for INT
          Clean up for INT
          ++ echo Clean up for ERR
          Clean up for ERR


          As for calling the trap only once, one option would be to reset the ERR trap while inside the INT trap:



          ...
          trap "echo Clean up for INT; trap ERR" INT ERR
          ...


          ... which results in:



          + trap 'echo Clean up for INT; trap ERR' INT ERR
          + sleep 9999
          ^C++ echo Clean up for INT
          Clean up for INT
          ++ trap ERR






          share|improve this answer













          share|improve this answer



          share|improve this answer











          answered May 3 at 16:31









          Jeff Schaller

          31.1k846105




          31.1k846105






















              up vote
              1
              down vote













              In bash, you can simply replace this with trap "my-cleanup-command" EXIT. This trap will be run when the script exits, including if it is sent SIGINT. In my opinion this is usually the more elegant approach...



              Except for the fact that it is bash-specific. EXIT traps are mentioned in POSIX, but the behaviour is not specified. In many other shells, the EXIT trap is not run if the shell exits because of a signal.



              https://unix.stackexchange.com/a/57960/29483



              Sometimes I really hate shell scripting :).




              Looking at the linked answer, I think a less bash-specific way to ensure no code gets run after the first trap would be to exit immediately. It seems there's different ways you might want to do this, but here's the simplest one I would try.



              cleanup() 
              echo "Clean up"
              rm -rf "$dest"

              trap cleanup EXIT
              trap "exit 1" INT ERR





              share|improve this answer



























                up vote
                1
                down vote













                In bash, you can simply replace this with trap "my-cleanup-command" EXIT. This trap will be run when the script exits, including if it is sent SIGINT. In my opinion this is usually the more elegant approach...



                Except for the fact that it is bash-specific. EXIT traps are mentioned in POSIX, but the behaviour is not specified. In many other shells, the EXIT trap is not run if the shell exits because of a signal.



                https://unix.stackexchange.com/a/57960/29483



                Sometimes I really hate shell scripting :).




                Looking at the linked answer, I think a less bash-specific way to ensure no code gets run after the first trap would be to exit immediately. It seems there's different ways you might want to do this, but here's the simplest one I would try.



                cleanup() 
                echo "Clean up"
                rm -rf "$dest"

                trap cleanup EXIT
                trap "exit 1" INT ERR





                share|improve this answer

























                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote









                  In bash, you can simply replace this with trap "my-cleanup-command" EXIT. This trap will be run when the script exits, including if it is sent SIGINT. In my opinion this is usually the more elegant approach...



                  Except for the fact that it is bash-specific. EXIT traps are mentioned in POSIX, but the behaviour is not specified. In many other shells, the EXIT trap is not run if the shell exits because of a signal.



                  https://unix.stackexchange.com/a/57960/29483



                  Sometimes I really hate shell scripting :).




                  Looking at the linked answer, I think a less bash-specific way to ensure no code gets run after the first trap would be to exit immediately. It seems there's different ways you might want to do this, but here's the simplest one I would try.



                  cleanup() 
                  echo "Clean up"
                  rm -rf "$dest"

                  trap cleanup EXIT
                  trap "exit 1" INT ERR





                  share|improve this answer















                  In bash, you can simply replace this with trap "my-cleanup-command" EXIT. This trap will be run when the script exits, including if it is sent SIGINT. In my opinion this is usually the more elegant approach...



                  Except for the fact that it is bash-specific. EXIT traps are mentioned in POSIX, but the behaviour is not specified. In many other shells, the EXIT trap is not run if the shell exits because of a signal.



                  https://unix.stackexchange.com/a/57960/29483



                  Sometimes I really hate shell scripting :).




                  Looking at the linked answer, I think a less bash-specific way to ensure no code gets run after the first trap would be to exit immediately. It seems there's different ways you might want to do this, but here's the simplest one I would try.



                  cleanup() 
                  echo "Clean up"
                  rm -rf "$dest"

                  trap cleanup EXIT
                  trap "exit 1" INT ERR






                  share|improve this answer















                  share|improve this answer



                  share|improve this answer








                  edited May 4 at 7:51


























                  answered May 4 at 7:40









                  sourcejedi

                  18.2k32475




                  18.2k32475






















                       

                      draft saved


                      draft discarded


























                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f441580%2ftrap-both-int-and-err-but-callback-got-executed-multiple-times%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Popular posts from this blog

                      How to check contact read email or not when send email to Individual?

                      Displaying single band from multi-band raster using QGIS

                      How many registers does an x86_64 CPU actually have?