在bash
中,我不清楚哪些陷阱是继承的。该联机帮助页说:
当要执行除内置函数或shell函数之外的简单命令时,它将在单独的执行环境中调用[...] [T]将shell捕获的raps重置为从shell的父级继承的值,忽略shell忽略的陷阱[。]
后来它说子弹的行为方式相同。
我觉得这对我来说足够了。这听起来好像是一个shell 取消一个陷阱,它会被任何子shell和诸如此类的东西所记住,而如果一个shell 设置一个陷阱,那就会被遗忘。我不明白为什么会做出这样的设计选择,但我至少认为我理解发生了什么。
但是内置函数或shell函数的命令呢?并且两者的表现有所不同(关于陷阱继承)?我在手册中找不到全面的描述 - 据我所知,任何事情都有。看起来它们通常继承自父级,但是有ERR
和RETURN
等异常,当使用某些shell选项时,每个异常都只由函数继承
我的问题是:
陷阱继承对内置函数和函数的典型方式究竟是什么?例如,关于设置与未设置陷阱有什么微妙之处,大多数命令似乎都有这种方式吗?
所有函数和内置函数的行为方式是否相同? (请不要告诉我每个内置版都有一套单独的规则......)
有什么例外?即,默认情况下哪些信号表现不同,哪些函数可以通过shell选项更改其默认行为?我知道ERR
和RETURN
,但还有其他人吗?尽我所能,我找不到一个很好的简单列表。
如果有的话,函数或内置函数是否会影响父级的陷阱? trap - SIGSPEC
与trap '' SIGSPEC
如何发挥作用?
谢谢!
PS:我使用的是GNU bash版本“4.4.19(1)-release”。
答案 0 :(得分:2)
原始帖子包含多个问题。尝试解决最后一个问题:When, if ever, can a function or builtin affect the traps of a parent? How does trap - SIGSPEC vs. trap '' SIGSPEC play into this?
(2个问题)
函数何时可以影响父级的陷阱?
简短的回答:只有在与父调用方相同的进程中运行的功能才能影响调用方。
长答案:请务必注意信号特定于“执行环境”。在linux / Unix中,这是一个过程。继承发生在进程之间。因此,一个函数只有在同一进程中执行时才能影响“父”(调用者)。如果在其他过程中执行,将不会影响“父级”。使用子shell的示例包括:何时强制使用子shell(使用“(命令)”),何时使用管道(管道的最后一条命令除外),何时使用命令替换等等。
function f {
trap 'echo SIGNAL' TERM
}
# Will impact current process traps, as 'f' is executed in the same process
f
# Will not impact current process traps, as 'f' is executed in a sub-shell.
(f)
“陷阱-SIG”和“陷阱“”信号”之间的区别:
简短答案:“-”将恢复信号行为,“”将忽略它。对于大多数信号,默认行为是终止外壳。
长答案:使用'trap-SIG'将信号重置为默认行为,而'trap“” SIG'将强制忽略该信号。
对于(很少)信号,默认(初始)行为将被忽略(例如QUIT),因此,命令之间没有区别。对于大多数其他信号(例如QUIT),默认行为是忽略该信号。您可以使用'trap“” SIG来防止信号在特定时间点受到影响。
例如:在复制关键文件时禁止ctrl / C(INTR):
sleep 5
# Disable INT during copying of critical files
trap '' INT
cp -r critical-file backup
# Restore INT behavior
trap -- INT
由于信号被继承,因此可以修改信号的“默认”行为。考虑:
# Get greeting on USR1
trap 'echo HI' USR1
# Start sub-shell
(
# USR1 will result in 'HI'
sleep 5
trap '' USR1
# USR1 will be ignored during critical file copy
cp -r critical-file backup
# Restore INT behavior
trap - INT
# USR1 will result in 'HI'
sleep 5
)
答案 1 :(得分:0)
尝试解决:
陷阱继承对内置函数和函数的典型工作方式到底是什么?例如,关于设置和取消设置陷阱是否有任何微妙之处,大多数命令似乎都是这样?
如上所述,函数和内置函数不继承陷阱。继承作用于进程边界(子外壳,管道,命令替换等)。在同一过程中执行功能或内置命令时,它与调用方共享相同的陷阱设置-甚至可以对其进行修改。
在《 Bash手册》(“功能”部分)中,以下水龙头专用于功能:DEBUG,RETURN和ERR。
在函数及其调用者之间,shell执行环境的所有其他方面都是相同的 除了以下例外:DEBUG和RETURN陷阱(请参阅SHELL下内置的陷阱的描述 除非已为函数赋予trace属性(请参阅下面的BUILTIN COMMANDS),否则不会继承 下面的内置声明的描述)或-o functrace shell选项已启用 内置的set(在这种情况下,所有函数都继承DEBUG和RETURN陷阱),而ERR陷阱为 除非已启用-o errtrace shell选项,否则不会继承
builtin的工作方式类似-但是RETURN,DEBUG不适用于单个命令。 ERR也适用于内置。
延迟信号处理:
值得强调的是,大多数脚本引擎通常将使用“延迟处理”进行信号处理。收到信号后,外壳程序将记住该信号,设置“中止”标志,然后继续执行当前命令。该命令在检查“尽快中止”时将尝试尽快终止。
对于执行速度非常快的内置命令,无需检查“中止”就可以完成执行。对于功能,脚本引擎通常会在完成每个“简单”步骤之后检查“中止ASAP”标志。
延迟执行允许每个命令执行常规清理(释放内存和其他资源)。
仅在当前执行命令终止时,才开始执行信号命令(由陷阱设置)。