直接从URL执行bash脚本的解决方案之一是:
bash <(curl -sS http://1.1.1.1/install)
问题是,当curl
无法检索url时,bash没有得到任何作为输入,并且它正常结束(返回代码0)。
我想用curl返回的代码终止。
更新:
两种可能的解决方案:
curl -sS http://1.1.1.1/install | bash; exit ${PIPESTATUS[0]}
或:
bash <(curl -sS http://1.1.1.1/install || echo "exit $?")
最后一条有点粗俗(但更短)
尝试获取curl的returncode:
curl -sS http://1.1.1.1/install | bash
echo ${PIPESTATUS[0]}
使用临时文件
trap 'rm "$install"' EXIT
installer=$(mktemp)
curl ... > "$installer" || exit
# Ideally, verify the installer *before* running it
bash "$installer"
这是为什么。如果您简单地将curl
返回的任何内容通过管道传递给bash
,那么实际上就是允许未知代码在您的机器上执行。最好先确保你所执行的是无害的。
您可能会问,这与使用预打包的安装程序、RPM或其他包系统有什么不同?对于包,您可以通过打包程序提供的校验和来验证您要安装的包是否与他们提供的包相同。您仍然必须信任打包器,但是您不必担心攻击者在途中修改包(中间人攻击)。
您可以将curl
命令的输出保存在一个变量中,并仅在返回状态为零时执行它。它可能不那么优雅,但它与其他shell更兼容(不依赖于$PIPESTATUS
,这在许多shell上都不可用):
install=`curl -sS http://1.1.1.1/install`
if [ $? -ne 0 ]; then
echo "error"
else
echo "$install" | bash
fi