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!

  • 相关阅读:
    python 环境搭建
    马后炮之12306抢票工具(四)--抢票Demo,2014年1月9日终结版
    Office2013插件开发Outlook篇(2)-- Ribbon
    Office2013插件开发Outlook篇(1)-- 第一个office2013插件
    ExtJS4随笔(1) -- 在VS中加入Ext4的智能提示
    PHP中使用CURL请求页面,使用fiddler进行抓包
    微博公众平台(二)-- Token验证代码
    微博公众平台(一)-- 开发者接口配置信息
    cookie介绍
    jquery--工具插件
  • 原文地址:https://www.cnblogs.com/weidagang2046/p/bash-trap.html
Copyright © 2011-2022 走看看