Bash 스크립트의 명령 옵션 구문 분석

Bash 스크립트의 명령 옵션 구문 분석

나는 "빠른" 스크립트를 작성한 다음 메일 스위치(에코에서 파이프되는 구문)를 끄기 위해 "--nomail" 옵션을 추가하는 것을 고려했습니다.

나는 그것이 쉬울 것이라고 생각했지만 근본적으로 원본 스크립트를 잘 구성하지 않았기 때문에 이 "옵션"이 나를 죽였습니다.

Bash의 새로운 기능입니다... 감사합니다!

내 멋진 작업 스크립트! :

 ## Current threshold value setting
 THRESHOLD="80"                                      

 ## Input Files and Mailx
 LOCATIONS="fsIn.txt"                                               ## Edit "fsIn.txt" to add or change filesystems
 TOLIST="$(cat toList.txt | tr -s '\n' ' ' )"                       ## Sets who receives email if an error condition exists
 REPLYTO="$(cat replyTo.txt | tr -s '\n' ' ' )"                     ## sets the reply to email addresses
 FROM=”SCRIPT TEAM"                             ## Sets the "from" address on error emails
 SUBJECT="$HOST: ! STORAGE LEVEL MET OR EXCEEDED !"         ## Sets the subject line
 ############

 for i in $(cat $LOCATIONS)

 do

 ## Main df pipeline to return usage percentage
 CAP=$(df -PH --no-sync "$i" | awk 'NR>1'| awk {'print $5'} | sed 's/.$//')

for i in $(cat $LOCATIONS)                  #Several different file system locations are ‘catted’ in here .  E.g.  /dev

do

