《UNIX编程环境》——5.4 trap:捕获中断

简介: 如果在运行watchwho时突然按下Delete键或挂断电话,在目录/tmp中,将保存一个或两个临时文件。Watchwho应该在退出之前清除这些暂存文件。我们需要一定的手段来检测各种中断事件,并进行恢复处理。

本节书摘来自异步社区《UNIX编程环境》一书中的第5章,第5.4节,作者:【美】Brian W. Kernighan , Rob Pike著,更多章节内容可以访问云栖社区“异步社区”公众号查看

5.4 trap:捕获中断

如果在运行watchwho时突然按下Delete键或挂断电话,在目录/tmp中,将保存一个或两个临时文件。Watchwho应该在退出之前清除这些暂存文件。我们需要一定的手段来检测各种中断事件,并进行恢复处理。

按Delete键时,一个中断信号会送给终端上正在运行的所有进程;同样地,当挂断电话时,会传送一个挂断信号。其他信号发生的情形亦同。除非程序有专门处理中断信号措施,否则,中断信号将一律终止程序的运行。如果是中断信号,后台运行的进程(使用&运行)能得到保护,但如果是挂断信号,则得不到保护。

第7章将详细讨论各种中断信号,但你无需知道太多细节就可以在shell中处理中断信号。shell的内部命令trap能生成中断信号发生时所要执行的命令序列:

screenshot

命令序列是一个单独的参数,一般要用引号括起来。信号值是小整数,用于标识中断信号。例如,2表示Delete键产生的信号,1表示电话挂断信号。shell程序使用的大多数通用信号值列在表5-4中。
screenshot

为了清除watchwho中的暂存文件,程序要在循环之前加上调用trap的语句,以捕获挂断信号、中断信号和终止信号:

screenshot

trap的第一个参数是一个命令序列,这个序列类似中断信号发生时立即调用的子程序。命令结束后,程序返回到断点继续执行,除非中断信号终止了它。因此,trap命令序列必须显式地调用exit,否则在中断之后将继续执行shell程序。实际上trap中的命令序列将被读取两次,一次是建立trap时,一次是trap被调用时。因此,命令序列最好用单引号来保护,这样变量仅在trap程序执行时才被赋值。在这个例子里没有关系,但在有的情况下,这种区别非常重要,后面我们将看到一个例子。另外,选择项-f表示rm不进行询问。

有时,trap程序在交互上很有用,最常用的情况是保护程序不会由于电话断线引起的挂断信号异常终止:

screenshot

空的命令序列意味着在进程及其子进程中“不响应中断”。括号的作用是使trap和命令一起在一个后台子shell中运行;如果没有括号,trap将同时作用到登录的shell和long-runing-command中的命令上。

命令nohup(1)是一个很短的shell程序,它能提供这种服务。下面是在第7版中nohup的实现:

screenshot

test-t测试标准输出是否为终端,以决定输出是否需要保存。带nice运行的后台进程的优先级比交互程序的优先级低。(注意:nohup没有设置PATH。是否应该 设置?)

使用exec主要是为了提高效率,没有exec,程序的运行也不会有问题。exec是一个shell命令,它用给定程序代替运行shell的进程,因此节省了一个shell进程,而一般这个shell需要等待程序运行结束。我们还可以在其他一些地方使用exce,例如,在增强的cal程序结尾处调用/usr/bin/cal时可以使用exec。

附带提一下,信号9是一个不能捕获也不能忽略,而且必须执行的信号;它总是要终止程序,在shell环境下,可用如下方法发出信号9:

screenshot

kill -9的选项不是默认设置,因为按这样的方式来终止进程,进程在结束之前没有任何机会处理善后工作。

练习5-14 上述nohup版本把命令的标准错误输出和标准输出结合在一起,这样设计好吗?如果不好,怎样将它们分开呢?

练习5-15 查阅shell内置函数times,在你的.profile文件里增加一行命令;当退出系统时打印出所使用的CPU时间。

