gpt4 book ai didi

bash - shell 管道的惰性(非缓冲)处理

转载 作者:行者123 更新时间:2023-11-29 09:22:47 25 4
gpt4 key购买 nike

我正在尝试弄清楚如何对标准 UNIX shell 管道执行最懒惰的可能处理。例如,假设我有一个执行一些计算和输出的命令,但计算变得越来越昂贵,因此前几行输出很快到达,但随后的几行变得更慢。如果我只对前几行感兴趣,那么我想通过 lazy evaluation 获得它们,在它们变得太昂贵之前尽快终止计算。

这可以通过直接的 shell 管道来实现,例如:

./expensive | head -n 2

然而,这并没有达到最佳效果。让我们用一个指数级变慢的脚本来模拟计算:

#!/bin/sh

i=1
while true; do
echo line $i
sleep $(( i ** 4 ))
i=$(( i+1 ))
done

现在,当我通过 head -n 2 传递此脚本时,我观察到以下情况:

  • line 1是输出。
  • 睡了一秒后,line 2是输出。
  • 尽管head -n 2已经收到两条(\n-终止)线路并退出,expensive继续运行,现在在完成之前再等待 16 秒 ( 2 ** 4 ),此时管道也完成。

显然,这并不像预期的那样懒惰,因为理想情况下 expensive将在 head 后立即终止进程收到两行。然而,这并没有发生; IIUC 它实际上在尝试写入其第三 行后终止,因为此时它试图写入其 STDOUT。它通过管道连接到 STDIN head已经退出并因此不再从管道读取输入的进程。这导致 expensive收到SIGPIPE ,这会导致 bash运行脚本以调用其 SIGPIPE 的解释器默认情况下终止运行脚本的处理程序(尽管这可以通过 trap 命令更改)。

所以问题是,我怎样才能做到 expensivehead立即退出退出,不只是在 expensive 时试图将其第三行写入另一端不再有监听器的管道?由于管道是由交互式 shell 进程构建和管理的,因此我输入了 ./expensive | head -n 2。命令进入,大概是交互式 shell 是这个问题的任何解决方案所在的地方,而不是对 expensive 的任何修改。或 head ?是否有任何 native 技巧或额外的实用程序可以构建具有我想要的行为的管道?或者可能根本不可能在 bash 中实现我想要的或 zsh ,唯一的方法是编写我自己的管道管理器(例如在 Ruby 或 Python 中),它会在读取器终止时发现并立即终止写入器?

最佳答案

如果您只关心前台控制,您可以在进程替换中运行expensive;它仍然会阻塞,直到它下次尝试写入,但是 head 在收到输入后立即退出(并且您的脚本的流控制可以继续)

head -n 2 < <(exec ./expensive)
# expensive still runs 16 seconds in the background, but doesn't block your program

在 bash 4.4 中,它们将它们的 PID 存储在 $! 中,并允许以与其他后台进程相同的方式进行进程管理。

# REQUIRES BASH 4.4 OR NEWER
exec {expensive_fd}< <(exec ./expensive); expensive_pid=$!
head -n 2 <&"$expensive_fd" # read the content we want
exec {expensive_fd}<&- # close the descriptor
kill "$expensive_pid" # and kill the process

另一种方法是协进程,它的优点是只需要 bash 4.0:

# magic: store stdin and stdout FDs in an array named "expensive", and PID in expensive_PID
coproc expensive { exec ./expensive }

# read two lines from input FD...
head -n 2 <&"${expensive[0]}"

# ...and kill the process.
kill "$expensive_PID"

关于bash - shell 管道的惰性(非缓冲)处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45326901/

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