Linux의 Bash 스크립트에서 set 및 pipefail을 사용하는 방법

0
447
파란색 배경 위에 노트북 화면의 Linux 터미널.
Fatmawati achmad zaenuri/Shutterstock.com

리눅스 set 그리고 pipefail 명령은 Bash 스크립트에서 오류가 발생할 때 발생하는 일을 나타냅니다. 중단해야 하거나 계속해야 하는 것보다 생각해야 할 것이 더 많습니다.

관련된: 셸 스크립팅 초보자 가이드: 기본 사항

Bash 스크립트 및 오류 조건

Bash 쉘 스크립트는 훌륭합니다. 그들은 작성이 빠르고 컴파일이 필요하지 않습니다. 수행해야 하는 반복적이거나 다단계 작업을 편리한 스크립트로 래핑할 수 있습니다. 스크립트는 표준 Linux 유틸리티를 호출할 수 있기 때문에 쉘 언어 자체의 기능에 제한되지 않습니다.

그러나 외부 유틸리티나 프로그램을 호출할 때 문제가 발생할 수 있습니다. 실패하면 외부 유틸리티가 닫히고 반환 코드를 셸로 보내고 터미널에 오류 메시지를 인쇄할 수도 있습니다. 그러나 스크립트는 계속 처리됩니다. 아마도 그것은 당신이 원하는 것이 아닙니다. 스크립트 실행 초기에 오류가 발생하는 경우 스크립트의 나머지 부분이 실행되도록 허용되면 문제가 더 악화될 수 있습니다.

Bash 셸이란 무엇이며 Linux에 왜 중요한가요?

관련된Bash 셸이란 무엇이며 Linux에 왜 중요한가요?

각 외부 프로세스가 완료되면 반환 코드를 확인할 수 있지만 프로세스가 다른 프로세스로 파이프되면 어려워집니다. 반환 코드는 중간에 실패한 프로세스가 아니라 파이프 끝에 있는 프로세스에서 가져온 것입니다. 물론 초기화되지 않은 변수에 액세스하려는 것과 같이 스크립트 내부에서도 오류가 발생할 수 있습니다.

그만큼 set 그리고 pipefile 명령을 사용하면 이와 같은 오류가 발생할 때 어떤 일이 발생하는지 결정할 수 있습니다. 또한 파이프 체인 중간에서 오류가 발생한 경우에도 오류를 감지할 수 있습니다.

사용 방법은 다음과 같습니다.

문제 시연

다음은 간단한 Bash 스크립트입니다. 터미널에 두 줄의 텍스트를 에코합니다. 텍스트를 편집기에 복사하여 “script-1.sh”로 저장하면 이 스크립트를 실행할 수 있습니다.

#!/bin/bash

echo This will happen first 
echo This will happen second

실행 가능하게 하려면 다음을 사용해야 합니다. chmod:

chmod +x script-1.sh

컴퓨터에서 실행하려면 각 스크립트에서 해당 명령을 실행해야 합니다. 스크립트를 실행해 보겠습니다.

./script-1.sh

오류 없이 간단한 스크립트를 실행합니다.

예상대로 두 줄의 텍스트가 터미널 창으로 전송됩니다.

스크립트를 약간 수정해 보겠습니다. 우리는 물을 것이다 ls 존재하지 않는 파일의 세부 정보를 나열합니다. 이것은 실패합니다. 이것을 “script-2.sh”로 저장하고 실행 가능하게 만들었습니다.

#!/bin/bash

echo This will happen first
ls imaginary-filename
echo This will happen second

이 스크립트를 실행하면 다음의 오류 메시지가 표시됩니다. ls .

./script-2.sh

스크립트를 실행하고 실패 조건을 생성합니다.

비록 ls 명령이 실패했지만 스크립트는 계속 실행되었습니다. 그리고 스크립트 실행 중에 오류가 발생하더라도 스크립트에서 쉘로의 리턴 코드는 0으로 성공을 나타냅니다. echo를 사용하여 이것을 확인할 수 있고 $? 쉘로 보낸 마지막 리턴 코드를 보유하는 변수.

echo $?

마지막으로 실행된 스크립트의 반환 코드를 확인합니다.

