Linux Bash 스크립트를 실행하기 전에 구문을 확인하는 방법
게시 됨: 2022-06-16Linux Bash 스크립트의 버그와 오타는 스크립트가 실행될 때 끔찍한 일을 일으킬 수 있습니다. 다음은 스크립트를 실행하기 전에 스크립트 구문을 확인하는 몇 가지 방법입니다.
그 성가신 버그
코드를 작성하는 것은 어렵습니다. 또는 더 정확하게 말하면 버그가 없는 중요하지 않은 코드를 작성하는 것은 어렵습니다. 그리고 프로그램이나 스크립트에 코드 줄이 많을수록 버그가 있을 가능성이 높아집니다.
프로그래밍 언어는 이것과 직접적인 관련이 있습니다. 어셈블리 프로그래밍은 C 프로그래밍보다 훨씬 어렵고 C 프로그래밍은 Python 프로그래밍보다 더 어렵습니다. 프로그래밍하는 언어가 낮을수록 더 많은 작업을 스스로 수행해야 합니다. Python은 내장된 가비지 수집 루틴을 즐길 수 있지만 C와 어셈블리는 확실히 그렇지 않습니다.
Linux 셸 스크립트를 작성하는 것은 그 자체로 어려움이 있습니다. C와 같은 컴파일된 언어를 사용하면 컴파일러라는 프로그램이 소스 코드(텍스트 파일에 입력한 사람이 읽을 수 있는 명령)를 읽고 이진 실행 파일로 변환합니다. 이진 파일에는 컴퓨터가 이해하고 실행할 수 있는 기계어 코드 명령이 포함되어 있습니다.
컴파일러는 읽고 구문 분석하는 소스 코드가 언어의 구문 및 기타 규칙을 따르는 경우에만 이진 파일을 생성합니다. 예약어 (언어의 명령어 중 하나)나 변수 이름의 철자를 틀리면 컴파일러에서 오류가 발생합니다.
예를 들어, 어떤 언어는 변수를 사용하기 전에 선언해야 한다고 주장하지만 다른 언어는 그렇게 까다롭지 않습니다. 작업 중인 언어에서 변수를 선언해야 하지만 이를 잊어버린 경우 컴파일러는 다른 오류 메시지를 표시합니다. 이러한 컴파일 시간 오류가 성가신 만큼 많은 문제를 포착하고 해결해야 합니다. 그러나 구문상 버그 가 없는 프로그램이 있다고 해도 프로그램에 버그가 없는 것은 아닙니다. 그것과는 거리가 멀다.
논리적 결함 으로 인한 버그는 일반적으로 발견하기가 훨씬 더 어렵습니다. 프로그램에 2와 3을 추가하도록 지시했지만 실제로 2와 2를 추가하기를 원했다면 예상한 답을 얻지 못할 것입니다. 그러나 프로그램은 수행하도록 작성된 것입니다. 프로그램의 구성이나 구문에는 문제가 없습니다. 문제는 당신입니다. 당신은 당신이 원하는 것을 하지 않는 잘 구성된 프로그램을 작성했습니다.
테스트가 어렵다
프로그램을 철저하게 테스트하는 것은 단순한 프로그램일지라도 시간이 많이 걸립니다. 몇 번 실행하는 것만으로는 충분하지 않습니다. 코드의 모든 부분이 확인되도록 코드의 모든 실행 경로를 테스트해야 합니다. 프로그램에서 입력을 요청하는 경우 허용되지 않는 입력을 포함하여 모든 조건을 테스트할 수 있도록 충분한 범위의 입력 값을 제공해야 합니다.
고급 언어의 경우 단위 테스트와 자동화된 테스트는 철저한 테스트를 관리 가능한 연습으로 만드는 데 도움이 됩니다. 따라서 문제는 버그가 없는 Bash 셸 스크립트를 작성하는 데 사용할 수 있는 도구가 있습니까?
대답은 Bash 쉘 자체를 포함하여 예입니다.
Bash를 사용하여 스크립트 구문 확인
Bash -n
(noexec) 옵션은 Bash에 스크립트를 실행하지 않고 스크립트를 읽고 구문 오류가 있는지 확인하도록 지시합니다. 스크립트의 의도에 따라 스크립트를 실행하고 문제를 찾는 것보다 훨씬 안전할 수 있습니다.
다음은 확인할 스크립트입니다. 복잡하지 않고 주로 if
문 집합입니다. 월을 나타내는 숫자를 요청하고 수락합니다. 스크립트는 해당 월이 속한 시즌을 결정합니다. 분명히 사용자가 입력을 전혀 제공하지 않거나 숫자 대신 문자와 같은 잘못된 입력을 제공하는 경우에는 작동하지 않습니다.
#! /bin/bash read -p "월 입력(1~12): " 월 # 입력한 것이 있습니까? if [ -z "$month" ] 그 다음에 echo "월을 나타내는 숫자를 입력해야 합니다." 1번 출구 파이 # 유효한 월입니까? if (( "$month" < 1 || "$month" > 12)); 그 다음에 echo "월은 1에서 12 사이의 숫자여야 합니다." 0번 출구 파이 # 봄의 달인가? if (( "$월" >= 3 && "$월" < 6)); 그 다음에 echo "봄의 달입니다." 0번 출구 파이 # 여름방학인가요? if (( "$month" >= 6 && "$month" < 9)); 그 다음에 echo "여름의 달입니다." 0번 출구 파이 #가을달인가? if (( "$월" >= 9 && "$월" < 12)); 그 다음에 echo "가을입니다." 0번 출구 파이 # 겨울이 되어야 한다 echo "그건 겨울의 달입니다." 0번 출구
이 섹션에서는 사용자가 아무 것도 입력하지 않았는지 확인합니다. $month
변수가 설정되지 않았는지 테스트합니다.
if [ -z "$month" ] 그 다음에 echo "월을 나타내는 숫자를 입력해야 합니다." 1번 출구 파이
이 섹션에서는 1에서 12 사이의 숫자를 입력했는지 여부를 확인합니다. 또한 문자와 구두점 기호는 숫자 값으로 변환되지 않기 때문에 숫자가 아닌 잘못된 입력을 트래핑합니다.
# 유효한 월입니까? if (( "$month" < 1 || "$month" > 12)); 그 다음에 echo "월은 1에서 12 사이의 숫자여야 합니다." 0번 출구 파이
다른 모든 If 절은 $month
변수의 값이 두 값 사이에 있는지 확인합니다. 그렇다면 해당 월이 해당 시즌에 속합니다. 예를 들어, 사용자가 입력한 월이 6, 7 또는 8이면 여름 월입니다.
# 여름방학인가요? if (( "$month" >= 6 && "$month" < 9)); 그 다음에 echo "여름의 달입니다." 0번 출구 파이
예제를 통해 작업하려면 스크립트 텍스트를 복사하여 편집기에 붙여넣고 "seasons.sh"로 저장하십시오. 그런 다음 chmod
명령을 사용하여 스크립트를 실행 가능하게 만드십시오.
chmod +xseasons.sh
다음으로 스크립트를 테스트할 수 있습니다.
- 입력을 전혀 제공하지 않습니다.
- 숫자가 아닌 입력을 제공합니다.
- 1에서 12 사이의 범위를 벗어난 숫자 값을 제공합니다.
- 1에서 12 사이의 숫자 값을 제공합니다.
모든 경우에 동일한 명령으로 스크립트를 시작합니다. 유일한 차이점은 스크립트에 의해 승격될 때 사용자가 제공하는 입력입니다.
./계절.sh
예상대로 작동하는 것 같습니다. Bash가 스크립트의 구문을 확인하도록 합시다. -n
(noexec) 옵션을 호출하고 스크립트 이름을 전달하여 이를 수행합니다.
bash -n ./seasons.sh
이것은 "좋은 소식이 없는 소식"의 경우입니다. 우리를 명령 프롬프트로 조용히 되돌리는 것은 모든 것이 괜찮아 보인다고 말하는 Bash의 방식입니다. 스크립트를 방해하고 오류를 도입합시다.
첫 번째 if
절에서 then
을 제거합니다.
# 유효한 월입니까? if (( "$month" < 1 || "$month" > 12)); # "그때"가 제거되었습니다. echo "월은 1에서 12 사이의 숫자여야 합니다." 0번 출구 파이
이제 사용자의 입력 없이 먼저 스크립트를 실행한 다음 입력을 사용하여 스크립트를 실행해 보겠습니다.
./계절.sh
스크립트가 처음 실행될 때 사용자는 값을 입력하지 않으므로 스크립트가 종료됩니다. 우리가 방해한 부분에는 도달하지 못했습니다. 스크립트는 Bash의 오류 메시지 없이 종료됩니다.
스크립트가 두 번째 실행될 때 사용자는 입력 값을 제공하고 첫 번째 if 절이 실행되어 사용자의 입력이 온전한지 확인합니다. 그러면 Bash에서 오류 메시지가 표시됩니다.
Bash는 스크립트의 논리 를 고려하지 않기 때문에 해당 절의 구문과 다른 모든 코드 라인을 확인합니다. 스크립트가 실행되고 있지 않기 때문에 Bash가 스크립트를 확인할 때 사용자에게 숫자를 입력하라는 메시지가 표시되지 않습니다.
스크립트의 다른 가능한 실행 경로는 Bash가 구문을 확인하는 방법에 영향을 미치지 않습니다. Bash는 스크립트의 상단에서 하단으로 간단하고 체계적으로 작동하여 모든 라인의 구문을 확인합니다.
ShellCheck 유틸리티
유닉스 전성기의 C 소스 코드 검사 도구의 이름을 딴 린터는 프로그래밍 오류, 문체 오류, 의심스럽거나 의심스러운 언어 사용을 감지하는 데 사용되는 코드 분석 도구입니다. Linters는 많은 프로그래밍 언어에서 사용할 수 있으며 현학적인 것으로 유명합니다. linter가 발견한 모든 것이 그 자체 로 버그는 아니지만 그들이 발견한 모든 것이 주의를 기울일 가치가 있습니다.
ShellCheck는 셸 스크립트용 코드 분석 도구입니다. Bash용 린터처럼 작동합니다.
누락된 예약어를 스크립트에 then
넣고 다른 것을 시도해 보겠습니다. 첫 번째 if
절에서 여는 대괄호 "["를 제거합니다.
# 입력한 것이 있습니까? if -z "$month" ] # 여는 대괄호 "["가 제거됨 그 다음에 echo "월을 나타내는 숫자를 입력해야 합니다." 1번 출구 파이
Bash를 사용하여 스크립트를 확인하면 문제를 찾지 않습니다.
bash -nseasons.sh
./계절.sh
그러나 스크립트를 실행 하려고 하면 오류 메시지가 표시됩니다. 그리고 오류 메시지에도 불구하고 스크립트는 계속 실행됩니다. 이것이 일부 버그가 위험한 이유입니다. 스크립트에서 추가로 수행되는 작업이 사용자의 유효한 입력에 의존하는 경우 스크립트의 동작은 예측할 수 없습니다. 잠재적으로 데이터를 위험에 빠뜨릴 수 있습니다.
Bash -n
(noexec) 옵션이 스크립트에서 오류를 찾지 못하는 이유는 여는 대괄호 "["가 [
라는 외부 프로그램이기 때문입니다. Bash의 일부가 아닙니다. test
명령을 사용하는 약식 방법입니다.
Bash는 스크립트의 유효성을 검사할 때 외부 프로그램의 사용을 확인하지 않습니다.
ShellCheck 설치
ShellCheck는 설치가 필요합니다. Ubuntu에 설치하려면 다음을 입력하십시오.
sudo apt install shellcheck
Fedora에 ShellCheck를 설치하려면 이 명령을 사용하십시오. 패키지 이름은 대소문자가 혼합되어 있지만 터미널 창에서 명령을 실행하면 모두 소문자입니다.
sudo dnf install ShellCheck
Manjaro 및 유사한 Arch 기반 배포판에서는 pacman
을 사용합니다.
sudo pacman -S shellcheck
ShellCheck 사용
스크립트에서 ShellCheck를 실행해 보겠습니다.
shellcheckseasons.sh
ShellCheck는 문제를 찾아 보고하고 추가 정보에 대한 링크 집합을 제공합니다. 링크를 마우스 오른쪽 버튼으로 클릭하고 나타나는 컨텍스트 메뉴에서 "링크 열기"를 선택하면 링크가 브라우저에서 열립니다.
ShellCheck는 또한 심각하지 않은 또 다른 문제를 찾습니다. 녹색 텍스트로 보고됩니다. 이것은 아웃앤아웃 오류가 아니라 경고임을 나타냅니다.
오류를 수정하고 누락된 "[." 한 가지 버그 수정 전략은 우선 순위가 가장 높은 문제를 먼저 수정하고 나중에 경고와 같은 우선 순위가 낮은 문제로 해결하는 것입니다.
누락된 "["를 교체하고 ShellCheck를 한 번 더 실행했습니다.
shellcheckseasons.sh
ShellCheck의 유일한 출력은 이전 경고를 참조하므로 좋습니다. 수정이 필요한 우선순위가 높은 문제는 없습니다.
경고는 -r
(있는 그대로 읽기) 옵션 없이 read
명령을 사용하면 입력의 모든 백슬래시가 이스케이프 문자로 처리된다는 것을 알려줍니다. 이것은 린터가 생성할 수 있는 현학적 출력 유형의 좋은 예입니다. 우리의 경우 사용자는 어쨌든 백슬래시를 입력해서는 안 됩니다. 숫자를 입력해야 합니다.
이와 같은 경고는 프로그래머 측의 판단이 필요합니다. 그것을 고치기 위해 노력할 것인가, 아니면 그대로 둘 것인가? 2초면 해결됩니다. 그리고 경고가 ShellCheck의 출력을 어지럽히는 것을 막을 것이므로 우리는 그 조언을 받아들일 수도 있습니다. read
명령의 플래그 옵션에 "r"을 추가하고 스크립트를 저장합니다.
read -pr "월 입력(1~12): " 월
ShellCheck를 한 번 더 실행하면 깨끗한 상태를 확인할 수 있습니다.
ShellCheck는 당신의 친구입니다
ShellCheck는 전체 범위의 문제를 감지, 보고 및 조언할 수 있습니다. 얼마나 많은 유형의 문제를 감지할 수 있는지 보여주는 불량 코드 갤러리를 확인하십시오.
무료이고 빠르며 셸 스크립트를 작성하는 데 많은 수고를 덜어줍니다. 좋아하지 않는 것은 무엇입니까?