Bash 我写的流水线 Shell 脚本 Starved/Deadlocked/Performing 很差

Bash Pipelined Shell scripts I wrote are Starved/Deadlocked/Performing poorly

我已经使用 duff 创建了文件系统中重复文件的报告:

duff ~/Photos > ~/Photos/duplicates.txt

我已经编写了一些 groovy 脚本来将此报告转换为 HTML 页面,我可以在浏览器中查看重复的照片:

cat duplicates.txt | filter_non_existent.groovy | duff_to_json.groovy | json_to_html.groovy > duplicates.html

大约 50% 的时间,它工作得很好,没有任何问题。

有时我的一些脚本没有开始执行,或者 运行 非常慢。为什么会这样,我能做些什么来防止它发生? (为什么 "professionally written" 像 grep 这样的命令行程序没有遇到这个问题?)

更多信息

根据您提供的有限信息很难说出原因。每次您通过管道连接到 groovy 的另一个实例时,您都会启动一个新的 jvm,它会产生开销并且会给您的系统带来负担。 (检查 java 的默认启动设置。)

另一件事是您的脚本休眠 2.5 秒,然后轮询工作,然后返回休眠 2.5 秒...如果您有 3 个脚本按顺序执行并且一个正在等待另一个的输出,这正在睡觉等。您最多可以等待:

2.5 + 2.5 + 2.5 = 7.5 秒

如果其他脚本必须完成的工作超过一秒,则可能会更长(例如直接在 java 中处理大量字符串)...可能值得您花时间学习使用:bash、grep 等。首先要避免重复发明轮子,其次要使用正确的工具来完成正确的工作。

Groovy 很棒,但是从你正在做的事情来看,你可能可以用 grep -v 过滤东西,对于 duff 到 json,json 到 html,也许写你的适配器直接去 html?听起来你正在做的任何转换文本的工作都可能不是很有效...

为什么要检查流是否准备好?您要做的就是等待数据可用,并在可用时读取它;如果您只是使用普通的潜在阻塞读取,就会发生这种情况。

如果您在没有数据立即可用时立即退出读取循环(您的代码摘录似乎正在这样做),那么您的程序很可能会提前终止,至少在某些时候是这样。如果您只是阅读(可能会阻塞直到数据可用)直到看到 EOF,那么事情应该就可以了。 (这就是 grep 和其他 "professionally written programs" 所做的。)