셸에서 0이 참이지만 거짓이 1 인 이유는 무엇입니까?


122
false; echo $?

위의 출력 1은 내가 아는 다른 모든 프로그래밍 언어와 모순되는.

그 이유는 무엇입니까?


3
그것은 또한 유닉스 방식과 일치합니다 ... 성공에 대해 아무것도 반환하지 마십시오.
압둘라 Jibaly

21
종료 상태가 부울이 아니기 때문입니다. 그렇게 간단합니다.
Jens

2
false다른 프로그래밍 언어와 마찬가지로 부울이 아님 을 명심하십시오 . 그것은 단지에있는 프로그램입니다 /bin/false( /usr/bin/false항상 비슷한 오류 종료 코드 1을 반환하는 의미가있어 Mac에서) true. 따라서 여기에 캐스팅하는 것과 같은 것은 없습니다. 종료 코드에 관한 것입니다.
Mikhail Vasin

쉘은 운영 체제에 대한 (사용자) 인터페이스입니다. 유닉스 등의 프로그램 은 답변에 주어진 이유 (두 개 이상의 실패 이유를 전달할 수있는 능력) 때문에 0으로 종료하는 규칙을 따릅니다 . 쉘은이 규칙을 유지하기 때문에 if myprog; then echo OK; fi쉽고 직관적 인 구조를 만들 수 있습니다. 그렇지 않으면 프로그램의 성공을 위해 모든 테스트를 뒤집어 야합니다!
Peter-Monica 복원

답변:


93

관습이지만 생각할 때 특히 유용합니다. 일반적으로 프로그램이 성공하면 그만 알면됩니다. 그러나 실패하는 경우 실패에 대한 모든 종류의 정보 (발생 원인, 해결 방법 등)를 알아야 할 수 있습니다. 0은 '성공'을 의미하고 0이 아닌 평균 실패는 성공 여부를 매우 쉽게 확인할 수 있습니다. 을 클릭하고 원하는 경우 특정 오류를 조사하여 자세한 내용을 확인하십시오. 많은 API와 프레임 워크에는 비슷한 규칙이 있습니다. 성공한 함수는 0을 반환하고 실패한 함수는 특정 실패 사례를 설명하는 오류 코드를 반환합니다.


6
이 대답을 이해하지만 bool에서 int 로의 변환이 반전되는 이유를 여전히 알 수 없습니다. true를 반환하면 오류가 없음을 의미하고 false를 반환하면 오류가 발생했음을 의미하는 "반환 부울 ​​규칙"이 있습니까 (더 잘 알려진 "정수 = 오류 코드 규칙"과 같이)?
Guillaume86 2011

1
부울에서 정수로의 변환이 있다고 가정하면 실제로 답을 이해하지 못했음을 의미합니다. 0은 성공을 의미하고 1, 2, ..., 255는 모두 다른 실패 시나리오를 유용하게 전달할 수있는 오류 코드입니다. 특정 예는 명령 그룹 이 실패한 xargs방법을 나타 내기 위해 약 127 범위의 다른 오류 코드를 사용하는 것 입니다. 수행 할 수있는 변환은 0이 성공에 매핑되는 bool (내 생각에는 true / 1로 표현하고 싶지만 이것은 다른 임의의 규칙 일 뿐임)과 다른 모든 값을 실패로 매핑하는 int to bool입니다.
tripleee

79

Bash는 프로그래밍 (스크립팅) 언어이지만 셸이자 사용자 인터페이스이기도합니다. 0오류 인 경우 프로그램은 한 종류의 오류 만 표시 할 수 있습니다.

그러나 Bash에서 0이 아닌 값은 오류이며 1-255의 숫자를 사용하여 오류를 나타낼 수 있습니다. 이것은 우리가 다양한 종류의 오류를 가질 수 있음을 의미합니다. 1일반적인 오류, 126파일을 실행할 수 없음, 127'명령을 찾을 수 없음'등을 의미합니다 . 다음 은 가장 일반적인 종료 코드 중 일부를 보여주는 특별한 의미 가있는 Bash 종료 코드 목록입니다 .

또한 많은 종류의 성공이 있습니다 (종료 상태는 0). 그러나 성공하면 다음 단계로 진행할 수 있습니다. 결과를 화면에 인쇄하거나 명령을 실행할 수 있습니다.


8
다양한 리턴 코드의 유용성을 보여주는이 실용적인 답변은 다른 답변의 설교 성보다 낫습니다.
javadba

