답변:
set -e
부속 명령 또는 파이프 라인이 0이 아닌 상태를 리턴하면 쉘이 종료됩니다.
면접관이 찾고 있던 대답은 다음과 같습니다.
init.d 스크립트를 생성 할 때 "set -e"를 사용하는 것은 위험합니다 :
에서 http://www.debian.org/doc/debian-policy/ch-opersys.html 9.3.2 -
init.d 스크립트에서 set -e를 사용하도록주의하십시오. 올바른 init.d 스크립트를 작성하려면 데몬이 init.d 스크립트를 중단하지 않고 이미 실행 중이거나 이미 중지 된 경우 다양한 오류 종료 상태를 승인해야하며 일반적인 init.d 함수 라이브러리는 set -e를 사용하여 호출하기에 안전하지 않습니다. init.d 스크립트의 경우 종종 set -e를 사용하지 않고 대신 각 명령의 결과를 개별적으로 확인하는 것이 더 쉽습니다.
이는 서버 레벨 스크립팅 및 자동화에 대한 실무 지식을 측정하기 때문에 면접관 관점에서 유효한 질문입니다.
보낸 사람 bash(1)
:
-e Exit immediately if a pipeline (which may consist of a
single simple command), a subshell command enclosed in
parentheses, or one of the commands executed as part of
a command list enclosed by braces (see SHELL GRAMMAR
above) exits with a non-zero status. The shell does not
exit if the command that fails is part of the command
list immediately following a while or until keyword,
part of the test following the if or elif reserved
words, part of any command executed in a && or ││ list
except the command following the final && or ││, any
command in a pipeline but the last, or if the command’s
return value is being inverted with !. A trap on ERR,
if set, is executed before the shell exits. This option
applies to the shell environment and each subshell envi-
ronment separately (see COMMAND EXECUTION ENVIRONMENT
above), and may cause subshells to exit before executing
all the commands in the subshell.
불행히도 "스크립트의 나머지 부분은 실행되지 않을 것"또는 "아마도 실제 문제를 숨길 수 있습니다"를 제외하고 왜 위험한지 생각할만큼 창의적이지 않습니다.
set
! 나는 항상에 끝납니다 builtin(1)
. 감사.
set
가 있음을 어떻게 알 수 있습니까 man 1 bash
?? 어떻게 매뉴얼 페이지에서 키워드에 -e
대한 옵션 을 찾을 수 set
있을까요? 당신은 캔트 /-e
검색
help set
주목해야한다 set -e
스크립트의 다양한 섹션을 위해 켜거나 끌 수 있습니다. 전체 스크립트 실행을 위해 켜져 있지 않아도됩니다. 조건부로 활성화 할 수도 있습니다. 즉, 내 자신의 오류 처리를 수행하거나 사용하지 않으므로 사용하지 않습니다.
some code
set -e # same as set -o errexit
more code # exit on non-zero status
set +e # same as set +o errexit
more code # no exit on non-zero status
또한 특정 상황에서 trap
어떻게 set -e
작동 하는지 설명하는 명령 의 Bash 매뉴얼 페이지 섹션에서 주목할 만하다 .
실패한 명령이 while 또는 until 키워드 바로 다음에 오는 명령 목록의 일부이거나, if 문의 테스트 부분, && 또는 ⎪⎪ 목록에서 실행 된 명령의 일부이거나, 명령의 경우에는 ERR 트랩이 실행되지 않습니다. !를 통해 반환 값이 반전됩니다. 이것은 errexit 옵션이 준수하는 것과 동일한 조건입니다.
따라서 0이 아닌 상태가 종료되지 않는 조건이 있습니다.
나는 위험에 처 set -e
했을 때와 그것이 맞지 않을 때 어떤 잘못된 가정 하에서 잘못 이해하고있을 때 위험을 이해하지 못한다고 생각합니다 .
BashFAQ / 105 도 참조하십시오. -e (또는 set -o errexit 또는 trap ERR)를 설정하지 않은 이유는 무엇입니까?
이것은 면접을위한 퀴즈입니다. 질문은 현재 직원이 작성했을 수 있으며 잘못되었을 수 있습니다. 이것은 반드시 나쁘지는 않으며, 모든 사람이 실수를 저지르고 인터뷰 질문은 종종 검토없이 어두운 구석에 앉아 인터뷰 중 나옵니다.
'set -e'가 우리가 "위험한"것으로 간주하지 않는 것은 전적으로 가능합니다. 그러나이 질문의 저자는 자신의 무지 나 편견 때문에 'set-e'가 위험하다고 잘못 생각할 수 있습니다. 어쩌면 그들은 버그가 많은 쉘 스크립트를 작성했고, 끔찍하게 폭탄을 터뜨 렸으며, 실제로 올바른 오류 검사를 작성하지 않으면 'set -e'가 책임이 있다고 생각했습니다.
지난 2 년간 40 번의 면접에 참여한 적이 있으며, 면접관은 때때로 잘못된 질문을하거나 잘못된 답변을합니다.
아니면 어리석은 질문이지만 완전히 예기치 않은 것은 아닙니다.
또는 이것은 좋은 설명입니다 : http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg473314.html
set -e
스크립트에서 bash가 0이 아닌 리턴 값을 리턴 할 때마다 종료하도록 지시합니다.
나는 당신이 무언가에 대한 권한을 열지 않고 다시 제한하기 전에 스크립트가 죽는 것이 어떻게 귀찮고 버그가 있는지 위험에 대해 확신하지 못하는 것을 알 수있었습니다.
set -e
, 실제로는 스크립트에서 오류 확인을 무시하는 게으름에 대해 말합니다 ... 그래서이 고용주에게도 명심하십시오. 많은, 그들의 스크립트가 어떻게 생겼는지, 필연적으로 유지해야 할 것입니다 ...
set -e
특정 조건을 제외하고 0이 아닌 종료 코드가 발견되면 스크립트를 종료합니다. 몇 마디로 사용의 위험성을 요약하면 사람들이 생각하는대로 행동하지 않습니다.
제 생각에는 호환성 목적으로 만 존재하는 위험한 핵으로 간주해야합니다. 이 set -e
문장은 오류 코드를 사용하는 언어에서 예외와 같은 제어 흐름을 사용하는 언어로 쉘을 바꾸지 않고 단지 그 행동을 모방하려는 시도를 잘못합니다.
Greg Wooledge는 다음과 같은 위험에 대해 많은 의견을 가지고 있습니다 set -e
.
set -e
)두 번째 링크에는의 직관적이지 않고 예측할 수없는 동작에 대한 다양한 예가 set -e
있습니다.
직관적이지 않은 동작의 일부 예 set -e
(위의 wiki 링크에서 가져온 것) :
세트 -e x = 0 x ++하자 에코 "x는 $ x"위의
let x++
결과는 let
키워드에 의해 잘못된 값으로 취급되고 0이 아닌 종료 코드로 바뀌는 0을 리턴 하므로 쉘 스크립트가 조기에 종료 됩니다. set -e
이를 확인하고 스크립트를 자동으로 종료합니다.세트 -e [-d / opt / foo] && echo "경고 : foo가 이미 설치되어 있습니다. 덮어 씁니다." > & 2 echo "foo 설치 중 ..."
위의 내용은 예상대로 작동 /opt/foo
하며 이미 존재 하는 경우 경고를 인쇄합니다 .
세트 -e check_previous_install () { [-d / opt / foo] && echo "경고 : foo가 이미 설치되어 있습니다. 덮어 씁니다." > & 2 } check_previous_install echo "foo 설치 중 ..."
위의 내용은 단일 라인이 함수로 리팩토링되었다는 유일한 차이점에도 불구하고 /opt/foo
존재하지 않으면 종료됩니다 . 원래 작동했다는 사실이 set -e
의 행동에 대한 특별한 예외이기 때문 입니다. a && b
0이 아닌 값을 반환 하면 로 무시됩니다 set -e
. 그러나 이제는 함수이므로 함수의 종료 코드는 해당 명령의 종료 코드와 동일하며 0이 아닌 값을 반환하는 함수는 자동으로 스크립트를 종료합니다.
세트 -e IFS = $ '\ n'읽기 -d ''-r -a config_vars <구성
위의 내용은 config_vars
파일 에서 배열 을 읽습니다 config
. 작성자가 의도 한대로 config
누락 된 경우 오류와 함께 종료됩니다 . 저자가 의도 config
하지 않은 것처럼 , 개행으로 끝나지 않으면 자동으로 종료됩니다 . set -e
여기에서 사용되지 않은 경우 config_vars
파일이 줄 바꿈으로 끝나는 지 여부에 관계없이 파일의 모든 줄을 포함합니다.
Sublime Text (및 개행을 잘못 처리하는 다른 텍스트 편집기) 사용자는주의하십시오.
세트 -e should_audit_user () { 로컬 그룹 그룹 = "$ (그룹"$ 1 ")" $ groups의 그룹; 하다 [ "$ group"= audit] 인 경우; 그런 다음 0을 반환합니다. fi 끝난 1을 반환 } should_audit_user "$ user"이면; 그때 로거 'Blah' fi
여기서 저자는 어떤 이유로 사용자 $user
가 존재하지 않으면 groups
명령이 실패하고 사용자가 감사 하지 않은 일부 작업을 수행하도록하는 대신 스크립트가 종료 될 것으로 예상 할 수 있습니다 . 그러나이 경우 set -e
종료는 적용되지 않습니다. $user
어떤 이유로 스크립트를 종료하지 않고 찾을 수없는 경우 , should_audit_user
함수는 마치 set -e
유효하지 않은 것처럼 잘못된 데이터를 반환 합니다.
이것은 if
명령문 의 조건 부분에서 호출 된 함수에 관계없이, 얼마나 깊이 중첩되어 있든지, 정의 된 위치에 관계없이 set -e
다시 실행하더라도 상관없이 적용 됩니다. if
어느 시점에서나 사용 set -e
하면 조건 블록이 완전히 실행될 때까지의 효과가 완전히 비활성화 됩니다. 작성자가이 함정을 인식하지 못하거나 함수를 호출 할 수있는 모든 가능한 상황에서 전체 호출 스택을 알지 못하면 버그가있는 코드를 작성하고 제공되는 잘못된 보안 감각은 set -e
적어도 부분적으로 비난.
저자가이 함정을 완전히 알고 있더라도 해결 방법은 코드를 사용하지 않고 코드를 작성하는 것과 같은 방식으로 코드를 작성하는 것입니다 set -e
. 저자는 set -e
효과가없는 것처럼 수동 오류 처리 코드를 작성해야 할 뿐만 아니라 존재하는 것으로 set -e
인해 필요하지 않다고 생각하게 만들 수도 있습니다.
몇 가지 추가 단점 set -e
:
let x++
위와 같은 예 에서는 그렇지 않습니다. 스크립트가 예기치 않게 종료되면 일반적으로 자동으로 실행되므로 디버깅에 방해가됩니다. 스크립트가 죽지 않고 예상 한 경우 (이전 글 머리표 참조) 더 미묘하고 교묘 한 버그가 있습니다.if
조건 글 머리 기호를 다시 참조하십시오 .set -e
에서 해당 버전간에 조정 된 동작으로 인해 다르게 작동하는 스크립트를 실수로 작성할 수 있습니다.set -e
논쟁의 여지가있는 문제이며, 어떤 사람들은 그 문제에 대한 주변의 문제를 알고 있지만, 어떤 사람들은 함정을 잘 알고있는 동안 돌보는 것을 권장합니다. set -e
모든 스크립트에서 오류 조건에 대한 포괄적 인 것으로 추천 하는 많은 쉘 스크립팅 초보자가 있지만 실제로는 그렇게 작동하지 않습니다.
set -e
교육을 대신 할 수 없습니다.
나는 당신이 더 이상 스크립트의 흐름을 제어하지 않기 때문에 위험하다고 말합니다. 스크립트가 호출하는 명령이 0이 아닌 값을 반환하는 한 스크립트를 종료 할 수 있습니다. 따라서 구성 요소의 동작이나 출력을 변경하는 작업을 수행하면 주 스크립트를 종료 할 수 있습니다. 스타일 문제 일 수 있지만 결과는 확실합니다. 주 스크립트가 플래그를 설정해야하는데 초기에 종료되지 않았기 때문에 어떻게해야합니까? 플래그가 있어야한다고 가정하거나 예기치 않은 기본값 또는 이전 값으로 작업하면 시스템의 나머지 부분에 오류가 발생합니다.