为什么非交互式 bash 会话中的 运行 gradlew 会关闭会话的标准输入?
Why does running gradlew in a non-interactive bash session closes the session's stdin?
我注意到在 CI 系统中使用 gradlew
时脚本提前成功退出这个奇怪的问题。以下步骤有助于概括这一点。
创建名为 script
的文件,内容为:
./gradlew
echo DONE
从某处随机gradlew
- 运行
cat script | bash
注意 DONE 永远不会出现
AFAICT,运行 bash 非交互地导致 gradlew
末尾的 exec java blah
以某种方式允许 java 关闭标准输入并且永远不允许要从脚本中读取的 echo DONE
通过标准输入从 cat
读取。支持这一点的事实是:
- 将脚本更改为
./gradlew; echo DONE
将打印 DONE
- 将
./gradlew
替换为 ./gradlew < /dev/null
将打印 DONE
如果你有一个 exec something
某处(在你的情况下 gradlew
内),你正在用其他东西(java
替换当前过程映像(bash
) ).
来自help exec
:
exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
Replace the shell with the given command.
所以问题不在于 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)
在这里您可以清楚地看到正在运行的过程图像替换。
我注意到在 CI 系统中使用 gradlew
时脚本提前成功退出这个奇怪的问题。以下步骤有助于概括这一点。
创建名为
script
的文件,内容为:./gradlew echo DONE
从某处随机
gradlew
- 运行
cat script | bash
注意 DONE 永远不会出现
AFAICT,运行 bash 非交互地导致 gradlew
末尾的 exec java blah
以某种方式允许 java 关闭标准输入并且永远不允许要从脚本中读取的 echo DONE
通过标准输入从 cat
读取。支持这一点的事实是:
- 将脚本更改为
./gradlew; echo DONE
将打印 DONE - 将
./gradlew
替换为./gradlew < /dev/null
将打印 DONE
如果你有一个 exec something
某处(在你的情况下 gradlew
内),你正在用其他东西(java
替换当前过程映像(bash
) ).
来自help exec
:
exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
Replace the shell with the given command.
所以问题不在于 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)
在这里您可以清楚地看到正在运行的过程图像替换。