无论你的脚本是否成功运行,信号捕获(trap)都能让它平稳结束。

  • 来源:https://linux.cn/article-12715-1.html
  • 作者:Seth Kenlon
  • 译者:Hank Chow

(本文字数:3879,阅读时长大约:4 分钟)

无论你的脚本是否成功运行, 信号捕获(trap)都能让它平稳结束。

Shell 脚本的启动并不难被检测到,但 Shell 脚本的终止检测却并不容易,因为我们无法确定脚本会按照预期地正常结束,还是由于意外的错误导致失败。当脚本执行失败时,将正在处理的内容记录下来是非常有用的做法,但有时候这样做起来并不方便。而 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; domogrify -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 捕获信号

我们可以通过 trap 捕捉程序运行时的信号。如果你使用过 kill 或者 killall 命令,那你就已经使用过名为 SIGTERM 的信号了。除此以外,还可以执行 trap -ltrap --list 命令列出其它更多的信号:

$ trap --list1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP6) 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 识别的信号除了以上这些,还包括:

  • EXIT:进程退出时发出的信号
  • ERR:进程以非 0 状态码退出时发出的信号
  • DEBUG:表示调试模式的布尔值

如果要在 Bash 中实现信号捕获,只需要在 trap 后加上需要执行的命令,再加上需要捕获的信号列表就可以了。

例如,下面的这行语句可以捕获到在进程运行时用户按下 Ctrl + C 组合键发出的 SIGINT 信号:

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

因此,上文中脚本的缺陷可以通过使用 trap 捕获 SIGINTSIGTERM、进程错误退出、进程正常退出等信号,并正确处理临时目录的方式来修复:

#!/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; domogrify -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 语句。

Bash 中的信号捕获

信号捕获可以让脚本在无论是否成功执行所有任务的情况下都能够正确完成清理工作,能让你的脚本更加可靠,这是一个很好的习惯。尽管尝试把信号捕获加入到你的脚本里看看能够起到什么作用吧。


apscheduler 脚本执行失败_在脚本中使用 Bash 信号捕获 | Linux 中国相关推荐

  1. 创建模板_在 GNOME 中创建文档模板 | Linux 中国

    导读:制作模板可以让你更快地开始写作新的文档. 本文字数:1305,阅读时长大约:1分钟https://linux.cn/article-12699-1.html作者:Alan Formy-duval ...

  2. 中科大843信号与系统中国科学技术大学843信号与系统138,总分420+上岸经验帖

    中科大843信号与系统中国科学技术大学上岸经验帖 ​ 编辑切换为居中 添加图片注释,不超过 140 字(可选) ​ 数学:(多动手,多计算,多总结,打好基础) (1)3月中旬-6月底:(这段时间重点应 ...

  3. apscheduler 脚本执行失败_Bash编程入门-3:数学运算及脚本

    说明:本文是对Vamei知乎文章<快速学习Bash>(https://zhuanlan.zhihu.com/p/32692644)一文的学习笔记,根据个人理解调整了内容顺序,补充了一些注释 ...

  4. hive运行mysql脚本_用java代码调用shell脚本执行sqoop将hive表中数据导出到mysql

    1:创建shell脚本 1 touch sqoop_options.sh2 chmod 777 sqoop_options.sh 编辑文件  特地将执行map的个数设置为变量  测试 可以java代码 ...

  5. crontab自定义脚本执行失败,但是手动执行是成功的

    问题:自己写了个kubectl命令删除失败pods的脚本,然后crontab自动执行总是失败. 分析: [root@k8s-master-1 lyf]# which kubectl /usr/loca ...

  6. bash脚本切换管理员_开始为系统管理员使用Bash脚本

    bash脚本切换管理员 Bash外壳绝对不是唯一的外壳,但它是功能最强大的外壳之一. 对于需要开发严肃的应用程序的系统管理员来说,这是一种流行的选择,这些应用程序超出了要在系统上运行的简单命令列表的范 ...

  7. python try catch finally执行顺序_对python中的try、except、finally 执行顺序详解

    如下所示: def test1(): try: print('to do stuff') raise Exception('hehe') print('to return in try') retur ...

  8. python自动化测试脚本怎么写_自动化测试脚本一般用什么语言写

    1. 自动化测试脚本一般用什么语言写 我主要是做web测试的,最近也在研究自动化测试. 自动化测试主流的工具应该是QTP吧,这个你可以去51testing论坛搜到很多相关的资料.QTP是一个商业软件. ...

  9. 没有run窗口_使用 Terminator 在一个窗口中运行多个终端 | Linux 中国

    Terminator 为在单窗口中运行多个 GNOME 终端提供了一个选择,让你可以灵活地调整工作空间来适应你的需求.-- Sandra Henry-stocker Terminator 为在单窗口中 ...

最新文章

  1. linux下备份mysql上传到网盘_Linux命令行上传文件到百度网盘
  2. 使用JQuery Autocomplete插件(一)
  3. SAP UI5 应用开发教程之六十九 - 如何从 SAP UI5 Not Found 页面跳转回到正常的应用页面
  4. mysql batch mode_MySQL数据库增量日志解析工具 Canal 实战
  5. 直白介绍卷积神经网络(CNN)
  6. Lucene.Net 3.0.3如何从TokenStream中获取token对象
  7. springboot图书管理怎么实现借书时间到期提醒_东和店镇第一小学图书数字化管理先进做法...
  8. 银行考试计算机也需要考金融知识吗,银行招聘考试科技岗考试科目及考试内容...
  9. 移动硬盘安装win10
  10. c语言可编写的游戏,占卜子女兴盛大全篇
  11. 阿里云买的域名备案成功了 后续怎么建站 ?
  12. 192.168.1.0/24
  13. 万里长城第一里——实习之后台开发
  14. Pytorch中的detach用法
  15. winhex快捷键使用
  16. MySQL数据库学习笔记(一)—— 基础概念
  17. python录音pyaudio_用PyAudio录制特定时间的音频?
  18. 智能电动自行车充电远程管理系统
  19. h5 数字变化_基于JS实现数字动态变化显示效果附源码
  20. 【程序员的数学基础课-黄申】学习笔记 1-10

热门文章

  1. tensorflow切换到gpu_使用免费的GPU进行深度学习
  2. 作者:​林旺群(1983-),男,博士,北京系统工程研究所助理研究员。
  3. 【软件质量】变更管理与可追踪性
  4. 求第k小的数(洛谷P1923题题解,Java/C++语言描述)
  5. 【算法分析与设计】快速排序
  6. 数据获取之网络爬虫专栏简介
  7. unity快捷放置物体操作
  8. python出现的各种问题
  9. MySQL查询指定时间的数据
  10. Qt简单的解析Json数据例子(一)