보고되는 0은 스크립트의 두 번째 에코에서 반환되는 코드입니다. 따라서 이 시나리오에는 두 가지 문제가 있습니다. 첫 번째는 스크립트에 오류가 있었지만 계속 실행되었다는 것입니다. 스크립트의 나머지 부분이 실패한 작업이 실제로 성공한 것으로 예상하거나 의존하는 경우 다른 문제가 발생할 수 있습니다. 그리고 두 번째는 다른 스크립트나 프로세스가 이 스크립트의 성공 또는 실패를 확인해야 하는 경우 잘못된 판독을 얻게 된다는 것입니다.

set -e 옵션

그만큼 set -e (exit) 옵션은 스크립트가 호출하는 프로세스에서 0이 아닌 반환 코드를 생성하는 경우 스크립트가 종료되도록 합니다. 0이 아닌 모든 것은 실패로 간주됩니다.

추가하여 set -e 스크립트 시작에 옵션을 추가하면 동작을 변경할 수 있습니다. “script-3.sh”입니다.

#!/bin/bash 
set -e

echo This will happen first
ls imaginary-filename
echo This will happen second

이 스크립트를 실행하면 다음과 같은 효과를 볼 수 있습니다. set -e.

./script-3.sh
echo $?

오류 조건에서 스크립트를 종료하고 반환 코드를 올바르게 설정합니다.

스크립트가 중지되고 셸로 보내진 반환 코드는 0이 아닌 값입니다.

파이프 실패 처리

배관은 문제를 더 복잡하게 만듭니다. 파이프된 명령 시퀀스에서 나오는 반환 코드는 체인의 마지막 명령에서 나온 반환 코드입니다. 체인 중간에 명령이 실패하면 다시 원점으로 돌아갑니다. 해당 반환 코드는 손실되고 스크립트는 처리를 계속합니다.

다음을 사용하여 서로 다른 반환 코드로 파이프 명령의 효과를 볼 수 있습니다. true 그리고 false 쉘 내장. 이 두 명령은 각각 0 또는 1의 반환 코드를 생성합니다.

true
echo $?
false
echo $?

bash 셸 true 및 false 기본 제공 명령.

파이프하면 false ~ 안으로 true -와 함께 false 실패한 프로세스를 나타냅니다. true의 반환 코드는 0입니다.

false | true
echo $?

거짓을 참으로 연결합니다.

Bash에는 라는 배열 변수가 있습니다. PIPESTATUS그리고 이것은 파이프 체인에 있는 각 프로그램의 모든 반환 코드를 캡처합니다.

false | true | false | true
echo "${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]} ${PIPESTATUS[3]}"

PIPESTATUS를 사용하여 파이프 체인에 있는 모든 프로그램의 반환 코드를 봅니다.

PIPESTATUS 다음 프로그램이 실행될 때까지 반환 코드만 보유하고 어떤 반환 코드가 어떤 프로그램과 함께 가는지 결정하려고 하면 매우 빠르게 지저분해질 수 있습니다.

여기는 set -o (옵션) 및 pipefail 들어오세요. “script-4.sh”입니다. 이것은 존재하지 않는 파일의 내용을 다음으로 파이프하려고 시도합니다. wc.

#!/bin/bash 
set -e

echo This will happen first
cat script-99.sh | wc -l
echo This will happen second

예상대로 실패합니다.

./script-4.sh
echo $?

파이프 체인에서 오류가 있는 스크립트 실행.

첫 번째 0은 다음의 출력입니다. wc, 누락된 파일에 대한 행을 읽지 않았음을 알려줍니다. 두 번째 0은 두 번째의 반환 코드입니다. echo 명령.

우리는 -o pipefail “script-5.sh”로 저장하고 실행 가능하게 만드십시오.

#!/bin/bash 
set -eo pipefail

echo This will happen first
cat script-99.sh | wc -l
echo This will happen second

그것을 실행하고 리턴 코드를 확인합시다.

./script-5.sh
echo $?

파이프 체인의 오류를 트래핑하고 반환 코드를 올바르게 설정하는 스크립트를 실행합니다.

스크립트가 중지되고 두 번째 echo 명령이 실행되지 않습니다. 셸로 보낸 반환 코드는 1이며 올바르게 실패를 나타냅니다.

