• 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!

  • 相关阅读:
    灰度图转换
    OGRE分析之文件系统 (1)
    屏幕截图
    [GP]template必须定义于头文件中
    OGRE分析之设计模式
    ON_COMMAND_RANGE和ON_UPDATE_COMMAND_UI_RANGE
    使用SkinMagic Toolkit美化界面(II)
    Single Sign On for Windows and Linux
    "C compiler cannot create executables"
    How to Create a First C Program on Linux
  • 原文地址:https://www.cnblogs.com/weidagang2046/p/bash-trap.html
Copyright © 2020-2023  润新知