gpt4 book ai didi

bash - SIGPIPE 由于文件描述符和进程替换

转载 作者:行者123 更新时间:2023-12-04 01:17:57 25 4
gpt4 key购买 nike

我正在尝试从执行工具的 bash 函数中保存一些日志(其中一些在子 shell 中运行)。此外,我想将所有错误打印到终端。

我的代码导致一个 sigpipe 并在按下 ctr-c 加上一个奇怪的日志文件时退出代码 141。管道故障似乎是由于在陷阱内将 stdout 重定向到 stderr,这会破坏 tee 命令的 stdout 流。有趣的是,代码按预期终止,退出代码为 130,没有在陷阱或 cat 命令中使用重定向。

  1. 我仍然无法修复和解释生成的日志文件。为什么有些 echo 两次,为什么trap echo 也写入文件?

  2. 为什么 sigpipe 不是由函数内的重定向引起的?

trap '
echo trap_stdout
echo trap_stderr >&2
' INT

fun(){
echo fun_stdout
echo fun_stderr >&2
( sleep 10 | cat )
}

echo > log
fun >> log 2> >(tee -a log)

日志文件

fun_stdout
fun_stderr
fun_stderr
trap_stdout

编辑:根据 oguz ismail 回答的工作示例

exec 3>> log
exec 4> >(tee -ai log >&2)
fun 2>&4 >&3
exec 3>&-
exec 4>&-

最佳答案

Why are there some echos twice

fun 的标准输出被重定向到 log,然后它的 stderr 被重定向到为 tee 创建的 FIFO,因此 tee 继承了一个重定向到 log 的标准输出。我可以这样证明:

$ : > file 2> >(date)
$ cat file
Sat Jul 25 18:46:31 +03 2020

改变重定向的顺序将解决这个问题。例如:

fun 2> >(tee -a log) >> log

and why are the trap echos written to the file as well?

如果在 shell 仍在执行 fun 时触发了为 SIGINT 设置的陷阱,则与 fun 关联的重定向生效是完全正常的。

要将陷阱操作的标准输出和标准错误连接到主 shell 的标准输出和标准错误,您可以执行以下操作:

exec 3>&1 4>&2

handler() {
: # handle SIGINT here
} 1>&3 2>&4

trap handler INT

或者类似的东西;这个想法是复制主 shell 的标准输出和标准错误。

Why isn't the sigpipe caused earlier by the redirection within the function?

因为 tee 在执行 echo fun_stderr >&2 时还活着。并且 sleep 不会向其标准输出写入任何内容,因此它无法触发 SIGPIPE。

此脚本因 SIGPIPE 而终止的原因是 tee 也接收到键盘生成的 SIGINT,并在执行与 SIGINT 关联的陷阱操作之前终止。结果,在执行 echo trap_stderr >&2 时,由于它的 stderr 连接到刚才关闭的管道,shell 接收到 SIGPIPE。

如前所述,为避免这种情况,您可以使 tee 忽略 SIGINT。不过,您不需要为此设置空陷阱,-i 选项就足够了。

fun 2> >(tee -a -i log) >> log

关于bash - SIGPIPE 由于文件描述符和进程替换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63025706/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com