当前位置:  开发笔记 > 编程语言 > 正文

使用管道命令忽略Bash脚本中的HUP信号

如何解决《使用管道命令忽略Bash脚本中的HUP信号》经验,为你挑选了1个好方法。

我有以下脚本/tmp无限期地监视目录,如果该目录中有任何文件操作,则文件名由while循环读取,文件名中的第一个a字符替换为b字符,并将此修改后的文件名记录到test.log文件中:

#!/bin/bash

trap ':' HUP
trap 'kill $(jobs -p)' EXIT

/usr/local/bin/inotifywait -q -m /tmp --format %f | 
  while IFS= read -r filename; do
    echo "$filename" | sed 's/a/b/' > test.log
  done

这是实际脚本的简化版本.我上面的脚本也有一个Sys-V类型的init脚本,因为我希望保持LSB兼容,我的init脚本有force-reload(如果服务支持,则重新加载配置.否则,重新启动服务.)选项它将HUP信号发送到脚本.现在在执行之前执行force-reload,killproc -HUP test.sh输出pstree如下:

# pstree -Ap 4424
test.sh(4424)-+-inotifywait(4425)
              `-test.sh(4426)
# 

执行后strace killproc -HUP test.sh,子shell终止:

# pstree -Ap 4424
test.sh(4424)---inotifywait(4425)
# 

strace,killproc发送SIGHUP到过程44244426,但只有后者被终止.

4426在我的例子中,这个带有PID的子shell有什么意义,即为什么它首先被创建?另外,有没有办法忽略HUP信号?



1> Anthony G - ..:

管道命令在子shell中运行

问题的第一部分是通过shell(在本例中为Bash)在管道中运行命令的机制来解释的.

是FIFO(先入先出)单向的进程间通信(IPC)信道:它允许字节在一端(被写入只写端)和来自其他(读只读结束)无需读取或写入物理文件系统.

管道允许两个不同的命令来通过相互通信匿名无名(即,在文件系统中没有条目)管.

当shell执行简单命令时,该命令在shell的子进程中运行.如果没有使用作业控制,则当子进程终止时,shell将重新获得对终端的控制.

当在管道中运行两个命令时,管道中的两个命令都作为两个单独的子进程执行,这些子进程同时运行.

在Unix系统中,使用pipe(2)系统调用创建管道,系统调用创建一个新管道并返回一对文件描述符,其中一个引用读取端,另一个引用管道的写入端.

在GNU/Linux系统上使用Bash,clone(2)系统调用用于创建子进程.这允许子进程与其父进程共享文件描述符表,以便两个子子进程都继承匿名管道的文件描述符,以便可以读取它并且另一个可以写入它.

在您的情况下,该inotifywait命令获得4425的PID并通过将其连接stdout到写端的文件描述符来写入管道的只写端.

同时,管道命令的右侧获取PID,4426并且其stdin文件描述符设置为管道的只读端的文件描述符.由于管道右侧的子shell不是外部命令,因此表示子进程的名称与其父进程的名称相同test.sh.

有关详细信息,请参阅man 7 pipe以下链接:

匿名管道,维基百科文章

Unix Pipeline,Wikipedia文章

信号处理

我花了很长时间(实际上是几个小时的研究)来弄清楚为什么SIGHUP信号的陷阱没有被忽略.

我的所有研究表明,clone(2)系统调用创建的子进程也应该能够共享父进程的信号处理程序表.

Bash手册页也说明了这一点

命令替换,用括号分组的命令和异步命令在子shell环境中调用,该shell环境是shell环境的副本,除了shell捕获的陷阱被重置为shell在调用时从其父级继承的值.

它后来说明了这一点

进入shell时忽略的信号不能被捕获或重置.当创建一个被捕获的信号时,未被忽略的信号将在子shell或子shell环境中重置为其原始值.

这表明子shell不继承未被忽略的信号处理程序.正如我所理解的那样,你的trap ':' HUP行意味着(有效地)忽略了SIGHUP信号(因为:内置函数除了返回成功之外什么都不做) - 而且应该被管道的子shell忽略.

但是,我最终trap在Bash手册页中找到了内置的描述,它通过忽略定义了Bash的含义:

如果arg是空字符串,则shell将忽略每个sigspec指定的信号以及它调用的命令.

只需更改trap命令以trap '' HUP确保忽略SIGHUP信号,脚本本身 - 以及任何子shell.

推荐阅读
ifx0448363
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有