免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3349 | 回复: 14
打印 上一主题 下一主题

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

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-10-27 17:36 |只看该作者 |倒序浏览
本帖最后由 homerzhou 于 2015-10-27 17:38 编辑

我有一个test.sh,内容如下:
  1. #!/bin/sh
  2. while true
  3. do
  4.     ping baidu.com
  5. done
复制代码
我运行./test.sh 然后使用 ctrl + c ,可是test.sh没有终止,ping终止了,由于循环,ping之后又运行了,在网上查到ping是捕捉SIGINT信号的

我理解 ctrl + c 是向前台进程组发送 SIGINT信号的,即使ping捕捉了SIGINT信号,test.sh 也应该能终止

如果把ping 改成 sleep ,就没有这个问题了,求高手请教

论坛徽章:
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
2 [报告]
发表于 2015-10-28 00:22 |只看该作者
按住 Ctr+C 不要松手

论坛徽章:
0
3 [报告]
发表于 2015-10-28 17:25 |只看该作者
其实我关心的不是用什么办法停下来,是为什么会出现这个情况 回复 2# yjh777


   

论坛徽章:
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
4 [报告]
发表于 2015-10-28 18:05 |只看该作者
我的理解是这样:因为你只安一次 Ctr+C 只发一个信号给前台进程,如果这是正好是ping占据前台执行, 就是ping收到信号停止,
但是循环语句没有停,因为循环耗时很少 所以碰到ping在执行的概率很大。
如果连续按多次,从ping停掉,到下一个ping产生之前,bash在前台 这时收到信号就会终止 当前循环语句

如果在 ping 后面插入一个其他语句比较容易发现差异:
while :; do
        ping localhost
        /usr/bin/sleep 1
done

BTW: 发现在一个单核的VBox虚拟机上,如果没有插入sleep 1,即使连续按Ctr+C 也无法使脚本停下来
物理机上测试行为都类似,连续按总能停下来

论坛徽章:
0
5 [报告]
发表于 2015-10-29 09:47 |只看该作者
你好,其实我产生这个以为是在看一篇文档的时候遇到的,由于我没有权限发送网址,所以我这边就截取那边的一段
  1. 5. Special Note On SIGINT

  2. If you choose to set up a handler for SIGINT (rather than using the EXIT trap), you should be aware that a process that exits in response to SIGINT should kill itself with SIGINT rather than simply exiting, to avoid causing problems for its caller. Thus:


  3. trap 'rm -f "$tempfile"; trap - INT; kill -INT $' INT
  4. We can see the difference between a properly behaving process and a misbehaving process. 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. For example,


  5. # Bash.  Linux ping syntax.
  6. for i in {1..254}; do
  7.   ping -c 2 192.168.1.$i
  8. done
  9. Here, if the user presses Ctrl-C during the loop, it will terminate the current ping command, but it will not terminate the loop. This is because Linux's ping command does not kill itself with SIGINT in order to communicate to the caller that the SIGINT was fatal. (Linux is not unique in this respect; I do not know of any operating system whose ping command exhibits the correct behavior.)

  10. A properly behaving process such as sleep does not have this problem:


  11. i=1
  12. while [ $i -le 100 ]; do
  13.   printf "%d " $i
  14.   i=$((i+1))
  15.   sleep 1
  16. done
  17. echo
  18. If we press Ctrl-C during this loop, sleep will receive the SIGINT and die from it (sleep does not catch SIGINT). The shell sees that the sleep died from SIGINT. In the case of an interactive shell, this terminates the loop. In the case of a script, the whole script will exit, unless the script itself traps SIGINT.
复制代码
回复 4# yjh777


   

论坛徽章:
0
6 [报告]
发表于 2015-10-29 10:11 |只看该作者
我觉得出现ctrl + c 无效,并不和ping是不是正在执行有关,而是和ping捕捉信号有关,因为如果把ping修改为sleep 2000,其实sleep也是一直在运行,可是这时只要按一次ctrl + c 就能停止test.sh运行,而且我觉得 ctrl + c 是发给前台进程组,不是单单一个前台进程的回复 4# yjh777


   

论坛徽章:
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
7 [报告]
发表于 2015-10-29 11:55 |只看该作者
homerzhou 发表于 2015-10-29 10:11
我觉得出现ctrl + c 无效,并不和ping是不是正在执行有关,而是和ping捕捉信号有关,因为如果把ping修改为sleep 2000,其实sleep也是一直在运行,可是这时只要按一次ctrl + c 就能停止test.sh运行,而且我觉得 ctrl + c 是发给前台进程组,不是单单一个前台进程的


嗯,也不是进程组,就是前台进程;但确实跟该进程是否处理 信号有关;

根据你粘贴的文档,应该是两种:
    1. 程序接收到 SIGINT 异常退出,这是他的父进程也会接收到相应子进程异常退出的信号,然后一起退出;比如 sleep
    2. 进程里面对 SIGINT 处理函数做了注册,收到信号后正常 exit,这是不影响父进程 循环继续执行

所以有的循环你一个 Ctr+C 就全到停掉了
而如果循环体有处理 SIGINT, 你就需要分别给 子进程和父进程 发信号,让他们都停下来

论坛徽章:
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
8 [报告]
发表于 2015-10-29 12:09 |只看该作者
不是很确定 如果说的不对,请纠正我,非常感谢!
    回去温习一下APUE~

论坛徽章:
0
9 [报告]
发表于 2015-10-29 16:33 |只看该作者
本帖最后由 homerzhou 于 2015-10-29 16:34 编辑

很开心能不厌其烦的回答我的问题
我重新找了一遍APUE关于 控制终端的那一节,里面有写到 ctrl + c 是发送给前台进程组中所有进程的,
关于你说的第一点,父进程接收到子进程异常退出 而退出,我觉得是不成立的,我觉得子进程异常退出如果没有人为的发送信号,那么默认的应该就是发送信号SIGCHLD,这个信号不会是导致父进程退出。而且在 那篇文档中讲到 正确的做法应该是
  1. trap 'rm -f "$tempfile"; trap - INT; kill -INT
复制代码
,我理解这个shell的意思是当捕捉到 SIGINT信号后,处理一下,接着把SIGINT的信号处理方式设置成默认,再给自己发送SIGINT信号,并没有给父进程发送SIGINT信号
我把 这篇文档网址(有一些空格)发给你 http : // mywiki. wooledge. org / SignalTrap 回复 8# yjh777



   

论坛徽章:
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
10 [报告]
发表于 2015-10-29 17:58 |只看该作者
嗯,我也找APUE看了一下,确实是发给进程组;而且看了一下不管是 ping 还是 sleep,两个脚本的进程组ID都是父进程shell的进程ID;
谢谢分享链接。

不过到底是什么原因导致用ping的时候,Ctr+C 无法停掉shell进程呢???
    这个从那个文档里还是没有看太明白,,有事先撤了,回头再研究研究;

@homerzhou
  如果有新的发现,请分享你的成果,谢谢啦
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP