![POSIX 的退出陷阱](https://linux22.com/image/153897/POSIX%20%E7%9A%84%E9%80%80%E5%87%BA%E9%99%B7%E9%98%B1.png)
我有一个用 Bash 编写的脚本,我正在尝试修改它以使其符合 POSIX 标准。我已经设法让一切正常工作,除了当使用killall、CTRL+C或关闭终端终止进程时我无法触发 EXIT 陷阱 - 就像 Bash 所做的那样。这是我的退出陷阱:
#!/bin/sh
TMP=$(mktemp /tmp/countdown.XXXXX)
trap 'rm -rf $TMP' EXIT
答案1
在严格的 POSIX shell 中,EXIT
在 shell 由于执行exit
或由于执行脚本中的最后一个命令而退出之前,会评估陷阱。如果 shell 由于信号而退出,则不会执行。
如果你想捕获Ctrl+C,你就必须捕获INT
(“中断”信号)。如果关闭终端向脚本发送一个HUP
(“挂断”)信号,您也必须捕获该信号。
trap 'rm -rf "$TMP"; trap - EXIT; exit' EXIT INT HUP
您可能还想捕获TERM
,默认情况下发送的通用“终止”信号kill
。
上面的陷阱显式地重置了EXIT
陷阱,以便它不会被调用再次当脚本因接收到列出的信号之一而退出时。
答案2
正如 Kusalananda 所提到的,EXIT
不会捕获 POSIX 中的信号。最简单的解决方案是在代码中添加如下内容:
trap exit INT HUP TERM
这将捕获您想要的信号,并在到达退出语句时调用原始陷阱。
答案3
只需在创建临时文件后立即将其删除,然后通过文件描述符对其进行读写即可。
将其作为/dev/fd/[fd]
或/proc/self/fd/[fd]
传递给需要路径的命令。
例子:
t=$(mktemp); exec 5<>"$t"; rm "$t"
echo some text >&5
exec 5<>/dev/fd/5 # rewind / seek back at the start of the file
cat <&5
cmd1 /dev/fd/5 # cmd1 only takes paths
cmd2 5>&- # don't leak fd 5 to cmd2
您还可以将临时文件打开为多个分离fds,如exec 5<"$t" 6>"$t"
.
倒回技巧仅适用于 Linux;我想不出任何可移植的方法来做到这一点;欢迎提出想法;-\