考虑以下 shell 脚本:
#!/bin/bash
echo Hello
gradle clean
echo Bye
通过文件运行时,预期输出是正确的。
$ chmod +x script.sh
$ ./script.sh
Hello
BUILD SUCCESSFUL in 1s
1 actionable task: 1 up-to-date
Bye
当通过 stdin 运行时,预期输出是错误的。
$ cat script.sh | bash -s
Hello
BUILD SUCCESSFUL in 1s
1 actionable task: 1 up-to-date
在 stdin 情况下,运行
gradle clean
后,脚本流程被中断,以返回码 0 退出,并且永远不会到达下一个命令。我正在搜索通过 stdin 执行上述脚本的方法,因为我将使用带curl的管道,例如curl -so- http://host/script.sh | bash -s
。
我可以解决它在新管道中包裹
gradle
的问题,但我也不明白它为什么起作用:
#!/bin/bash
echo Hello
echo gradle clean | bash -s
echo Bye
我想找到一个简洁的解决方案(例如:bash/gradle 中的标志)。谢谢。
正如戈登·戴维森
所指出的大概是从标准输入读取,因此它读取脚本的其余部分,而不是让 shell 读取并执行它。如果gradle
实际上不需要任何输入,请尝试使用gradle
gradle clean </dev/null
您可以使用
重现类似的错误bash -s << 'EOF'
read var
echo "this line is consumed by read"
echo "end of script"
EOF
我不想窃取戈登·戴维森的答案。如果他们写了答案,请接受他们的答案。不过,我有一些重要的事情要补充:
当您计划使用
curl | bash -s
执行脚本时,最好针对此错误和其他典型错误添加更一般的预防措施。bash <(cat <<'END_OF_SCRIPT'
insert your
entire script
here
END_OF_SCRIPT
)
这至少可以防止以下问题
curl
下载脚本的前半部分,但随后失败。脚本只执行了一半。在这种情况下,用户不会收到错误消息(curl -s
是silent,并且bash不知道应该遵循更多命令,除非您处于命令块的中间,例如if ...; then
)也没有退出代码(curl
可能会以非零值退出;但该代码在管道中丢失curl | bash
)。当
bash -e
和/或 set -e
等出现问题时,您可能还想使用 mkdir somedir
/ cd somedir
来停止脚本。有一些警告,但总比没有好。