## Main df pipeline to return usage percentage to stdout and piped to mailx
CAP=$(df -PH --no-sync "$i" | awk 'NR>1'| awk {'print $5'} | sed 's/.$//')
        if [ $CAP -ge $THRESHOLD ]
            then
           (echo                               
            echo "---------- CAPACITY TEST FAILED ---------- "
            echo -n "  SYSTEM NAME: " ; uname -n
            echo -n "  USER DETAIL: " ; whoami
            echo "  TEST AREA:   $i "
            echo "  USED SPACE:  $CAP% "
            echo "  THRESHOLD:   $THRESHOLD% "
            echo "  !!!!!! THRESHOLD EXCEEDED !!!!!! ") | tee >(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
            echo

        else
            echo
            echo "++++++++++ CAPACITY TEST PASSED ++++++++++ "
            echo "  TEST AREA:   $i "
            echo "  USED SPACE:  $CAP% "
            echo "  THRESHOLD:   $THRESHOLD% "
            echo " !!! SUCCESS SUCCESS SUCCESS SUCCESS !!! "
            echo
    fi

done

exit 0

이것은 아주 잘 작동합니다! 하지만 --nomail 옵션을 포함하도록 재구성하는 방법을 모르겠습니다. "사례"가 신중한 것 같지만 여기서는 길을 잃었습니다.

어떤 아이디어가 있나요?

매우 감사합니다!

답변1

간단한 대답은 두 가지입니다.

  • send_emailto 와 같은 플래그를 설정하고 true이메일 억제 매개변수가 있는 경우 이를 설정 해제하거나 false로 설정합니다.
  • 출력이 될 변수나 임시 파일을 조합한 다음 실제 이메일 전송을 함수 호출에 전달하여 미리 이메일을 작성합니다.

예를 들어:

send_email="true"
handle_email() {
    echo "$email_body" | mailx -s "$subject" -r "$from" -S replyto="$replyto" ${recipients[@]}
}

[...]
if [[ "--nomail" == "$1" ]]; then
    send_email=false
fi
[...]
if [[ true == "$send_email ]]; then
    handle_email
fi

답변2

고쳐 쓰다

나는 돌아가서 귀하의 질문 전체를 읽었으며 원래 귀하가 요청한 질문과 약간 다른 질문에 대답했다는 것을 깨달았습니다. 그래서 여기에 있습니다:

  1. 당신의 구조는 훌륭합니다. 스크립트 시작 부분에서 명령 옵션을 구문 분석합니다.

  2. case예, 문을 사용 하여 확인할 수 있습니다 $1(아래 원래 답변 참조). 하지만 한 가지 옵션만 계획하는 경우 단일 테스트를 쉽게 수행할 수 있습니다(아래 원래 답변 참조). case여러 가지 가능한 옵션이 포함된 명령문을 사용하려면 해당 명령을 while명령 줄의 다음 단어/옵션으로 대체합니다 .while "$1" ; do case ... esac; shift; doneshift$1

원래 답변

이 문제를 해결하는 방법에는 여러 가지가 있습니다. 이것이 유일한 옵션이거나 몇 가지 옵션만 있는 경우 직접 수동으로 구문 분석하는 것을 고려할 수 있습니다. 쉘 언어에서는 쉘 명령 뒤에 오는 모든 단어를 쉘이라고 합니다.매개변수, 그리고 각각은위치 매개변수, 양식은 1 $n부터 시작됩니다 n. 따라서 테스트를 수행하여 문제가 발생하는지 확인 [[ $1 == "--nomail" ]]하고 그에 따라 조치를 취할 수 있습니다. 이는 옵션이 하나만 있는 간단하고 간단한 방법입니다.

getopts옵션이 많은 더 복잡한 셸 스크립트의 경우 특정 형태의 명령을 활용하여 옵션을 구문 분석 해야 할 수도 있습니다 . 셸에는 내장 버전이 bash포함되어 있으며 명령줄에 then(기본 호출기가 설정된 경우)을 입력하여 자세한 내용을 알아볼 수 있습니다 .getoptsman bashless/^ *getopt

답변3

다른 답변에서는 이미 명령줄 옵션을 사용하는 방법을 언급했습니다(즉, "$1"직접 확인하거나 사용 getopts). 내 대답은 --nomail스크립트를 처음부터 다시 작성할 필요 없이 옵션을 사용하도록 스크립트를 빠르게 수정하는 방법입니다 . 쉘 스크립팅 기술과 지식의 점진적인 향상을 활용하려면 장기적으로 이 작업을 수행해야 합니다.

가장 확실한 방법은 변수나 임시 파일을 사용하여 인쇄하려는 출력을 저장하거나 인쇄하여 메일로 보낸 다음 매번 이를 어떻게 처리할지 선택하는 것입니다.

덜 분명한 방법은 파이프를 표준 입력 인지 아니면 그냥 입력인지 tee >(mailx ...)를 결정하는 함수 호출에 대한 파이프로 바꾸는 것입니다 . 이 접근 방식을 사용하면 출력을 저장할 필요가 없으며 출력을 파이프하고 함수가 처리하도록 두면 됩니다. 나머지 코드는 알거나 신경 쓸 필요가 없습니다(그리고 가장 중요한 것은 처리하기 위해 작성할 필요가 없습니다). 두 경우 모두).teemailxcat

그게 다야 ...

먼저 스크립트 시작 부분 근처에 다음과 같은 코드를 추가합니다.

# set the default, i.e. to send mail.
send_email=1

# Very basic option processing. Using getopts would be better.
[ "$1" == "--nomail" ] && send_email=''

myoutput() {
  if [ "$send_email" ] ; then
    # print stdin to stdout AND mail it
    tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
  else 
    # only print stdin to stdout. no mail.
    cat
  fi
}

둘째, | tee ...루프 내에서 교체하여 여기에 정의된 함수를 사용합니다.for| myoutput

( myoutput형편없는 함수 이름입니다. 이름을 바꾸 cat_or_mail거나 가장 이해하기 쉬운 이름으로 바꾸세요.)

이상적으로 함수는 전역 변수에 의존하기보다는 매개변수를 허용해야 하며 다음과 같이 작성되어야 합니다.

myoutput() {
  local send_email SUBJECT FROM REPYLTO TOLIST

  # more of the primitive option handling.  getopts can and should be used
  # inside a function too.    
  send_email="$1"
  SUBJECT="$2"
  FROM="$3"
  REPLYTO="$4"
  TOLIST="$5"

  # add code here to check if those variables contain valid values.
  # print warnings and/or abort and/or set appropriate defaults if they don't.

  if [ "$send_email" ] ; then
    # print stdin to stdout AND mail it
    tee <(mailx -s "$SUBJECT" -r "$FROM" -S replyto="$REPLYTO" "$TOLIST")
  else 
    # only print stdin to stdout. no mail.
    cat
  fi
}

그리고 전화해... | myoutput "$send_email" "$SUBJECT" "$FROM" "$REPLYTO" "$TOLIST"

이렇게 하면 전역 변수를 미리 설정할 필요 없이 함수를 재사용할 수 있습니다. 필요한 값으로 호출하기만 하면 됩니다.

관련 정보