Programing

bash 스크립트에서 set -e는 무엇을 의미합니까?

lottogame 2020. 10. 3. 09:44
반응형

bash 스크립트에서 set -e는 무엇을 의미합니까?


Debian 아카이브 (.deb) 파일에서 패키지를 풀기 전에 스크립트가 실행하는 preinst 파일 의 내용을 연구 중 입니다.

스크립트에는 다음 코드가 있습니다.

#!/bin/bash
set -e
# Automatically added by dh_installinit
if [ "$1" = install ]; then
   if [ -d /usr/share/MyApplicationName ]; then
     echo "MyApplicationName is just installed"
     return 1
   fi
   rm -Rf $HOME/.config/nautilus-actions/nautilus-actions.conf
   rm -Rf $HOME/.local/share/file-manager/actions/*
fi
# End automatically added section

내 첫 번째 쿼리는 라인에 관한 것입니다.

set -e

나머지 스크립트는 매우 간단하다고 생각합니다. Debian / Ubuntu 패키지 관리자가 설치 작업을 실행 중인지 확인합니다. 그렇다면 내 응용 프로그램이 시스템에 방금 설치되었는지 확인합니다. 이 경우 스크립트는 "MyApplicationName이 방금 설치되었습니다"라는 메시지를 인쇄 하고 종료합니다 ( return 1이는 "오류"로 끝나지 않습니까?).

사용자가 Debian / Ubuntu 패키지 시스템에 내 패키지를 설치하도록 요청하는 경우 스크립트는 두 개의 디렉토리도 삭제합니다.

이것이 맞습니까 아니면 내가 뭔가를 놓치고 있습니까?


에서 help set:

  -e  Exit immediately if a command exits with a non-zero status.

그러나 일부 (bash FAQ 및 irc freenode #bash FAQ 작성자)는 나쁜 습관으로 간주합니다. 다음을 사용하는 것이 좋습니다.

trap 'do_something' ERR

do_something오류 발생시 기능 을 실행 합니다.

http://mywiki.wooledge.org/BashFAQ/105 참조


set -e명령이나 파이프 라인에 오류가있는 경우 스크립트 실행을 중지합니다. 이는 스크립트의 오류를 무시하는 기본 셸 동작과 반대입니다. help set이 내장 명령에 대한 문서를 보려면 터미널을 입력 하십시오.


당으로 배쉬 - set 내부의 설명서, 경우 -e/이 errexit설정되고, 쉘 종료 즉시 만약 파이프 라인 단일로 구성된 간단한 명령 , 목록 또는 복합 명령 반환이 아닌 제로 상태입니다.

기본적으로 파이프 라인의 종료 상태는 pipefail옵션이 활성화되어 있지 않으면 (기본적으로 비활성화되어 있음) 파이프 라인에서 마지막 명령의 종료 상태입니다 .

그렇다면 파이프 라인의 반환 상태는 마지막 (가장 오른쪽) 명령이 0이 아닌 상태로 종료하거나 모든 명령이 성공적으로 종료되면 0입니다.

종료시 무언가를 실행하려면 다음과 같이 정의 해보십시오 trap.

trap onexit EXIT

여기서 onexit같은 그 이하 간단한 인쇄되고, 출구에 뭔가를 할 수있는 함수입니다 스택 추적 :

onexit(){ while caller $((n++)); do :; done; }

비슷한 옵션이 -E/errtrace 있는 것 ERR에 트랩 대신에, 예를 들면 :

trap onerr ERR

제로 상태 예 :

$ true; echo $?
0

0이 아닌 상태 예 :

$ false; echo $?
1

부정 상태의 예 :

$ ! false; echo $?
0
$ false || true; echo $?
0

pipefail비활성화 된 상태에서 테스트 :

$ bash -c 'set +o pipefail -e; true | true | true; echo success'; echo $?
success
0
$ bash -c 'set +o pipefail -e; false | false | true; echo success'; echo $?
success
0
$ bash -c 'set +o pipefail -e; true | true | false; echo success'; echo $?
1

pipefail활성화 된 상태에서 테스트 :

$ bash -c 'set -o pipefail -e; true | false | true; echo success'; echo $?
1

인터넷 검색 중에이 질문을 발견하여 .NET Framework로 인해 중단 된 스크립트의 종료 상태가 무엇인지 알아 내려고했습니다 set -e. 대답은 분명하지 않았습니다. 따라서이 대답. 기본적으로 set -e명령 (예 : 쉘 스크립트)의 실행을 중단하고 실패한 명령의 종료 상태 코드 (예 : 외부 스크립트가 아닌 내부 스크립트)를 반환합니다 .

For example, suppose I have the a shell script outer-test.sh:

#!/bin/sh
set -e
./inner-test.sh
exit 62;

The code for inner-test.sh is:

#!/bin/sh
exit 26;

When I run outer-script.sh from the command line my outer script terminates with the exit code of the inner script:

$ ./outer-test.sh
$ echo $?
26

I believe the intention is for the script in question to fail fast.

To test this yourself, simply type set -e at a bash prompt. Now, try running ls. You'll get a directory listing. Now, type lsd. That command is not recognized and will return an error code, and so your bash prompt will close (due to set -e).

Now, to understand this in the context of a 'script', use this simple script:

#!/bin/bash 
# set -e

lsd 

ls

If you run it as is, you'll get the directory listing from the ls on the last line. If you uncomment the set -e and run again, you won't see the directory listing as bash stops processing once it encounters the error from lsd.


Script 1: without setting -e
#!/bin/bash
decho "hi"
echo "hello"
This will throw error in decho and program continuous to next line

Script 2: With setting -e
#!/bin/bash
set -e
decho "hi" 
echo "hello"
# Up to decho "hi" shell will process and program exit, it will not proceed further

This is an old question, but none of the answers here discuss the use of set -e aka set -o errexit in Debian package handling scripts. The use of this option is mandatory in these scripts, per Debian policy; the intent is apparently to avoid any possibility of an unhandled error condition.

What this means in practice is that you have to understand under what conditions the commands you run could return an error, and handle each of those errors explicitly.

Common gotchas are e.g. diff (returns an error when there is a difference) and grep (returns an error when there is no match). You can avoid the errors with explicit handling:

diff this that ||
  echo "$0: there was a difference" >&2
grep cat food ||
  echo "$0: no cat in the food" >&2

(Notice also how we take care to include the current script's name in the message, and writing diagnostic messages to standard error instead of standard output.)

If no explicit handling is really necessary or useful, explicitly do nothing:

diff this that || true
grep cat food || :

(The use of the shell's : no-op command is slightly obscure, but fairly commonly seen.)

Just to reiterate,

something || other

is shorthand for

if something; then
    : nothing
else
    other
fi

i.e. we explicitly say other should be run if and only if something fails. The longhand if (and other shell flow control statements like while, until) is also a valid way to handle an error (indeed, if it weren't, shell scripts with set -e could never contain flow control statements!)

And also, just to be explicit, in the absence of a handler like this, set -e would cause the entire script to immediately fail with an error if diff found a difference, or if grep didn't find a match.

On the other hand, some commands don't produce an error exit status when you'd want them to. Commonly problematic commands are find (exit status does not reflect whether files were actually found) and sed (exit status won't reveal whether the script received any input or actually performed any commands successfully). A simple guard in some scenarios is to pipe to a command which does scream if there is no output:

find things | grep .
sed -e 's/o/me/' stuff | grep ^

It should be noted that the exit status of a pipeline is the exit status of the last command in that pipeline. So the above commands actually completely mask the status of find and sed, and only tell you whether grep finally succeeded.

(Bash, of course, has set -o pipefail; but Debian package scripts cannot use Bash features. The policy firmly dictates the use of POSIX sh for these scripts, though this was not always the case.)

In many situations, this is something to separately watch out for when coding defensively. Sometimes you have to e.g. go through a temporary file so you can see whether the command which produced that output finished successfully, even when idiom and convenience would otherwise direct you to use a shell pipeline.

참고URL : https://stackoverflow.com/questions/19622198/what-does-set-e-mean-in-a-bash-script

반응형