sh脚本和bash脚本_在脚本中使用Bash陷阱

sh脚本和bash脚本

很容易检测到shell脚本何时启动,但是并不总是容易知道何时停止。 脚本可能会正常终止,就像作者希望的那样终止,但是由于意外的致命错误,脚本也可能会失败。 有时,保留脚本失败时正在进行的所有操作的残余是有益的,而其他时候则很不方便。 无论哪种方式,检测脚本的结尾并以某种预先计算的方式对其做出React都是Bash trap指令存在的原因。

应对失败

这是脚本中的一个失败可能导致未来失败的示例。 假设您编写了一个程序,该程序在/tmp中创建了一个临时目录,以便它可以先取消归档和处理文件,然后再将它们以另一种格式捆绑在一起:


     
     
     
     
#!/usr/bin/env bash
CWD = ` pwd `
TMP = ${TMP:-/tmp/tmpdir}

## create tmp dir
mkdir " ${TMP} "

## extract files to tmp
tar xf " ${1} " --directory " ${TMP} "

## move to tmpdir and run commands
pushd " ${TMP} "
for IMG in * .jpg; do
  mogrify -verbose -flip -flop " ${IMG} "
done
tar --create --file " ${1%.*} " .tar * .jpg

## move back to origin
popd

## bundle with bzip2
bzip2 --compress " ${TMP} " / " ${1%.*} " .tar \
      --stdout > " ${1%.*} " .tbz

## clean up
/ usr / bin / rm -r / tmp / tmpdir

大多数情况下,脚本会按预期运行。 但是,如果您不小心在填充了PNG文件而不是预期的JPEG文件的存档上运行它,则该过程会中途失败。 一个失败导致另一个失败,最终,脚本退出而未达到删除临时目录的最终指令。 只要您手动删除目录,就可以快速恢复,但是如果您不打算这样做,那么下次运行脚本时,它必须处理一个充满了无法预测的剩余文件的现有临时目录。

解决此问题的一种方法是,通过在脚本开头添加预防性删除来反转和加倍逻辑。 虽然有效,但它依赖于蛮力而非结构。 trap是更优雅的解决方案。

用陷阱捕捉信号

trap关键字捕获执行期间可能发生的信号 如果您曾经使用过killkillall命令(默认情况下调用SIGTERM ,则您已使用这些信号之一。 Shell还会响应许多其他信号,您可以使用trap -l来查看其中的大多数信号(如“列表”中所示):


     
     
     
     
$ trap --list
  1 ) SIGHUP       2 ) SIGINT       3 ) SIGQUIT       4 ) SIGILL       5 ) SIGTRAP
  6 ) SIGABRT       7 ) SIGBUS       8 ) SIGFPE       9 ) SIGKILL     10 ) SIGUSR1
11 ) SIGSEGV     12 ) SIGUSR2     13 ) SIGPIPE     14 ) SIGALRM     15 ) SIGTERM
16 ) SIGSTKFLT   17 ) SIGCHLD     18 ) SIGCONT     19 ) SIGSTOP     20 ) SIGTSTP
21 ) SIGTTIN     22 ) SIGTTOU     23 ) SIGURG       24 ) SIGXCPU     25 ) SIGXFSZ
26 ) SIGVTALRM   27 ) SIGPROF     28 ) SIGWINCH     29 ) SIGIO       30 ) SIGPWR
31 ) SIGSYS       34 ) SIGRTMIN     35 ) SIGRTMIN+ 1   36 ) SIGRTMIN+ 2   37 ) SIGRTMIN+ 3
38 ) SIGRTMIN+ 4   39 ) SIGRTMIN+ 5   40 ) SIGRTMIN+ 6   41 ) SIGRTMIN+ 7   42 ) SIGRTMIN+ 8
43 ) SIGRTMIN+ 9   44 ) SIGRTMIN+ 10 45 ) SIGRTMIN+ 11 46 ) SIGRTMIN+ 12 47 ) SIGRTMIN+ 13
48 ) SIGRTMIN+ 14 49 ) SIGRTMIN+ 15 50 ) SIGRTMAX- 14 51 ) SIGRTMAX- 13 52 ) SIGRTMAX- 12
53 ) SIGRTMAX- 11 54 ) SIGRTMAX- 10 55 ) SIGRTMAX- 9   56 ) SIGRTMAX- 8   57 ) SIGRTMAX- 7
58 ) SIGRTMAX- 6   59 ) SIGRTMAX- 5   60 ) SIGRTMAX- 4   61 ) SIGRTMAX- 3   62 ) SIGRTMAX- 2
63 ) SIGRTMAX- 1   64 ) SIGRTMAX

使用trap可以预期这些信号中的任何一个。 除这些之外, trap识别:

  • EXIT :在shell进程本身退出时发生
  • ERR :当命令(例如tarmkdir )或内置命令(例如pushcd )以非零状态完成时发生
  • DEBUG :表示调试模式的布尔值

要在Bash中设置陷阱,请使用trap后跟要执行的命令列表,然后是触发它的信号列表。

例如,此陷阱检测到SIGINT ,即当用户在进程运行时按下Ctrl + C时发送的信号:

 trap "{ echo 'Terminated with Ctrl+C'; }" SIGINT 

带有临时目录问题的示例脚本可以通过检测SIGINT ,错误和成功退出的陷阱来修复:


     
     
     
     
#!/usr/bin/env bash
CWD = ` pwd `
TMP = ${TMP:-/tmp/tmpdir}

trap \
  "{ /usr/bin/rm -r " ${TMP} " ; exit 255; }" \
 SIGINT SIGTERM ERR EXIT

## create tmp dir
mkdir " ${TMP} "
tar xf " ${1} " --directory " ${TMP} "

## move to tmp and run commands
pushd " ${TMP} "
for IMG in * .jpg; do
  mogrify -verbose -flip -flop " ${IMG} "
done
tar --create --file " ${1%.*} " .tar * .jpg

## move back to origin
popd

## zip tar
bzip2 --compress $TMP / " ${1%.*} " .tar \
      --stdout > " ${1%.*} " .tbz
使用Bash函数 trap语句。

巴什的陷阱

陷阱对于确保脚本顺利结束(无论脚本是否成功运行)很有用。 完全依靠自动化垃圾收集永远是不安全的,因此一般来说,这是一个好习惯。 尝试在脚本中使用它们,看看它们能做什么!

翻译自: https://opensource.com/article/20/6/bash-trap

sh脚本和bash脚本

你可能感兴趣的:(sh脚本和bash脚本_在脚本中使用Bash陷阱)