df를 사용하고 특정 열에 대해 awk를 시도하십시오.

df를 사용하고 특정 열에 대해 awk를 시도하십시오.

내가 만들려고 하는 이 스크립트에 대한 다른 질문에서는(이것은 내가 만든 첫 번째 unix/linux 스크립트입니다) df를 사용하여 사용된 디스크 공간의 비율을 구하고 이를 루트 디렉토리로 이메일로 보내려고 합니다. . 우리의 지침은 df에서 /proc 플로피와 CDROM을 제외하라는 것입니다.

내가 지금까지 가지고 있는 것:

fsExclude=(/proc /dev/floppy /dev/cdrom) #Exclusions from df file system
fsUsed=15 #percent to watch for
WarnEmail=root #email for warning message
if (df -x $fsExclude | awk '$5' | sed '2p' > fsUsed)
then
df -h > dfFile.tmp
mail -s "WARNING: Almost out of disk space %" '$WarnEmail' < dfFile.tmp
rm dfFile.tmp
fi

이제 나는 이것에 몇 가지 문제가 있다는 것을 알고 있습니다. 어떤 종류의 출력이 나오는지 확인하기 위해 실행하면 다음과 같은 결과가 나옵니다(첫 번째 줄은 내가 포함하지 않은 if 문 위에 있는 메시지입니다).

Emailing admin, disk almost full...
3 
$WarnEmail... User unknown 
60 
awk:    cmd. line:1: print $4 
awk: cmd. line:1: ^ parse error    
/root/dead.letter... Saved message in /root/dead.letter 

더 많은 것이 있지만 나중에 저장하겠습니다. 아무런 문제 없이 비슷한 방식으로 스크립트 외부에 루트를 메일로 보냈지만 스크립트 내에서는 작동하지 않습니다. df의 awk 출력을 사용하여 %used 열에서 값을 가져와 fsUsed 값보다 큰지 작은지 확인하고 싶습니다. 그렇다면 들어가서 전체 df 출력을 루트에 이메일로 보내십시오. 내가 검색했을 때 누군가가 -perc 또는 -avail과 함께 무언가를 사용하도록 제안하는 것을 보았지만 여기서는 둘 다 작동하지 않습니다. 알 수 없다는 메시지가 표시되므로 awk로 돌아가려고 합니다.

이 문제를 해결하는 데 도움을 주시면 대단히 감사하겠습니다.

답변1

당신이 가진 주요 문제는

  1. fsExclude은 배열이며 필요한 모든 요소를 ​​얻으려면 ${array[@]}어쨌든 이 -x옵션에는 장치가 아닌 파일 시스템 유형이 필요합니다.

  2. 명령에 구문 오류가 있습니다 awk.

    awk '{print $5}' 
    

    그렇지 않은 경우 print5번째 필드가 있는지 평가하는 표현식이 사용되므로 awk5개 이상의 필드를 포함하는 모든 행이 인쇄됩니다.$5true

  3. 귀하의 목표를 이해하면 현재 백분율을 값과 비교하려는 것 같습니다 fsUsed. 그러나 명령을 실행하면 이라는 파일이 생성되고 fsUsed해당 파일의 출력이 인쇄됩니다 df. 당신이 원하는 것은

    if [ "$(df -x $fsExclude | awk '$5' | sed '2p')" -gt "$fsUsed" ]
    

    $()~라고 불리는명령 대체실행하는 모든 명령의 출력으로 확장됩니다. 비교하고 싶은게 바로 이거다그리고 fsUsed필요한 가치를 얻으려면 $.

  4. 작은 따옴표가 있습니다 $WarnEMail. 이는 변수가 아닌 문자열 리터럴로 처리된다는 의미입니다. 이 시도:

    mail -s "WARNING: Almost out of disk space %" "$WarnEmail" < dfFile.tmp
    
  5. 명령은 df여러 행을 반환하지만 단일 비교를 실행 중이므로 작동하지 않습니다. df출력의 모든 줄을 확인해야 합니다 .

그러면 불필요하게 복잡한 방식으로 작업을 수행하게 됩니다. 왜 안되나요?

#!/bin/bash
fsExclude="/proc|/dev/floppy|/dev/cdrom" #Exclusions from df file system
fsUsed=15 #percent to watch for
WarnEmail=root #email for warning message
problem=0;
df | grep -v "$fsExclude" |
    while read line
    do
    ## Check the percentage, send the mail if at least
    ## one mount point's percentage is > $fsUsed
    if [[ $(grep -oE '[0-9]+%' <<<"$line" | tr -d '%') -gt $fsUsed ]]
    then
        ## I'm not sure if `command | mail` works and I don't have a system
        ## I can test it on. If it doesn't, use a file as you did before. 
        df -h | mail -s "WARNING: Almost out of disk space %" "$WarnEmail" 
        ## No need to rpocess any more lines, exit the while loop
        break;
    fi
    done

답변2

하이라이트:

  • 명령을 실행 중입니다 df -x /proc /dev/floppy /dev/cdrom. 이는 존재하지 않는 유형의 파일 시스템(파일 시스템 유형은 ) 을 df건너뛰고 및 . 특정 장치는 무시할 수 없으며 필터링할 수 있습니다./procproc/dev/floppy/dev/cdrom

  • awk의 다섯 번째 필드를 인쇄하려면 다음을 사용하십시오. 이는 각 행에서 명령을 실행합니다 awk '{print $5}'. 다섯 번째 필드가 0이 아니거나 비어 있지 않은 경우(조건입니다. 해당 작업이 없으므로 기본 작업이 수행되고 전체 라인이 인쇄됩니다) 전체 라인이 인쇄됩니다. 문법 오류입니다.print $5awk '$5'$5awk 'print $5'

  • 에서 sed '2p' > fsUsed>기호는 리디렉션 연산자입니다. sed 명령의 출력은 임시 파일에 기록됩니다 fsUsed.

  • '$WarnEmail'달러 기호로 시작하는 10자로 구성된 리터럴 문자열입니다. 변수 참조를 확장하려면 큰따옴표를 사용하십시오.

반품:

  • 작은 출력을 저장하기 위해 임시 파일을 사용하지 마십시오. 사용명령 대체변수에 넣으세요.

  • 출력을 구문 분석할 때 이 옵션을 에 -P전달하십시오 . df그렇지 않으면 장치 경로가 너무 길 때 레코드 중간에 줄바꿈이 추가될 수 있습니다.

  • awk에서는 모든 필터링을 수행할 수 있습니다.

이는 이메일을 하나로 병합하는 스크립트를 작성하는 또 다른 방법입니다.

body=$(df -P | awk -v fsUsed=15 fsExclude='/dev/floppy /dev/cdrom' '
    BEGIN {split(fsExclude, fsExcludeArray)}
    NR == 1 {next}           # skip the header line
    $1 in fsExcludeArray {next}
    {$5 = sub(/%/, "")}      # remove the % character from the Use% column
    $5 > fsUsed {print}      # print lines with almost-full disks
')
if [ -n "$body" ]; then
  # $body is non-empty: there is at least one almost-full filesystem
  echo "$body" | mail -s "Warning: some filesystems are almost full" "$WarnEmail"
fi

관련 정보