1
그리고 그것의 재미를 위해, 나는 그들이 나타내는 관습이 1980 년대로 거슬러 올라간다하더라도 아마도 더 열망적인 /usr/include/sysexits.h출구 가치 에 주목할 것입니다. 이 규칙은 bash의 범위 밖에 존재합니다.
ghoti

2
위대하고 간단하며 실용적인 설명. 이것은 맨 위에 있어야합니다.
Rey Leonard Amorato

3
" 0오류 인 경우 프로그램은 한 종류의 오류 만 표시 할 수 있습니다. " 이 진술이 핵심이며이 답변이 맨 위에 있어야하는 이유입니다.
rayryeng

1
@LuisLavaire 정의되지 않은 동작입니다. 실제로 숫자는 잘리는 경향이 있습니다. 그러나 런타임이 경고를 생성하거나 단순히 충돌을 일으킨다면 "더 잘못"된 것은 아닙니다. OS는이 정보를 위해 정확히 1 바이트를 예약했으며 2 바이트 이상을 넣으려고하면 확실히 오류가 발생합니다. 그러나 OS 설계자들은 아마도 첫날 충돌을 겪고 어깨를 으쓱하고 그들이 할 수있는 최선의 방법은 그저 가치를 줄이고 계속 나아가는 것이라고 결정했습니다.
tripleee

30

여기에는 두 가지 관련 문제가 있습니다.

첫째, OP의 질문, 왜 0은 참이지만 거짓은 쉘에서 1입니까? 둘째, 응용 프로그램이 성공하면 0을 반환하고 실패하면 0이 아닌 이유는 무엇입니까?

OP의 질문에 답하려면 두 번째 질문을 이해해야합니다. 이 게시물에 대한 수많은 답변은 이것이 컨벤션이라고 설명했으며이 컨벤션이 제공하는 몇 가지 장점을 나열했습니다. 이러한 장점 중 일부는 아래에 요약되어 있습니다.

응용 프로그램이 성공하면 0을 반환하고 실패하면 0이 아닌 이유는 무엇입니까?

작업을 호출하는 코드는 작업의 종료 상태에 대해 두 가지를 알아야합니다. 작업이 성공적으로 종료 되었습니까? [* 1] 그리고 작업이 성공적으로 종료되지 않은 경우 작업이 성공적으로 종료 된 이유는 무엇입니까? 모든 값을 사용하여 성공을 나타낼 수 있습니다. 그러나 0은 플랫폼간에 이식 가능하기 때문에 다른 숫자보다 편리합니다. 2011 년 8 월 16 일 이 질문 에 대한 xibo의 답변 요약 :

0은 인코딩에 독립적입니다.

32 비트 정수 단어에 one (1)을 저장하려는 경우 첫 번째 질문은 "빅 엔디안 단어 또는 리틀 엔디안 단어?"와 "바이트가 리틀 엔디안 단어를 구성하는 길이?"입니다. ", 0은 항상 동일하게 보입니다.

또한 어떤 사람들은 errno를 어떤 시점에서 char 또는 short로 캐스팅하거나 심지어 float로 캐스팅 할 것으로 예상해야합니다. (int) ((char) ENOLCK)는 char 길이가 8 비트 이상 (UNIX에서 7 비트 ASCII char 시스템을 지원함)이 아닐 때 ENOLCK가 아닌 반면 (int) ((char) 0)은 char의 건축 세부 사항.

0이 성공에 대한 반환 값이라고 결정되면 0이 아닌 값을 실패에 사용하는 것이 좋습니다. 이를 통해 많은 종료 코드 가 작업이 실패한 이유에 대한 질문에 답할 수 있습니다 .

셸에서 0이 참이지만 거짓이 1 인 이유는 무엇입니까?

쉘의 기본적인 사용법 중 하나는 스크립팅을 통해 프로세스를 자동화하는 것입니다. 일반적으로 이것은 작업을 호출 한 다음 작업의 종료 상태에 따라 조건부로 다른 작업을 수행하는 것을 의미합니다. Philippe A. 는이 게시물에 대한 그의 답변에서

일반적으로 bash 및 유닉스 셸에서 반환 값은 부울이 아닙니다. 정수 종료 코드입니다.

그런 다음 이러한 작업의 종료 상태를 부울 값으로 해석해야합니다. 성공 ( 0) 종료 상태를 true 로 매핑하고 0이 아닌 / 실패 종료 상태를 false 로 매핑하는 것이 좋습니다 . 이렇게하면 연결된 쉘 명령을 조건부로 실행할 수 있습니다.