练习5-16 写一个程序,使之能在/etc/passwd文件里下寻找一个可用的用户标识符。如果有兴趣(并有访问权力),将这个程序改写成一个命令,在系统里添加新用户。完成上述工作需要什么访问权限?应该如何处理中断?

相关文章
|
Unix 程序员 C语言
《UNIX编程环境》——导读
本书的目的是传播UNIX程序设计的基本原则,由于这个基本原则是以程序间的关系为基础的,因此我们必须用大量的篇幅专门对单个的工具进行讨论,但同时贯穿了程序组合的主题和运用程序进行创建程序的内容。
1728 0
|
Unix Shell C语言
《UNIX编程环境》——5.10 后记
shell是一种很好的编程语言,虽然它的语法有些特殊。shell属于高级语言,它的操作对象为整个程序。由于shell是交互式语言,所以shell程序能够交互式地开发,可以逐级求精直至它能够令人满意地工作。
1737 0
|
Unix Shell Perl
《UNIX编程环境》——5.9 get和put:追踪文件变动
程序在开发过程中不断地改正错误和增加新功能。版本追踪往往是不可少的。特别是有的用户把程序移植到其他的机器上使用—他们常常跑回来问“在我们的版本之后又有哪些改动”,或者“这个那个错误是怎么改的”。
1569 0
|
Unix Shell
《UNIX编程环境》——5.8 news命令:社团服务信息
我们在第1章提到您的系统可以有一个news命令,用以报告用户社团方面的信息。大部分系统都提供新闻服务,尽管命令名和命令细节有所不同。这里给出一个news命令,不是要代替原有的本地命令,而旨在说明在shell里编写这样一个程序是多么地容易。
1268 0
|
Unix Shell C语言
《UNIX编程环境》——5.7 pick命令:空格和参数
本节书摘来自异步社区《UNIX编程环境》一书中的第5章,第5.7节,作者:【美】Brian W. Kernighan , Rob Pike著,更多章节内容可以访问云栖社区“异步社区”公众号查看
1566 0
|
Unix Shell
《UNIX编程环境》——5.6 zap:使用名字终止进程
kill命令只能通过指定进程号来终止进程。要终止某个后台进程时,一般要运行ps命令以得到进程标识号,然后再把它作为kill的参数输入。通过一个命令程序打印一个参数,再把这个参数手工输入到另一个命令中,这个方法似乎有些笨拙。
1306 0
|
Unix Shell Perl
《UNIX编程环境》——5.3 while和until循环:观察情况
在第3章中,for循环用于一些简单的迭代程序。一般地,for对一组文件名进行循环,如在for i in .c中;或对shell程序的所有参数进行循环,如for i in $。但实际上,shell中的for循环可以有更大的用途,如在which里的for循环。
1897 0
|
Unix Shell Perl
《UNIX编程环境》——5.2 which
建立自己的命令版本,如cal命令的新版本,会带来一些其他的问题。最明显的例子是,如果Mary一起工作,并且以mary登录,则此时的cal还是标准的版本,除非Mary把新的cal命令连接到她的bin目录里。你可能会非常疑惑—原先的cal命令给出的错误信息不足以使人弄清发生错误的原因。
1890 0
|
Unix Shell
《UNIX编程环境》——第5章 shell程序设计 5.1 定制cal命令
和其他很多命令一样,shell程序的使用细节通常可以通过实践很快地掌握。shell手册常常不易于理解,而一个好的例子有时是将问题解释清楚的最好方法。鉴于这一原因,本章围绕着程序实例而不是围绕着shell的特性来组织,是shell编程指南,而不是shell所有功能的罗列。
1708 0
|
Unix 程序员 编译器
《UNIX编程环境》——1.5 UNIX系统的其余部分
UNIX系统中的内容远远多于本章中所讨论的内容,也远比本书的内容多。现在,你应可放心地使用系统,特别是要尽量使用手册。当对如何使用命令有疑问时,应查询手册。
1038 0