首页 > 解决方案 > 为什么在非交互式 bash 会话中运行 gradlew 会关闭会话的标准输入?

问题描述

我注意到在 CI 系统中使用gradlew. 以下步骤有助于概述这一点。

  1. 创建一个名为的文件script,其内容为:

    ./gradlew
    echo DONE
    
  2. gradlew从某处随机获取

  3. cat script | bash

请注意,DONE 永远不会出现

AFAICT,以非交互方式运行 bash 会导致exec java blah最后gradlew以某种方式允许 java 关闭标准输入,并且永远不允许echo DONE从通过标准输入从cat. 支持这一点的事实是:

标签: linuxbashgradleposix

解决方案


如果你有某个exec something地方(在你的情况下),你正在用其他东西( )gradlew替换当前的过程映像()。bashjava

来自help exec

exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
用给定的命令替换 shell。

所以问题不在于stdin正在关闭,正在发生的事情是新进程 ( java) 将是读取该输入 ( "echo DONE" ) 的进程,并且可能什么都不做。


举例说明

考虑这个 script.sh:

#!/bin/bash

echo Hello
exec cat
echo World

如果你执行它提供一些输入cat

$ ./script.sh <<< "Nice"
Hello
Nice

您可能还希望屏幕上打印出 Wo​​rld 这个词……错了
这里什么都没有发生,因为在exec命令之后执行了任何其他操作。

现在,如果您将脚本通过管道传输到 bash:

$ cat script.sh | bash
Hello        <- bash interpreted "echo Hello" and printed Hello
echo World   <- cat read "echo World" and printed it (no interpertation ocurred)

在这里,您可以清楚地看到正在进行的过程映像替换


推荐阅读