여기에 예가 mkdir deleteme && cd $_ && pwd있습니다. 쉘이 0을 참으로 해석하기 때문에이 명령은 예상대로 편리하게 작동합니다. 쉘이 0을 거짓으로 해석한다면 각 작업에 대해 해석 된 종료 상태를 반전해야합니다.

요컨대, 응용 프로그램이 성공적인 종료 상태에 대해 0을 반환한다는 규칙을 고려할 때 쉘이 0을 거짓으로 해석하는 것은 의미가 없습니다.


[* 1] : 예, 여러 번 작업에서 단순한 성공 메시지 이상을 반환해야하지만 이는이 스레드의 범위를 벗어납니다.

고급 Bash 스크립팅 가이드의 부록 E 를 참조하십시오.


2
안녕하세요, 쉘이 0을 거짓으로 해석하고 0이 아닌 것을 참으로 해석한다면, 그 트릭은 mkdir deleteme && cd _$ && pwd실제로 실패하지 않을 것입니다. 그러나 우리는 그것을로 대체해야 할 것 mkdir deleteme || cd _$ || pwd입니다. 제 생각에는 훨씬 덜 명확합니다. 왜냐하면 우리가 실제로하고 싶은 것은 mkdir deletemeandcd _$andpwd... (여기서“and”는 일반 언어에서 의미를 가짐 )이기 때문 입니다.
Rémi Peyre

1
내 대답에서 다룬 것 같습니다. 하지만 논리를 반전시킬 때 &&연산자를 ||연산자로 바꾸는 것만으로는 충분하지 않습니다 . De Morgan의 법칙을 완전히 적용해야합니다. 참조 : en.wikipedia.org/wiki/De_Morgan%27s_laws
axiopisty

1
또 다른 고려 사항 : 일반적으로 true0에 false해당하고 0이 아닌 것에 해당하는 상태가 자연 스러울 수있는 이유를 최소한 세 가지 봅니다 . 첫째, 내가 무언가를 말하면,“진실을 말한 것”은 내가 말한 거짓말의 수에 따라 달라집니다. 그것은 0이고 내가 (전 세계적으로) 진실을 말했거나 0이 아니고 거짓말을했습니다. 이것은 본질적으로 논리 and가 덧셈의 일반적인 "and"에 대응하기를 원하는 것과 같습니다 (분명히 자연수로 제한 할 때).
Rémi Peyre

1
(이전 주석에서 계속). 두 번째 이유는 하나의 진실이 있지만 진실이 아닌 것은 많다는 것입니다. 따라서에 대한 단독 값 true과에 대한 다른 모든 값을 연결하는 것이 더 편리합니다 false. (이것은 본질적으로 프로그램의 반환 값에 대한 고려 사항과 동일합니다).
Rémi Peyre 2015 년

(이전 주석에서 계속). 세 번째 이유는“A가 사실이라면 사실”이“A가 사실이라면 거짓”과 같고,“A가 거짓이라면 거짓”은“A가 거짓”과 같기 때문입니다. 그래서 true곱셈 1과 같이 행동한다 false곱셈 -1. 이는 -1의 거듭 제곱 true으로서 "짝수"및 false"홀수"로 추가적으로 동작 함을 의미합니다 . 다시 말하지만, 그것은 true제로 가 될 자격이 있습니다 ...
Rémi Peyre

17

제가 이해해야 할 중요한 점은 이것입니다. 일반적으로 bash 및 유닉스 셸에서 반환 값은 부울이 아닙니다. 정수 종료 코드입니다. 따라서 0은 성공을 의미하고 다른 값은 오류를 의미한다는 규칙에 따라 평가해야합니다.

test, [ ]또는 [[ ]]운영자, 배쉬 조건은 종료 코드 0 (의 / 빈 / 진정한 결과)의 경우에는 사실로 평가합니다. 그렇지 않으면 거짓으로 평가됩니다.

문자열은 종료 코드와 다르게 평가됩니다.

if [ 0 ] ; then echo not null ; fi
if [ $(echo 0) ] ; then echo not null ; fi

if [ -z "" ] ; then echo null ; fi

(( ))연산기 참과 거짓으로 1과 0을 해석한다. 그러나이 연산자는 test, [ ]또는 의 완전한 대체물로 사용할 수 없습니다 [[ ]]. 다음은 산술 연산자가 유용한 경우를 보여주는 예입니다.

