셸 추적을 사용하여 셸 스크립트에서 명령 실행을 추적하는 방법
쉘 스크립트 디버깅 시리즈의 이 기사에서는 세 번째 쉘 스크립트 디버깅 모드인 쉘 추적을 설명하고 몇 가지 예제를 통해 작동 방식과 사용 방법을 보여줍니다.
이 시리즈의 이전 부분에서는 쉘을 활성화하는 방법에 대한 이해하기 쉬운 예를 통해 두 가지 다른 쉘 스크립트 디버깅 모드인 상세 모드 및 구문 검사 모드를 명확하게 설명합니다. 이러한 모드에서 스크립트 디버깅을 수행합니다.
- Linux에서 셸 스크립트 디버깅 모드를 활성화하는 방법 – 1부
- 셸 스크립트에서 구문 검사 디버깅 모드를 수행하는 방법 – 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부 시리즈와 관련된 질문이나 피드백을 처리할 수 있습니다.