linux - 为什么在非交互式 bash 会话中运行 gradlew 会关闭会话的标准输入?
问题描述
我注意到在 CI 系统中使用gradlew
. 以下步骤有助于概述这一点。
创建一个名为的文件
script
,其内容为:./gradlew echo DONE
gradlew
从某处随机获取- 跑
cat script | bash
请注意,DONE 永远不会出现
AFAICT,以非交互方式运行 bash 会导致exec java blah
最后gradlew
以某种方式允许 java 关闭标准输入,并且永远不允许echo DONE
从通过标准输入从cat
. 支持这一点的事实是:
- 将脚本更改为
./gradlew; echo DONE
将打印 DONE - 替换
./gradlew
为./gradlew < /dev/null
将打印 DONE
解决方案
如果你有某个exec something
地方(在你的情况下),你正在用其他东西( )gradlew
替换当前的过程映像()。bash
java
来自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
您可能还希望屏幕上打印出 World 这个词……错了!
这里什么都没有发生,因为在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)
在这里,您可以清楚地看到正在进行的过程映像替换。
推荐阅读
- rstudio - 如何更正 GLM 的 Y 值
- android - 我无法在 Xamarin 中与 WCF 服务建立连接
- r - for 循环正在工作,但没有任何好处
- visual-studio-code - 我无法在 vscode 上安装任何扩展
- java - 允许用户为数组输入整数,并在输入“-99”时进入下一步
- html - 语义UI表如何在水平滚动时固定右列
- laravel - 为什么 PHPunit 会忽略 .env.testing?
- python - Python pandas 在使用数据框操作时出现警告
- c# - 使用 Ajax aspnet mvc 5 的部分视图
- html - 如何去除 flex 容器中 div 之间的接缝