简体   繁体   English

没有来自curl的错误信息

[英]No error message from curl

I would like to know why the following bash script swallows the error message. 我想知道为什么以下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

....

Basically, the script fetches something and assigns the result to a variable LATEST . 基本上,脚本会获取内容并将结果分配给变量LATEST But when the fetching goes wrong, the script does not print the actual error message from curl . 但是,当提取错误时,脚本不会从curl打印实际的错误消息。

Any ideas or suggestions on how to not ignore the error? 关于如何不忽略错误的任何想法或建议?

What error message? 什么错误消息?

-s , --silent -s ,-- --silent
Silent or quiet mode. 静音或安静模式。 Don't show progress meter or error messages. 不要显示进度表或错误消息。 Makes Curl mute. 使Curl静音。

Use -sS instead. 使用-sS代替。

-S , --show-error -S--show-error
When used with -s it makes curl show an error message if it fails. -s使用时,如果curl失败,它将使curl显示一条错误消息。

There are other problems in your script: 您的脚本中还有其他问题:

  • If curl fails, the script continues without noticing. 如果curl失败,该脚本将继续运行而不会引起注意。 This is because the failure of a command on the left-hand side of a pipeline is ignored. 这是因为忽略了管道左侧的命令失败。 Usually a failure will lead to an empty output in LATEST , but this may not always be the case, if curl manages to connect but the connection is interrupted while it's downloading the data. 通常,失败将导致LATEST输出为空,但是,如果curl设法连接但下载数据时连接中断,则情况并非总是如此。
    In bash, but not in sh, you can capture the failure of the left-hand side of a pipe by setting the pipefail option. 在bash中,但不在sh中,您可以通过设置pipefail选项来捕获管道左侧的故障。 If you want to keep going, check PIPESTATUS , but note that you'd have to do this inside the command substitution. 如果要继续,请检查PIPESTATUS ,但请注意,您必须在命令替换内执行此操作。
  • [ -z $LATEST ] is wrong because the value of LATEST is split into whitespace-delimited words which are interpreted as wildcard patterns. [ -z $LATEST ]是错误的,因为LATEST的值被分成空格分隔的单词,这些单词被解释为通配符模式。 It'll work if the value doesn't contain any special characters, but this is fragile, especially since you're parsing downloaded content. 如果该值不包含任何特殊字符,它将起作用,但这很脆弱,尤其是因为您正在解析下载的内容。 See Why does my shell script choke on whitespace or other special characters? 请参阅为什么我的shell脚本在空白或其他特殊字符上会阻塞? . Always use double quotes around variable and command substitutions, unless you know why you need to leave them off. 始终在变量和命令替换周围使用双引号,除非您知道为什么需要将其保留。 Alternatively, in bash but not in sh, use the [[ … ]] syntax, which doesn't require double quotes (except on the right-hand side of comparison operators, and if you don't like remembering these exceptions, just use double quotes all the time). 另外,在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

There are two factors here which both contribute. 这里有两个因素共同起作用。

  1. You are running curl in a pipeline. 您正在管道中运行curl The set -e functionality only applies to the last command in a pipe; set -e功能仅适用于管道中的最后一个命令; this is how the shell is designed. 这就是外壳的设计方式。

  2. There is no error message from curl because you are running it with -s . 没有来自错误消息, curl ,因为你与运行它-s

Capturing the output from a command and checking its exit status at the same time is easy, but then you end up with the results in a shell variable. 捕获命令的输出并同时检查其退出状态很容易,但是最终将结果存储在shell变量中。 Depending on your scenario, this may or may not be cumbersome. 根据您的情况,这可能会或可能不会很麻烦。

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

I refactored your long pipeline into a single sed script, since that was relatively easy to do. 我将您的长管道重构为一个sed脚本,因为这样做相对容易。 I still doubt you can find many grep -E implementations which actually understand the Perl regex-ism \\d so maybe your code simply wasn't actually working. 我仍然怀疑您会发现许多grep -E实现实际上了解Perl regex-ism \\d因此也许您的代码实际上并没有真正起作用。 If the result is JSON, the proper solution would be to use a proper JSON parser like jq instead. 如果结果是JSON,则正确的解决方案是改用jq类的正确JSON解析器。

Also notice how your variables should be lower case; 还要注意您的变量应如何小写。 uppercase variables are generally reserved for system use. 大写变量通常保留供系统使用。

Your shebang says #!/bin/sh so you can't use Bash features like pipefail with that. 您的shebang会说#!/bin/sh因此您不能使用像pipefail这样的Bash功能。 Perhaps you actually want #!/bin/bash in the shebang so you can use Bash features in your script (seeing as you tagged this question anyway). 也许您实际上想要在shebang中使用#!/bin/bash以便您可以在脚本中使用Bash功能(无论如何,您始终在标记此问题看到)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM