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

时间:2015-12-08 17:42:53

标签: bash shell pipe signals pipeline

我有以下脚本无限期地监视a目录,如果该目录中有文件操作,则文件名由while循环读取,文件名中的第一个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 文件:

force-reload

这是实际脚本的简化版本。我还为上面的脚本提供了一个Sys-V类型的init脚本,因为我希望保持LSB兼容,我的init脚本有force-reload如果服务支持,则会重新加载配置。否则,服务重新启动。)选项,将HUP信号发送到脚本。现在,在执行执行killproc -HUP test.sh的{​​{1}}之前,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)
# 

根据stracekillproc已将SIGHUP发送到流程44244426,但只有后者才被终止。

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

1 个答案:

答案 0 :(得分:8)

管道命令在子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和以下链接:

信号处理

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

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

Bash手册页还说明了

  

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

后来说明了

  

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

这表示子shell不继承 not ignored 的信号处理程序。据我所知,你的trap ':' HUP行意味着(有效)忽略了SIGHUP信号(因为:内置函数除了返回成功之外什么都不做) - 而且应该被管道的子shell忽略。

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

  

如果arg是空字符串,则shell会忽略每个sigspec指定的信号及其调用的命令。

只需将trap命令更改为trap '' HUP即可确保忽略SIGHUP信号,以及脚本本身 - 以及任何子壳。