your programing

Bash 스크립트에서 특정 조건이 발생하면 전체 스크립트를 종료하려면 어떻게해야합니까?

lovepro 2020. 10. 2. 23:03
반응형

Bash 스크립트에서 특정 조건이 발생하면 전체 스크립트를 종료하려면 어떻게해야합니까?


일부 코드를 테스트하기 위해 Bash에서 스크립트를 작성하고 있습니다. 그러나 코드 컴파일이 처음에 실패하면 테스트를 실행하는 것은 어리석은 것처럼 보입니다.이 경우 테스트를 중단합니다.

while 루프 내부에 전체 스크립트를 래핑하고 중단을 사용하지 않고이 작업을 수행 할 수있는 방법이 있습니까? 유사한 뭔가 암갈색 암갈색 암갈색의 고토?


다음 진술을 시도하십시오.

exit 1

1적절한 오류 코드로 교체하십시오 . 특별한 의미를 가진 종료 코드를 참조하십시오 .


set -e 사용

#!/bin/bash

set -e

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

스크립트는 실패한 첫 번째 줄 이후에 종료됩니다 (0이 아닌 종료 코드 반환). 이 경우 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

명령이 실패하면 전체 스크립트가 실패하고 $?로 확인할 수있는 종료 상태가 반환됩니다 . . 스크립트가 매우 길거나 많은 것을 구축하는 경우 모든 곳에서 반환 상태 확인을 추가하면 매우 추악해질 것입니다.


한때 나쁜 SysOps 녀석이 나에게 Three-Fingered Claw 기술을 가르쳤습니다.

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

이러한 기능은 * NIX OS 및 쉘 특징입니다. 스크립트 (bash 또는 기타)의 시작 부분에 try()문장과 코드를 넣으십시오.

설명

( 날아 다니는 양 코멘트를 기반으로 함 ).

  • yell: 스크립트 이름과 모든 인수를 다음에 인쇄합니다 stderr.
    • $0 스크립트의 경로입니다.
    • $* are all arguments.
    • >&2 means > redirect stdout to & pipe 2. pipe 1 would be stdout itself.
  • die does the same as yell, but exits with a non-0 exit status, which means “fail”.
  • try uses the || (boolean OR), which only evaluates the right side if the left one failed.

If you will invoke the script with source, you can use return <x> where <x> will be the script exit status (use a non-zero value for error or false). But if you invoke an executable script (i.e., directly with its filename), the return statement will result in a complain (error message "return: can only `return' from a function or sourced script").

If exit <x> is used instead, when the script is invoked with source, it will result in exiting the shell that started the script, but an executable script will just terminate, as expected.

To handle either case in the same script, you can use

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

This will handle whichever invocation may be suitable. That is assuming you will use this statement at the script's top level. I would advise against directly exiting the script from within a function.

Note: <x> is supposed to be just a number.


I often include a function called run() to handle errors. Every call I want to make is passed to this function so the entire script exits when a failure is hit. The advantage of this over the set -e solution is that the script doesn't exit silently when a line fails, and can tell you what the problem is. In the following example, the 3rd line is not executed because the script exits at the call to 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"

Instead of if construct, you can leverage the short-circuit evaluation:

#!/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]

Note the pair of parentheses which is necessary because of priority of alternation operator. $? is a special variable set to exit code of most recently called command.


I have the same question but cannot ask it because it would be a duplicate.

The accepted answer, using exit, does not work when the script is a bit more complicated. If you use a background process to check for the condition, exit only exits that process, as it runs in a sub-shell. To kill the script, you have to explicitly kill it (at least that is the only way I know).

Here is a little script on how to do it:

#!/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

This is a better answer but still incomplete a I really don't know how to get rid of the boom part.

참고URL : https://stackoverflow.com/questions/1378274/in-a-bash-script-how-can-i-exit-the-entire-script-if-a-certain-condition-occurs

반응형