• The trap of Bash trap


    Can you spot the problem with the following Bash script?

    resource_created="false"
    
    function cleanup() {
      echo "Exit code: $?"
      if [[ $resource_created == "true" ]]; then
        echo "Clean up resource"
      else
        echo "Nothing to clean up"
      fi
    }
    
    function main() {
      resource_created="true"
      echo "Resource created"
      exit 1
    }
    
    trap cleanup EXIT
    
    main | tee /tmp/my.log
    

    The intent is that, we use global variable resource_created to track the state of the program, and register function cleanup as exit trap which prints the exit code and cleans up the resource if created. But it didn't work as expected, the actual output is:

    Resource created
    Exit code: 0
    Nothing to clean up
    

    Why? The catch is with the pipe |. When executing a pipe, each command of the pipe is in a separate process from the Bash process. The variable modified by main is lost. The exit code of main is also lost, because the exit code of a pipe is the exit code of the last command of the pipe. It becomes clear when we print the process IDs out. Watch out the difference between $$ and $BASHPID, we should use $BASHPID in this case.

    resource_created="false"
    
    function cleanup() {
      echo "Exit code: $?"
      if [[ $resource_created == "true" ]]; then
        echo "Clean up resource"
      else
        echo "Nothing to clean up"
      fi
      echo "cleanup() PID: $BASHPID"
    }
    
    function main() {
      echo "main() PID: $BASHPID"
      resource_created="true"
      echo "Resource created"
      exit 1
    }
    
    trap cleanup EXIT
    
    echo "Bash PID: $BASHPID"
    main | tee /tmp/my.log
    

    Output:

    Bash PID: 9852
    main() PID: 9853
    Resource created
    Exit code: 0
    Nothing to clean up
    cleanup() PID: 9852
    

    Then if global variable and exit code don't work, how do we untangle? File!

    function cleanup() {
      if [[ -f /tmp/resource_created ]]; then
        echo "Exit code: $(cat /tmp/resource_created)"
        echo "Clean up resource"
      else
        echo "Nothing to clean up"
      fi
    }
    
    function main() {
      echo "Resource created"
      echo 1 >/tmp/resource_created
      exit 1
    }
    
    trap cleanup EXIT
    
    main | tee /tmp/my.log
    

    Output:

    Resource created
    Exit code: 1
    Clean up resource
    

    Okay, it is almost the end of this short blog post. Bash programming is tricky, watch out for the traps. Thanks for reading and happy coding!

  • 相关阅读:
    C语言I作业12—学期总结
    # 第一周作业
    C语言Ⅰ博客作业11
    C语言Ⅰ博客作业10
    C语言Ⅰ博客作业09
    C语言Ⅰ博客作业08
    C语言||作业01
    C语言寒假大作战04
    C语言寒假大作战03
    C语言寒假大作战02
  • 原文地址:https://www.cnblogs.com/weidagang2046/p/bash-trap.html
Copyright © 2020-2023  润新知