【问题标题】:Bash Pipelined Shell scripts I wrote are Starved/Deadlocked/Performing poorly我写的 Bash Pipelined Shell 脚本饿死/死锁/性能不佳
【发布时间】:2016-08-16 02:59:40
【问题描述】:

我已使用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% 的时间,它运行良好,没有任何问题。

有时我的一些脚本无法开始执行,或者运行速度很慢。为什么会这样,我能做些什么来防止它? (为什么像 grep 这样的“专业编写的”命令行程序不会遇到这个问题?)

更多信息

  • 我延迟每个脚本的启动,直到它接收到标准输入(而 无数据,休眠 2.5 秒)。饥饿更加频繁 当睡眠间隔较短时
  • 我连接在一起的管道越多,它发生的频率就越高(如果我只是在 cat 之后执行我的脚本之一,我永远不会遇到问题)
  • 这是我的每个脚本使用的模板(我使用 groovy 运行时,但坚持使用纯 java 语法):

    public static void main(String[] args) 抛出 IOException {

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    
    while (!br.ready()) {
        Thread.sleep(2500L);
    }
    
    while (br.ready()) {
        String inputLine = br.readLine();
        // Do stuff
    }
    

    }

【问题讨论】:

    标签: bash groovy pipe pipeline


    【解决方案1】:

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

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

    【讨论】:

    • 哦,我明白了,我认为.ready() 将等同于阅读,直到它看到 EOF。我会试试这个。 (我试图避免在循环条件内分配给循环变量的那种可怕的习惯用法)。
    • 如果对ready 的调用相当于EOF 检查,那么在2.5 秒后重新测试它会有点傻,不是吗?管道不会仅仅因为没有可用数据而返回 EOF;当(最后一个)作者关闭文件描述符时,它们返回 EOF。
    • 我将不得不仔细考虑您刚才提到的常识方面。但在那之前,我很高兴地说这是可行的 :) 谢谢。
    【解决方案2】:

    由于您提供的信息有限,很难说出原因。每次您通过管道连接到另一个 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?听起来您正在做的任何转换文本的操作都可能不是很有效...

    【讨论】:

    • 感谢您分享您的想法。关于完全绕过 java/groovy,我宁愿不这样做,因为这个例子只是触及了我想做的事情的表面,这些事情在 Java 中比在 bash 中更容易做。此外,我试图向自己证明,大型企业 Java 应用程序是糟糕的,并且您可以使用管道以更模块化的方式完成相同的事情(希望在我职业生涯的后期获得更高资历时可以强加)。
    • 大多数大型企业 Java 应用程序都很糟糕,但 shell、管道和 groovy 脚本不一定是解决该问题的最佳方法。谷歌微服务
    猜你喜欢
    • 2021-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 2018-07-08
    • 1970-01-01
    • 2020-11-30
    相关资源
    最近更新 更多