curl没有错误消息

时间:2018-02-08 10:34:26

标签: bash curl

我想知道为什么以下bash脚本会吞下错误消息。

#!/bin/sh

set -eu

LATEST=$(curl -s https://api.github.com/repos/dnote-io/cli/tags | grep -Eo '"name": "v\d*\.\d*\.\d*",'  | head -n 1 | sed 's/[," ]//g' | cut -d ':' -f 2)

if [ -z $LATEST ]; then
    echo "Error fetching latest version. Please try again."
    exit 1
fi

....

基本上,脚本会抓取某些内容并将结果分配给变量LATEST。但是当提取错误时,脚本不会打印来自curl的实际错误消息。

关于如何不忽视错误的任何想法或建议?

2 个答案:

答案 0 :(得分:3)

什么错误信息?

  

-s--silent
  无声或安静模式。不要显示进度表或错误消息。使卷曲静音。

改为使用-sS

  

-S--show-error
  当与-s一起使用时,如果curl失败,则会使curl显示错误消息。

您的脚本中还有其他问题:

  • 如果curl失败,脚本会继续,而不会注意到。这是因为忽略了管道左侧的命令失败。通常故障会导致LATEST中的空输出,但如果curl设法连接但连接在下载数据时被中断,则情况可能并非总是如此。 在bash中,但不是在sh中,您可以通过设置pipefail选项来捕获管道左侧的故障。如果您想继续,请检查PIPESTATUS,但请注意,您必须在命令替换中执行此操作。
  • [ -z $LATEST ]是错误的,因为LATEST的值被拆分为以空格分隔的单词,这些单词被解释为通配符模式。如果值不包含任何特殊字符,它将起作用,但这很脆弱,尤其是因为您正在解析下载的内容。见Why does my shell script choke on whitespace or other special characters? 。始终在变量和命令替换周围使用双引号,除非您知道为什么需要将它们关闭。或者,在bash中但不在sh中,使用[[ … ]]语法,它不需要双引号(比较运算符的右侧除外,如果你不想记住这些)例外,只是一直使用双引号。
#!/bin/bash
set -eu
set -o pipefail

LATEST=$(curl -s https://api.github.com/repos/dnote-io/cli/tags | grep -Eo '"name": "v\d*\.\d*\.\d*",'  | head -n 1 | sed 's/[," ]//g' | cut -d ':' -f 2)

if [ -z "$LATEST" ]; then
    echo >&2 "Download from github successful, but extracting the version failed."
    exit 1
fi

答案 1 :(得分:0)

这里有两个因素都有贡献。

  1. 您正在管道中运行curlset -e功能仅适用于管道中的最后一个命令;这就是shell的设计方式。

  2. 没有来自curl的错误消息,因为您使用-s运行它。

  3. 从命令中捕获输出并同时检查其退出状态很容易,但最终结果是shell变量。根据您的情况,这可能会也可能不会很麻烦。

    if curlout=$(curl -s https://api.github.com/repos/dnote-io/cli/tags); then
        # curl succeeded; *now* parse the result
        latest="$(sed -n 's/.*"name": "\(v\[0-9]*\.\[0-9]*\.\[0-9]*\)",.*/!d;s//\1/;q' <<<"$curlout")"
    else
        rc=$?
        echo "$0: curl failed: $rc" >&2
        exit "$rc"
    fi
    

    我将您的长管道重构为单个sed脚本,因为这样做相对容易。我仍然怀疑你能找到许多实际理解Perl正则表达式主义grep -E的{​​{1}}实现,所以也许你的代码实际上并没有真正起作用。如果结果是JSON,那么正确的解决方案是使用适当的JSON解析器,例如\d

    还要注意你的变量应该是小写的;大写变量通常保留供系统使用。

    你的shebang说jq所以你不能使用像#!/bin/sh这样的Bash功能。也许你真的希望在shebang中pipefail,所以你可以在你的脚本中使用Bash功能(无论如何,当你标记这个问题时)。