관련된: Linux에서 Echo 명령을 사용하는 방법

초기화되지 않은 변수 잡기

초기화되지 않은 변수는 실제 스크립트에서 찾기 어려울 수 있습니다. 우리가 시도하면 echo 초기화되지 않은 변수의 값, echo 단순히 빈 줄을 인쇄합니다. 오류 메시지를 표시하지 않습니다. 나머지 스크립트는 계속 실행됩니다.

이것은 script-6.sh입니다.

#!/bin/bash 
set -eo pipefail

echo "$notset" 
echo "Another echo command"

우리는 그것을 실행하고 행동을 관찰할 것입니다.

./script-6.sh
echo $?

초기화되지 않은 변수를 캡처하지 않는 스크립트를 실행합니다.

스크립트는 초기화되지 않은 변수를 단계별로 실행하고 계속 실행합니다. 반환 코드는 0입니다. 매우 길고 복잡한 스크립트에서 이와 같은 오류를 찾는 것은 매우 어려울 수 있습니다.

Bash에서 변수로 작업하는 방법

관련된Bash에서 변수로 작업하는 방법

우리는 다음을 사용하여 이러한 유형의 오류를 잡을 수 있습니다. set -u (설정되지 않음) 옵션. 이를 스크립트 상단에 있는 세트 옵션 모음에 추가하고 “script-7.sh”로 저장하고 실행 가능하게 만들 것입니다.

#!/bin/bash 

set -eou pipefail

echo "$notset" 

echo "Another echo command"

스크립트를 실행해 보겠습니다.

./script-7.sh
echo $?

초기화되지 않은 변수를 캡처하는 스크립트를 실행합니다.

초기화되지 않은 변수가 감지되고 스크립트가 중지되고 반환 코드가 1로 설정됩니다.

그만큼 -u (설정되지 않음) 옵션이 충분히 지능적입니다. 발동되지 않도록 초기화되지 않은 변수와 합법적으로 상호 작용할 수 있는 상황에 의해.

“script-8.sh”에서 스크립트는 변수가 New_Var 초기화 여부입니다. 스크립트가 여기서 멈추는 것을 원하지 않습니다. 실제 스크립트에서는 추가 처리를 수행하고 상황을 직접 처리해야 합니다.

다음을 추가했습니다. -u 옵션으로 set 문의 옵션. 그만큼 -o pipefail 옵션은 마지막에 와야 합니다.

#!/bin/bash 

set -euo pipefail

if [ -z "${New_Var:-}" ]; then 

echo "New_Var has no value assigned to it." 

fi

“script-9.sh”에서는 초기화되지 않은 변수를 테스트하고 초기화되지 않은 경우 기본값을 대신 제공합니다.

#!/bin/bash
set -euo pipefail

default_value=484
Value=${New_Var:-$default_value}
echo "New_Var=$Value"

스크립트는 완료될 때까지 실행할 수 있습니다.

./script-8.sh
./script-9.sh

초기화되지 않은 변수가 내부적으로 처리되고 -u 옵션이 트리거되지 않는 두 개의 스크립트를 실행합니다.

도끼로 봉인

사용할 수 있는 또 다른 편리한 옵션은 set -x (실행 및 인쇄) 옵션. 스크립트를 작성할 때 이것은 생명의 은인이 될 수 있습니다. 실행될 때 명령과 해당 매개변수를 인쇄합니다.

빠른 “거칠고 준비된” 형태의 실행 추적을 제공합니다. 논리 결함을 분리하고 버그를 찾는 것이 훨씬 더 쉬워집니다.

set -x 옵션을 “script-8.sh”에 추가하고 “script-10.sh”로 저장하고 실행 가능하게 만듭니다.

#!/bin/bash
set -euxo pipefail

if [ -z "${New_Var:-}" ]; then
  echo "New_Var has no value assigned to it."
fi

추적 라인을 보려면 실행하십시오.

./script-10.sh

터미널에 기록된 -x 추적 라인으로 스크립트 실행.

이러한 사소한 예제 스크립트에서 버그를 찾는 것은 쉽습니다. 더 많은 관련 스크립트를 작성하기 시작하면 이러한 옵션이 그 가치를 증명할 것입니다.