zoukankan      html  css  js  c++  java
  • 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!

  • 相关阅读:
    windows Visual Studio 2017 编译 HEVC cmake-3.8.1-win64-x64.msi 下载
    DirectShow
    IDA反汇编学习
    .NET dnSpy 程序集编辑器,反编译器和调试器
    Win7如何自定义鼠标右键菜单 添加新建PowerPoint文档
    Win7如何自定义鼠标右键菜单 添加新建EXCEL文档
    推荐电视剧 大秦帝国之裂变 2008
    推荐电视剧 大明王朝1566 2007
    C#如何生成release版本的程序,生成debug版本的程序
    Solidworks安装完成提示failed to load slderresu.dll怎么办
  • 原文地址:https://www.cnblogs.com/weidagang2046/p/bash-trap.html
Copyright © 2011-2022 走看看