免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12
最近访问板块 发新帖
楼主: homerzhou
打印 上一主题 下一主题

[系统管理] 关于这个shell为什么没有停止 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2015-10-30 00:18 |只看该作者
找到一篇文章讲解的不错:
https://  blog.robotshell.org/2012/necessary-details-about-signal-trap-in-shell

他也提到了楼主说的文档:
http://  mywiki.wooledge.org/SignalTrap

梳理下原因:

1、
Bash 等终端的默认行为是这样的:当按下 CTRL-C 之后,它会向当前的整个进程组发出 SIGINT 信号。而 sleep 是由当前脚本调用的,是这个脚本的子进程,默认是在同一个进程组的,所以也会收到 SIGINT 并停止执行


2、
这篇文档给了我们一个更准确的说明——如果当前正有一个外部命令在前台执行,那么 trap 会等待当前命令结束以后再处理信号队列中的信号。


3、
On most operating systems, ping is an example of a misbehaving process. It traps SIGINT in order to display a summary at the end, before exiting. But it fails to kill itself with SIGINT, and so the calling shell does not know that it should abort as well


这个问题挺有趣儿的,学习了。

论坛徽章:
0
12 [报告]
发表于 2015-10-30 10:54 |只看该作者
本帖最后由 homerzhou 于 2015-10-30 10:56 编辑

还是有一个小的疑惑,那篇文档中提到  “如果当前正有一个外部命令在前台执行,那么 trap 会等待当前命令结束以后再处理信号队列中的信号。”  ,不管怎么样./test.sh 还是会收到SIGINT的信号,即使需要等到ping结束之后,那为什么这个时候收到SIGINT信号就没有停止呢,
“But it fails to kill itself with SIGINT, and so the calling shell does not know that it should abort as well”
我是这么理解这句话的意思的,当按ctrl +c 时,如果子进程ping没有因为SIGINT信号退出,那么./test.sh不知道子进程ping是由于SIGINT退出的,它认为ping是正常退出的,这时./test.sh对SIGINT就会是默认不处理,不知道这么理解对不对,要是确实是这样的话,有链接可以共享吗?
回复 11# sncchen


   

论坛徽章:
84
每日论坛发贴之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00
13 [报告]
发表于 2015-10-30 15:05 |只看该作者
本帖最后由 yjh777 于 2015-10-30 15:07 编辑

我知道原因了,bash的 SIGINT 处理逻辑如下:
    判断是否还有活着的子进程,如果没有了就退出,如果还有就忽略;

ping的特殊性在于,它收到信号后,先做一些需要一定时间的操作 然后再退出
    如果这个退出在bash处理SIGINT之前,bash就不会退出。


下面是我写的一个用于测试的例子,三种情况:
    1) 如果把 sub.sh 里面那个usleep 时间设置的足够长,shell就永远不会退出
    2) 如果把 usleep 和 上面的echo去掉,快速按几次Ctr+C 就可以让shell退出,因为父子进程处理SIGINT的耗时相当
    3) 如果sub.sh不去trap SIGINT的话,系统默认的SIGINT处理是最快的,
          所以子进程总是在shell处理SIGINT时就死光了,所以shell就一次Ctr+C 就保证退出了
  1. jiyin@dhcp-12-137:~$ cat kkk.sh

  2. while :; do
  3.                 ./sub.sh
  4. done
  5. jiyin@dhcp-12-137:~$ cat sub.sh

  6. sigproc() {
  7.         echo "$@" >>sig.log
  8.         usleep 100000
  9.         exit
  10. }

  11. >sig.log
  12. trap sigproc SIGINT SIGTERM

  13. echo "I am a sub process of kkk.sh $"
  14. sleep 10
复制代码
@homerzhou

论坛徽章:
0
14 [报告]
发表于 2015-11-02 09:38 |只看该作者
有道理!回复 13# yjh777


   

论坛徽章:
0
15 [报告]
发表于 2015-11-02 18:18 |只看该作者

主要是因为bash 脚本作为父进程处于waitpid时,会检查子进程是如何退出的。 如果是调用exit退出的, 父进程不退出,bash 脚本继续运行。 如果是因为收到SIGINT信号后做默认处理退出的(也就是不捕获该信号),父进程退出,bash 脚本终止执行。

ping代码中捕获了SIGINT信号,并安装了信号处理函数, 该信号处理函数打印统计信息, 然后正常返回,ping随后也正常退出了。 bash发现子进程退出,但是不是因为SIGINT默认处理退出的,所以 父进程并不退出, 而是继续执行。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP