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!

原文地址:https://www.cnblogs.com/weidagang2046/p/bash-trap.html

时间: 2024-10-09 09:43:28

The trap of Bash trap的相关文章

【转】shell脚本调试(bash trap support bashdb )

原文网址:http://zhu8337797.blog.163.com/blog/static/170617549201122512712136/ 命 令 选 项 功 能 bash –x 脚本名 回显 在变量替换之后.执行命令之前,显示脚本的每一行 bash –v 脚本名 详细 在执行之前,按输入的原样打印脚本中各行 bash –n 脚本名 不执行 解释但不执行命令 set –x 打开回显 跟踪脚本的执行 set +x 关闭回显 关闭跟踪功能 --------------------------

bash - trap

http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html The syntax for the trap statement is straightforward: trap [COMMANDS] [SIGNALS]

bash脚本编程(三)

写在前面: 博客书写牢记5W1H法则:What,Why,When,Where,Who,How. 本篇主要内容: ● case语句 ● function函数 ● 数组 ● bash内置字符串处理 ● glob模式匹配扩展 ● 脚本信号捕捉 ● bash中使用ASCII颜色 ● dialog实现窗口化编程 case语句 case $WORD in pattern1 [| pattern1_1] ... ) list1 ;; pattern2 [| pattern2_1] ... ) list2 ;;

马哥笔记第十六天故障排除、trap、sed、awk、bash数组、bash字符串操作

A.故障排除:             紧急救援模式:rescue,相当于一个小型的linux系统和让你切换到硬盘系统中. 1.grub损坏:                         谨慎操作 dd  if=/dev/zero of=/dev/sda count=1 bs=400   不能大于446,否则破坏分区表中数据.这时需要进入救援模式,选择Rescue installed system,选择语言.键盘设置.是否启用网络.继续continue.选择启动shell.使用chroot

Linux trap(捕捉) 命令

trap 命令用于指定在接收到信号后将要采取的行动: trap 命令的参数分为两部分,前一部分是接收到指定信号时将要采取的行动,后一部分是要处理的信号名.而且必须在你想保护的那部分代码以前指定trap命令. 格式:trap commands signal-list 例如:trap "cp -f /etc/resolv.conf.bak /etc/resolv.conf;exit"  INT .......................................... 信 号(S

正确使用‘trap指令’实现Docker优雅退出

一般应用(比如mariadb)都会有一个退出命令,用户使用类似systemctl stop ****.service方法,停止其服务时,systemd会调用其配置文件注册的退出命令,该命令执行清理资源.退出集群.输出必要日志等操作后才杀死自己的进程:在系统shutdown的时候也会有类似的流程,最大程度的保证应用正常退出,下面我们称之为"进程优雅退出". 将应用Docker化后,一个突出的问题是,如何让进程优雅的退出,而不是强行杀死进程.Docker stop和Docker kill分

shell Trap命令用法

[[email protected] prog]# cat trap2.sh #!/bin/bash function cleanup() { echo "Received signals and cleanup files" } #trap 到SIG信号,自动停止 trap 'cleanup;exit 1' SIGHUP trap 'cleanup;exit 1' SIGINT trap 'cleanup;exit 1' SIGTRAP #SIGKILL can not be tra

信号捕捉trap及其在shell中的用法

kll -l命令可以查看所有的信号 其中有几个最常用的信号值如下 tarp的用法(注意,使用的是单引号) 例如 #!/bin/bash trap 'echo "good"' 2 这里可以使用数字编号,也可使用信号名或简称 sleep 100 当上面这个脚本运行时,如果我们a 原文地址:https://blog.51cto.com/14240018/2432269

trap命令

重要的一些信号 1)SIGHUP本信号在用户终端连接结束时发出                    挂起,通常由终端掉线或用户退出而引发2)SIGINT程序终止信号,在用户键入Ctrl-C时发出                中断,通常因按下Ctrl+C而引发3)SIGQUIT和信号2类似,由Ctrl-/来控制,进程收到SIGQUIT会产生core文件    退出,通常因按下Ctrl+/而引发6)SIGABRT程序自己发现错误并调用abort时产生                中止,通常因某