당신을 위해 그림을 그려 보겠습니다. 사용자 생성, 패키지 설치/업데이트 등과 같은 작업을 수행하기 위해 원격으로 명령을 실행하는 일부 배포 스크립트 또는 빌드 스크립트 등을 작성하므로 추가 --gecos ''
하는 것을 잊었거나 adduser
추가하지 않을 수 있다는 걱정이 될 수 있습니다. DEBIAN_FRONTEND=noninteractive
귀하의 모든 아파트나 귀하가 알지 못하는 물건에 대해 이 정보를 제공하십시오. 오늘날 이러한 스크립트는 비대화형인 경향이 있습니다. 프롬프트를 받고 싶지 않으며 어떤 이유로 프롬프트가 발생하면 전체 작업이 실패하기를 원합니다. 그러나 이 상황에서 bash를 사용하면 0이 아닌 오류 코드로 실패하는 대신(나에게도 set -e
) 최악의 작업을 수행한다는 것을 알 수 있습니다. 중단하고 0을 반환합니다. 이는 호출자가 스크립트가 올바르게 완료되지 않았지만 실제로 중단되었음을 알 수 있는 방법이 없음을 의미합니다.
다음은 문제를 쉽게 설명하고 해결하는 어리석은 예입니다. 이 스크립트 주변에서 많은 일이 일어나는 것을 상상할 수 있습니다. 어쩌면 이 코드는 실제로 ssh를 사용하여 원격으로 실행되고 일부 패키지는 etc 대신 설치되며 read line
이 블록 이후에는 모든 코드가 성공적으로 실행될 것으로 예상됩니다.
set -e
# Do stuf...
/bin/bash <<SH
echo gonna try to be interactive
read line #tries to read a line from "user"
echo you wont see me #Will not be executed as Bash will halt execution on previous failing line, this could be vital bit of code to execute, but it's now silently skipped
SH
echo return value $?
#I want to stop here if the above bit of bash failed because some code tried to get user input
산출
gonna try to be interactive
return value 0
bin/sh
bash 대신 사용하면 다른 동작이 발생한다는 것을 알았습니다 . 읽는 즉시 자동으로 실행을 중지하지 않고 0을 반환합니다. 실제로 기본적으로 계속 진행되므로 set -e
실제로 반환 값 1을 제공하도록 명시적으로 "단락"해야 합니다. 하지만 bash가 제대로 작동하도록 하는 방법이 있나요?
답변1
다른 명령과 마찬가지로 반환 상태를 명시적으로 확인 read
하거나 set -e
.set -e
만병통치약은 아니다하지만 전혀 사용하지 않는 것보다 낫습니다.
어떤 언어 기능도 의미는 있지만 원하는 작업을 수행하지 않는 코드로부터 사용자를 안정적으로 보호할 수 없습니다. 컴퓨터는 평소와 같이 사용자가 원하는 작업이 아니라 사용자가 지시한 작업을 수행하기 때문에 코드에서 오류 신호를 보내지 않습니다.
/bin/bash <<SH
Bash의 표준 입력은 여기에 있는 문서의 내용을 포함하는 파일(실행되는 쉘에 따라 임시 파일 또는 파이프)에 연결됩니다.
read line #tries to read a line from "user"
아니요, "사용자로부터 한 줄을 읽지" 않습니다. 표준 입력에서 한 줄을 읽습니다. 여기 문서가 있습니다. 효과는 쉘이 스크립트를 구문 분석하는 방법에 따라 달라집니다. 이것이 교체 /bin/bash
로 /bin/sh
동작을 변경하는 이유입니다. 이 특정 스크립트와 이 특정 버전의 bash의 경우 bash는 한 번에 한 줄만 스크립트를 읽습니다. 따라서 한 줄을 읽으라고 지시하면 해당 작업을 수행하고 를 line
설정합니다 echo you wont see me #Will not be executed as Bash will halt execution on previous failing line, this could be vital bit of code to execute, but it's now silently skipped
. 명령이 성공적으로 완료되면 read
bash는 다음 줄을 실행합니다. 스크립트의 끝에 도달했으므로 마지막 명령의 상태인 0을 반환합니다.
무슨 일이 일어나고 있는지 확인하려면 다른 코드 줄을 추가하세요.
set -e
# Do stuf...
/bin/bash <<'SH'
echo gonna try to be interactive
read line #tries to read a line from "user"
echo you wont see me #Will not be executed as Bash will halt execution on previous failing line, this could be vital bit of code to execute, but it's now silently skipped
echo "Previous command='$_'; status=$?; line='$line'"
SH
echo return value $?
산출:
gonna try to be interactive
Previous command='line'; status=0; line='echo you wont see me #Will not be executed as Bash will halt execution on previous failing line, this could be vital bit of code to execute, but it's now silently skipped'
return value 0
명령이 올바르지 않습니다. 라인이 실패하지 않았고 bash가 실행을 중지하지도 않았습니다. 이 줄은 bash에게 데이터로 읽도록 지시했기 때문에 건너뛰었습니다.
대시는 스크립트를 실행하기 전에 전체 스크립트를 읽기 때문에 다른 동작을 관찰합니다. 예를 들어, 코드가 함수 내부에 있으면 bash에서도 이를 관찰할 수 있습니다.
하위 쉘이 상위 쉘의 표준 입력을 읽도록 하려면 하위 쉘의 표준 입력을 리디렉션하지 않거나 상위 쉘의 표준 입력을 다른 파일 설명자에서 사용할 수 있도록 설정하지 마십시오.
사용자 생성, 패키지 설치/업데이트 등의 작업을 수행하기 위해 원격으로 명령을 실행하는 배포 스크립트나 빌드 스크립트 등을 작성하므로 adduser에 --gecos ''를 추가하는 것을 잊어버릴 수도 있다는 걱정이 들 수도 있습니다. no DEBIAN_FRONTEND=모든 아파트 또는 귀하가 알지도 못하는 것에 대해 비대화형입니다. 오늘날 이러한 스크립트는 비대화형인 경향이 있습니다. 프롬프트를 받고 싶지 않으며 어떤 이유로 프롬프트가 발생하면 전체 작업이 실패하기를 원합니다.
이것은 완전히 다른 질문입니다. 배포 스크립트의 표준 입력이 에 연결되어 있는지 확인하세요 /dev/null
. 이렇게 하면 표준 입력에서 읽으려고 하면 읽기가 실패합니다.
배포자가 잘못된 위치에서 읽으려고 시도하거나 읽기 실패에 올바르게 반응하지 않는 경우 이는 환경 준비로 수정할 수 없는 배포자의 버그입니다.
¹코드가 사양을 준수하는지 증명할 방법은 없지만 그렇게 하고 싶다면 스크립팅 언어를 사용하지 않을 것입니다.