웹사이트 검색

셸 추적을 사용하여 셸 스크립트에서 명령 실행을 추적하는 방법


쉘 스크립트 디버깅 시리즈의 이 기사에서는 세 번째 쉘 스크립트 디버깅 모드인 쉘 추적을 설명하고 몇 가지 예제를 통해 작동 방식과 사용 방법을 보여줍니다.

이 시리즈의 이전 부분에서는 쉘을 활성화하는 방법에 대한 이해하기 쉬운 예를 통해 두 가지 다른 쉘 스크립트 디버깅 모드인 상세 모드구문 검사 모드를 명확하게 설명합니다. 이러한 모드에서 스크립트 디버깅을 수행합니다.

  1. Linux에서 셸 스크립트 디버깅 모드를 활성화하는 방법 – 1부
  2. 셸 스크립트에서 구문 검사 디버깅 모드를 수행하는 방법 – 2부

쉘 추적이란 단순히 쉘 스크립트에서 명령 실행을 추적하는 것을 의미합니다. 쉘 추적을 켜려면 -x 디버깅 옵션을 사용하십시오.

이는 쉘이 실행될 때 터미널에 모든 명령과 해당 인수를 표시하도록 지시합니다.

아래의 sys_info.sh 셸 스크립트를 사용하여 시스템 날짜와 시간, 로그인한 사용자 수 및 시스템 가동 시간을 간략하게 인쇄합니다. 그러나 여기에는 찾아서 수정해야 하는 구문 오류가 포함되어 있습니다.

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;    
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME
}

check_root
print_sys_info

exit 0

파일을 저장하고 스크립트를 실행 가능하게 만듭니다. 스크립트는 루트에서만 실행할 수 있으므로 sudo 명령을 사용하여 아래와 같이 실행합니다.

chmod +x sys_info.sh
sudo bash -x sys_info.sh

위의 출력에서 출력이 변수 값으로 대체되기 전에 명령이 먼저 실행된다는 것을 알 수 있습니다.

예를 들어, date가 처음 실행되었고 해당 출력이 DATE 변수의 값으로 대체되었습니다.

다음과 같이 구문 오류만 표시하도록 구문 검사를 수행할 수 있습니다.

sudo bash -n sys_info.sh 

쉘 스크립트를 비판적으로 살펴보면 if 문에 닫는 fi 단어가 없다는 것을 알게 될 것입니다. 따라서 이를 추가하면 새 스크립트는 이제 아래와 같이 표시됩니다.

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
   fi    
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME
}

check_root
print_sys_info

exit 0

파일을 다시 저장하고 루트로 호출한 후 구문 검사를 수행합니다.

sudo bash -n sys_info.sh

위의 구문 검사 작업 결과는 여전히 라인 21의 스크립트에 버그가 하나 더 있음을 보여줍니다. 따라서 아직 구문 수정 작업이 남아 있습니다.

스크립트를 다시 한 번 분석적으로 살펴보면 21행의 오류는 ( ")가 누락되었기 때문에 발생한 것입니다. >print_sys_info 함수.

echo 명령에 닫는 큰따옴표를 추가하고 파일을 저장합니다. 변경된 스크립트는 아래와 같습니다.

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME"
}

check_root
print_sys_info

exit 0

이제 스크립트를 한 번 더 구문적으로 확인해보세요.

sudo bash -n sys_info.sh

이제 스크립트가 구문적으로 정확하기 때문에 위 명령은 출력을 생성하지 않습니다. 두 번째로 스크립트 실행을 모두 추적할 수도 있으며 제대로 작동할 것입니다.

sudo bash -x sys_info.sh

이제 스크립트를 실행하세요.

sudo ./sys_info.sh

쉘 스크립트 실행 추적의 중요성

셸 스크립트 추적은 구문 오류와 더 중요하게는 논리적 오류를 식별하는 데 도움이 됩니다. 예를 들어 sys_info.sh 셸 스크립트의 check_root 함수를 생각해 보세요. 이 함수는 스크립트 실행만 허용되므로 사용자가 루트인지 여부를 확인하기 위한 것입니다. 슈퍼유저에 의해.

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

여기서 마술은 적절한 숫자 연산자()를 사용하지 않으면 if 문 표현식 [ "$UID" -ne "$ROOT_ID" ]에 의해 제어됩니다. -ne 이 경우, 같지 않음을 의미), 결국 논리적 오류가 발생할 수 있습니다.

-eq(같음)를 사용했다고 가정하면 루트 사용자뿐만 아니라 모든 시스템 사용자가 스크립트를 실행할 수 있으므로 논리적 오류가 발생합니다.

check_root(){
    if [ "$UID" -eq "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

참고: 앞서 이 시리즈의 시작 부분에서 살펴본 것처럼 set shell 내장 명령은 셸 스크립트의 특정 섹션에서 디버깅을 활성화할 수 있습니다.

따라서 아래 줄은 함수의 실행을 추적하여 함수에서 이러한 논리적 오류를 찾는 데 도움이 됩니다.

논리적 오류가 있는 스크립트:

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -eq "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME"
}

#turning on and off debugging of check_root function
set -x ; check_root;  set +x ;
print_sys_info

exit 0

파일을 저장하고 스크립트를 호출하면 아래 출력과 같이 일반 시스템 사용자가 sudo 없이 스크립트를 실행할 수 있음을 알 수 있습니다. 이는 USER_ID 값이 0인 루트 ROOT_ID와 동일하지 않은 100이기 때문입니다.

./sys_info.sh

글쎄, 지금은 그게 다입니다. 쉘 스크립트 디버깅 시리즈가 끝났습니다. 아래 응답 양식을 사용하여 이 가이드 또는 전체 3부 시리즈와 관련된 질문이나 피드백을 처리할 수 있습니다.