在Bash脚本中,如果发生某种情况,如何退出整个脚本?

本文讨论了在Bash脚本中如何在遇到错误或特定条件时退出整个脚本的方法,包括使用`set -e`、短路评估、自定义函数以及在命令失败时设置退出代码。此外,还提到了在复杂脚本中处理退出的挑战和解决方案。
摘要由CSDN通过智能技术生成

我正在Bash中编写脚本来测试一些代码。 但是,如果编译代码首先失败,则运行测试似乎很愚蠢,在这种情况下,我将中止测试。

有没有一种方法可以在不将整个脚本包装在while循环内并使用break的情况下做到这一点? 像dun dun dun goto之类的东西?


#1楼

尝试以下语句:

exit 1

用适当的错误代码替换1 。 另请参阅具有特殊含义的退出代码


#2楼

使用set -e

#!/bin/bash

set -e

/bin/command-that-fails
/bin/command-that-fails2

脚本将在失败的第一行之后终止(返回非零退出代码)。 在这种情况下, command-that-fails2将不会运行。

如果要检查每个命令的返回状态,则脚本将如下所示:

#!/bin/bash

# I'm assuming you're using make

cd /project-dir
make
if [[ $? -ne 0 ]] ; then
    exit 1
fi

cd /project-dir2
make
if [[ $? -ne 0 ]] ; then
    exit 1
fi

使用set -e它将看起来像:

#!/bin/bash

set -e

cd /project-dir
make

cd /project-dir2
make

任何失败的命令都将导致整个脚本失败并返回退出状态,您可以使用$检查该退出状态 。 如果您的脚本很长,或者您正在构建很多东西,那么在各处添加返回状态检查将变得非常难看。


#3楼

可以使用短路评估代替if构造:

#!/usr/bin/env bash

echo $[1+1]
echo $[2/0]              # division by 0 but execution of script proceeds
echo $[3+1]
(echo $[4/0]) || exit $? # script halted with code 1 returned from `echo`
echo $[5+1]

请注意一对括号,这是因为交替运算符的优先级所必需的。 $? 是一个特殊变量,用于退出最近调用的命令的代码。


#4楼

我经常包括一个名为run()的函数来处理错误。 我要进行的每个调用都传递给此函数,因此在遇到故障时会退出整个脚本。 与set -e解决方案相比,此方法的优势在于,脚本在行失败时不会自动退出,并且可以告诉您问题出在哪里。 在以下示例中,第三行未执行,因为脚本在调用false时退出。

function run() {
  cmd_output=$(eval $1)
  return_value=$?
  if [ $return_value != 0 ]; then
    echo "Command $1 failed"
    exit -1
  else
    echo "output: $cmd_output"
    echo "Command succeeded."
  fi
  return $return_value
}
run "date"
run "false"
run "date"

#5楼

SysOps的一个人曾经教过我三指爪技术:

yell() { echo "$0: $*" >&2; }
die() { yell "$*"; exit 111; }
try() { "$@" || die "cannot $*"; }

这些功能是* NIX OS和shell健壮的。 将它们放在脚本的开头(bash或其他方式), try()您的语句和代码。

说明

(根据飞羊的评论)。

  • yell :将脚本名称和所有参数打印到stderr
    • $0是脚本的路径;
    • $*都是参数。
    • >&2表示>将标准输出重定向到&管道2管道1本身就是stdout
  • dieyell相同,但退出状态为非0退出 ,表示“失败”。
  • try使用|| (布尔值OR ),仅在左侧失败时才评估右侧。
    • $@还是所有参数,但不同

#6楼

如果要使用source调用脚本,则可以使用return <x> ,其中<x>是脚本退出状态(对于错误或false,请使用非零值)。 但是,如果调用可执行脚本(即直接使用其文件名),则return语句将导致抱怨(错误消息“ return:只能从函数或源脚本中返回”)。

如果改用exit <x> ,则用source调用脚本时,它将导致退出启动脚本的外壳,但是可执行脚本将按预期终止。

要在同一脚本中处理任何一种情况,都可以使用

return <x> 2> /dev/null || exit <x>

这将处理任何合适的调用。 假设您将在脚本的顶层使用此语句。 我建议不要直接从函数中退出脚本。

注意: <x>应该只是一个数字。


#7楼

我有同样的问题,但不能问,因为它将是重复的。

当脚本有点复杂时,使用exit接受的答案不起作用。 如果使用后台进程检查条件,则退出仅退出该进程,因为它在子外壳程序中运行。 要杀死脚本,必须明确杀死它(至少这是我所知道的唯一方法)。

这是一个有关如何执行此操作的小脚本:

#!/bin/bash

boom() {
    while true; do sleep 1.2; echo boom; done
}

f() {
    echo Hello
    N=0
    while
        ((N++ <10))
    do
        sleep 1
        echo $N
        #        ((N > 5)) && exit 4 # does not work
        ((N > 5)) && { kill -9 $$; exit 5; } # works 
    done
}

boom &
f &

while true; do sleep 0.5; echo beep; done

这是一个更好的答案,但仍然不完整-我真的不知道该如何摆脱吊杆零件。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值