如何根据 for 循环的结果让这个脚本错误退出?

the*_*fog 20 bash shell-script

我有一个 bash 脚本,它使用set -o errexit以便在出错时整个脚本在故障点退出。
该脚本运行的curl命令有时无法检索预期文件 - 但是当发生这种情况时,脚本不会错误退出。

我添加了一个for循环

  1. 暂停几秒钟,然后重试该curl命令
  2. false在 for 循环的底部使用来定义默认的非零退出状态 - 如果 curl 命令成功 - 循环中断并且最后一个命令的退出状态应该为零。
#! /bin/bash

set -o errexit

# ...

for (( i=1; i<5; i++ ))
do
    echo "attempt number: "$i
    curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
    if [ -f ~/.vim/autoload/pathogen.vim ]
    then
        echo "file has been retrieved by curl, so breaking now..."
        break;
    fi

    echo "curl'ed file doesn't yet exist, so now will wait 5 seconds and retry"
    sleep 5
    # exit with non-zero status so main script will errexit
    false

done

# rest of script .....
Run Code Online (Sandbox Code Playgroud)

问题是当curl命令失败时,循环会重试命令五次 - 如果所有尝试都不成功,则 for 循环完成并且主脚本恢复 - 而不是触发errexit.
如果此curl语句失败,如何让整个脚本退出?

Joh*_*024 29

代替:

done
Run Code Online (Sandbox Code Playgroud)

和:

done || exit 1
Run Code Online (Sandbox Code Playgroud)

如果for循环以非零退出代码退出,这将导致代码退出。

作为一个琐事,不需要1in exit 1。如果下载失败,普通exit命令会以最后执行的命令的退出状态退出,该状态将是false(code=1)。如果下载成功,循环的退出码就是echo命令的退出码。 echo通常以 code=0 退出,表示成功。在这种情况下,||不会触发并且exit不执行命令。

最后,请注意这set -o errexit可能充满惊喜。有关其优缺点的讨论,请参阅Greg 的常见问题解答 #105

文档

来自man bash

for (( expr1 ; expr2 ; expr3 )) ; 清单; done
首先,算术表达式 expr1 根据下面在算术求值中描述的规则求值。然后重复计算算术表达式 expr2 直到它的计算结果为零。每次 expr2 计算为非零值时,都会执行 list 并计算算术表达式 expr3。如果任何表达式被省略,它的行为就像它的计算结果为 1。 返回值是列表中执行的最后一个命令的退出状态,如果任何表达式无效,则返回 false。[强调]


小智 6

如果您希望在第一次失败时停止循环,并避免set -e,您可以执行以下操作:

for i in `seq 1 10`; do
  run_command || exit 1;
done
Run Code Online (Sandbox Code Playgroud)

  • `exit 1` 会停止循环,但也会停止整个脚本。将其替换为 `break` 以停止循环(如您所描述的) (3认同)