for (( counter = 0 ; counter < 10 ; counter ++ )) ; do
  if (( counter % 2 )) ; then echo "odd number $counter" ; fi
done

참 / 거짓에 대한 중괄호 대 괄호에 대한 설명에 감사드립니다
javadba

15

0 종료 코드는 성공을 의미하는 규칙입니다. EXIT_SUCCESS 는 거의 모든 최신 시스템에서 0이됩니다.

편집하다:

"테스트 0과 테스트 1이 모두 0 (성공)을 반환하는 이유는 무엇입니까?"

그것은 완전히 다른 질문입니다. 대답은 테스트에 단일 인수를 전달하면 해당 인수가 널 문자열 ( "")이 아닌 한 항상 성공한다는 것입니다. Open Group 문서를 참조하십시오 .


그렇다면 왜 test 0와 모두 test 10 (성공)을 반환합니까?
httpinterpret

5
@httpinterpret, test숫자 값을 테스트하지 않습니다. 해당 문자열이 널 문자열인지 여부를 테스트합니다. man test자세한 내용은.
Carl Norum

12

일반적으로 프로그램은 성공하면 0을, 실패하면 0이 아닌 값을 반환합니다. false편리한 0이 아닌 값이기 때문에 1을 반환하지만 일반적으로 0이 아닌 값은 일종의 실패를 의미하며 많은 프로그램은 다른 실패 모드를 나타 내기 위해 다른 0이 아닌 값을 반환합니다.


2
설명이없는 (또는 명백한 이유) 비참한 투표를하는 사람들은 커뮤니티를 전혀 돕지 않기 때문에 절름발이입니다.
압둘라 Jibaly

1
아니 그것을 용서 ... 그러나 그것은 이다 자신의 2 점을 ... 그리고 @MichaelMrozek에 .. 19.6k로, 그것은 롤 나쁘지 해치지 않을 수 있습니다.
Alex Gray

1
@alexgray 2 년 전의 일입니다. 당시 나는 약 5k를 가지고 있었다. 그리고 나는 담당자에 대한보다 답변을 잘못 무엇인지 더 궁금
마이클 Mrozek


4

이것은 유닉스 초기로 거슬러 올라가는 관습입니다.

규칙에 따라 모든 시스템 호출은 성공하면 0을 반환하고 그렇지 않으면 0이 아닌 값을 반환합니다. 다른 번호를 사용하여 다른 실패 이유를 나타낼 수 있기 때문입니다.

쉘은이 규칙을 따릅니다. 0은 마지막 명령이 성공했음을 의미하고 그렇지 않으면 0이 아닙니다. 마찬가지로 0이 아닌 반환 값은 출력 오류 메시지에 유용합니다. 예 : 1 : "brain dead", 2 : "heartless"등.


이것이 답입니다.
Peter-Monica 복원

3

참 / 거짓을 성공 / 실패와 동일시하려고합니다.

처음에는 미묘하지만 완전히 다른 이분법입니다!

쉘 스크립팅에는 참 / 거짓과 같은 것이 없습니다. 셸 '표현식'은 참 / 거짓으로 해석되지 않습니다. 오히려 쉘 '표현식'은 성공하거나 실패하는 프로세스입니다.

분명히 프로세스는 여러 가지 이유로 실패 할 수 있습니다. 따라서 가능한 오류를 매핑하려면 더 큰 세트 코드가 필요합니다. 양의 정수가 트릭을 수행합니다. 반면에 프로세스가 성공하면해야 할 일을 정확히 수행했음을 의미합니다. 이를 수행하는 방법은 하나뿐이므로 하나의 코드 만 필요합니다. 0은 트릭입니다.

C에서는 프로그램을 만들고 있습니다. 쉘 스크립트에서 우리는 무언가를하기 위해 많은 프로그램을 실행하고 있습니다.

차!


혼란 스럽습니다. 'man ['을 입력합니다. 테스트 유틸리티가 표현식을 평가하고 true로 평가되면 0 (true) 종료 상태를 리턴합니다. 그렇지 않으면 1 (거짓)을 반환합니다. 표현식이 없으면 test도 1 (거짓)을 반환합니다.
cavalcade 2016 년

1

기억하는 좋은 방법은 다음과 같습니다.

  • 반환 코드는 "대답은 무엇입니까?"라고 대답합니다. 참 (또는 기타 결과) 또는 거짓
  • 종료 코드는 "무엇이 문제입니까?"라고 대답합니다. 종료 코드 또는 문제 없음 (0)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.