shell 为什么curl在bash脚本中不返回值?

hyrbngr7  于 2023-02-09  发布在  Shell
关注(0)|答案(1)|浏览(470)

我的任务很简单--尽管如此,我已经坐了好几个小时了,不知道为什么它不起作用。
在linux bash脚本中,我想得到curl调用webservice的结果,我对内容不感兴趣,只对状态码感兴趣:

#!/bin/bash
set -euo pipefail # put bash in "strict mode"

echo "Before"
response2=$(curl  -o /dev/null -s  -w '%{http_code}'  -u username:password-X POST https://xxxxx.yyyyy.at:8081/MyPath/service/rest/crypto/encrypt -H 'Content-Type: application/json' -d '{"deviceId": "ABCD","payload": "ABCD"}')
echo "after"

它在存在有效请求时工作

Before...
200

此外,当服务的路径错误时,它会给出http错误代码

Before...
500

但是当主机错误(不存在主机名)时,我会得到

Before...

并且脚本终止(尽管调用来自循环菜单)。
为什么会这样呢?
使用相同参数手动调用curl,给出

000

作为输出,那么为什么这个输出是不显示在我的脚本?
下面是一个可重现的示例(服务器名称不存在):

#!/bin/bash
set -euo pipefail

#- Check kms
f_check_kms(){

    echo "Before..."
    response2=$(curl  -o /dev/null -s  -w '%{http_code}'  -u user:xxxx -X POST https://xxxx.xxx.intra.graz.at:8081/ATM-KeyManagement-REST-Service/service/rest/crypto/encryptUCast -H 'Content-Type: application/json' -d '{"deviceId": "SAG0530000016261", "encryptionSuite": "DLMS_SUITE_0", "securityMode": "AUTHENT_AND_ENCRYPT", "roleId": "001","initialVector": "4D4D4D0000BC614E01234567","payload": "ABCD","usedGuek":"NO","usedGak":"NO"}')
    
    echo "$response2"

}


f_check_kms
oknrviil

oknrviil1#

您使用set -e运行脚本,以使shell解释器在任何未检查的¹ ²命令以非零状态退出时退出,并且当您提供无效的主机名时,curl以非零退出状态退出。
因为您传递的是静默模式的-s,所以它不会打印任何错误消息(您要求它不要这样做!),它 * 确实 * 仍然打印您所要求的http_code,但是因为脚本退出,所以永远不会到达echo "after",并且您依赖于打印response2变量内容的任何其他代码也同样永远不会到达。
抑制这种情况非常简单,只需在末尾添加一个条件,如下面的|| :序列:

response2=$(curl -o /dev/null -s  -w '%{http_code}' -u username:password \
  -X POST https://xxxxx.yyyyy.at:8081/MyPath/service/rest/crypto/encrypt \
  -H 'Content-Type: application/json' \
  -d '{"deviceId": "ABCD","payload": "ABCD"}' \
) || : "Ignoring exit status of $?"

在跟踪模式下运行脚本时,您可以看到该消息(set -x/bash -x yourscript),但在其他情况下,它是不可见的,并且由于||在curl的退出状态上进行分支,因此将curl标记为“checked”,因此set -e不会根据其退出状态决定退出。
¹不完全正确:set -e有一堆异常,它 * 不会 * 退出,这些异常在各个shell版本之间会发生变化。
²这是一个 * 非常 * 缺乏直观定义的词:例如,当您检查一个函数的退出状态时,* 函数调用的所有内容 * 都可能变为“已检查”,因此set -e的行为与上下文极其相关,很难预测;当一个函数被调用一次时所检查的内容在以后被再次调用时可能不会被检查。

相关问题