【问题标题】:exit statement will not break while loop in unix shell在 unix shell 中,exit 语句不会中断 while 循环
【发布时间】:2013-07-23 12:46:02
【问题描述】:

每个状态检查 if 语句中的 exit 语句不会中断 while 循环并真正退出脚本。我可以做些什么来打破循环并使用 $STATUS 代码退出?

编辑:我已经更新了我的代码,但它仍然无法正常工作。如果语句成功中断循环,则状态检查,但是当我尝试评估 $EXIT_STATUS 时,它始终为空,可能与范围有关。我在这里想念什么?

  if [ $RESTART -le $STEP ]; then
  . tell_step

  while read XML_INPUT; do

    XML_GDG=`get_full_name $GDG_NAME P`

    cp $XML_INPUT $XML_GDG


    STATUS=$?
    EXIT_STATUS=$STATUS
    if [ $STATUS -ne 0 ]; then
      break
    fi

    add_one_gen $XML_GDG

    STATUS=$?
    EXIT_STATUS=$STATUS
    if [ $STATUS -ne 0 ]; then
      break
    fi

  done < $XML_STAGE_LIST

  echo $EXIT_STATUS
  if [ $EXIT_STATUS -ne 0 ]; then
    exit $EXIT_STATUS
  fi

fi

【问题讨论】:

  • 快速评论 - 很难阅读包含很多大写字母的脚本。尝试为一些“特殊”变量保留大写名称(或者更好,仅用于导出的变量)..
  • 使用break 而不是exit
  • @fedorqui break 将退出循环,但不会以状态退出脚本,我实际上是在尝试两者。
  • 那么在这些情况下,将退出状态存储在变量 (exit_status=$STATUS) 中,然后使用它退出 exit $exit_status
  • @fedorqui 好电话,应该可以。

标签: shell unix while-loop


【解决方案1】:

我遇到了同样的问题:当管道进入 while 循环时,脚本在退出时没有退出。相反,它就像“break”应该做的那样工作。

我找到了 2 个解决方案:

a) 在你的 while 循环之后检查 while 循环的返回码然后退出:

somecommand | while something; do
    ...
done
# pass the exit code from the while loop
if [ $? != 0 ]
then
    # this really exits
    exit $?
fi

b) 设置 bash 脚本在任何错误时退出。将此粘贴到脚本的开头:

set -e

【讨论】:

    【解决方案2】:

    不太明白为什么你的脚本在退出时不退出,因为下一个是没有问题的:

    while read name; do
        echo "checking: $name"
        grep $name /etc/passwd >/dev/null 2>&1
        STATUS=$?
        if [ $STATUS -ne 0 ]; then
            echo "grep failed for $name rc-$STATUS"
            exit $STATUS
        fi
    done <<EOF
    root
    bullshit
    daemon
    EOF
    

    运行它,产生:

    $ bash testscript.sh ; echo "exited with: $?"
    grep failed for bullshit rc-1
    exited with: 1
    

    如您所见,脚本立即退出并且不检查“守护进程”。

    无论如何,也许它更具可读性,当你将使用bash functions 时:

    dostep1() {
        grep "$1:" /etc/passwd >/dev/null 2>&1
        return $?
    }
    
    dostep2() {
        grep "$1:" /some/nonexistent/file >/dev/null 2>&1
        return $?
    }
    
    err() {
        retval=$1; shift;
        echo "$@" >&2 ; return $retval
    }
    
    while read name
    do
        echo =checking $name=
        dostep1 $name || err $? "Step 1 failed" || exit $?
        dostep2 $name || err $? "Step 2 failed" || exit $?
    done
    

    当运行时:

    echo 'root
    > bullshit' | bash testexit.sh; echo "status: $?"
    =checking root=
    Step 2 failed
    status: 2
    

    所以,step1 正常并在 step2 上退出(不存在的文件) - grep 退出状态 2,以及何时

    echo 'bullshit
    bin' | bash testexit.sh; echo "status: $?"
    =checking bullshit=
    Step 1 failed
    status: 1
    

    在第 1 步立即退出(废话不在 /etc/passwd 中)- grep 退出状态 1

    【讨论】:

      【解决方案3】:

      您需要 break 退出循环,然后 exit 从脚本中退出。您可以使用设置为错误的变量来测试您是否需要 exit 带有错误条件。

      【讨论】:

        【解决方案4】:

        流水线时我遇到了类似的问题。我的猜测是流水线时会启动一个单独的外壳。希望它可以帮助遇到问题的其他人。

        从上面 jm666 的帖子中,这不会打印“我在这里!”:

        while read name; do
           echo "checking: $name"
           grep $name /etc/passwd >/dev/null 2>&1
           STATUS=$?
           if [ $STATUS -ne 0 ]; then
              echo "grep failed for $name rc-$STATUS"
              exit $STATUS
           fi
        done <<EOF
        root
        yayablah
        daemon
        EOF
        
        echo "Here I am!"
        

        但是,将名称通过管道传递到 while 循环的以下内容确实如此。它也会以代码 0 退出。设置变量和 breaking 似乎也不起作用(如果它是另一个 shell,这很有意义)。需要使用另一种方法来传达错误或首先避免这种情况。

        cat <<EOF |
        root
        yayablah
        daemon
        EOF
        while read name; do
           echo "checking: $name"
           grep $name /etc/passwd >/dev/null 2>&1
           STATUS=$?
           if [ $STATUS -ne 0 ]; then
              echo "grep failed for $name rc-$STATUS"
              exit $STATUS
           fi
        done
        
        echo "Here I am!"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-04-07
          • 1970-01-01
          • 2021-01-17
          • 2012-03-26
          • 1970-01-01
          • 2021-01-30
          • 2013-11-01
          • 2021-04-15
          相关资源
          最近更新 更多