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!

  • 相关阅读:
    WinForm 无边框窗体 拖动工作区移动窗体
    [CSS]火狐和IE对css样式解释的差异
    md类型文件迁移至Notion(img资源也可以上传)
    google推出notebook软件
    刚收到几个google analytics 邀请,有真正需要的我可以送给他一个
    最近用drupal做了一个CMS网站
    google adsense 又增加了Picasa的推介,我已加上
    googlepages空间的一个bug
    近段时间比较郁闷
    开复与学生面对面
  • 原文地址:https://www.cnblogs.com/weidagang2046/p/bash-trap.html
Copyright © 2011-2022 走看看