내가 만들려고 하는 이 스크립트에 대한 다른 질문에서는(이것은 내가 만든 첫 번째 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
당신이 가진 주요 문제는
fsExclude
은 배열이며 필요한 모든 요소를 얻으려면${array[@]}
어쨌든 이-x
옵션에는 장치가 아닌 파일 시스템 유형이 필요합니다.명령에 구문 오류가 있습니다
awk
.awk '{print $5}'
그렇지 않은 경우
print
5번째 필드가 있는지 평가하는 표현식이 사용되므로awk
5개 이상의 필드를 포함하는 모든 행이 인쇄됩니다.$5
true
귀하의 목표를 이해하면 현재 백분율을 값과 비교하려는 것 같습니다
fsUsed
. 그러나 명령을 실행하면 이라는 파일이 생성되고fsUsed
해당 파일의 출력이 인쇄됩니다df
. 당신이 원하는 것은if [ "$(df -x $fsExclude | awk '$5' | sed '2p')" -gt "$fsUsed" ]
$()
~라고 불리는명령 대체실행하는 모든 명령의 출력으로 확장됩니다. 비교하고 싶은게 바로 이거다값그리고fsUsed
필요한 가치를 얻으려면$
.작은 따옴표가 있습니다
$WarnEMail
. 이는 변수가 아닌 문자열 리터럴로 처리된다는 의미입니다. 이 시도:mail -s "WARNING: Almost out of disk space %" "$WarnEmail" < dfFile.tmp
명령은
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
건너뛰고 및 . 특정 장치는 무시할 수 없으며 필터링할 수 있습니다./proc
proc
/dev/floppy
/dev/cdrom
awk의 다섯 번째 필드를 인쇄하려면 다음을 사용하십시오. 이는 각 행에서 명령을 실행합니다
awk '{print $5}'
. 다섯 번째 필드가 0이 아니거나 비어 있지 않은 경우(조건입니다. 해당 작업이 없으므로 기본 작업이 수행되고 전체 라인이 인쇄됩니다) 전체 라인이 인쇄됩니다. 문법 오류입니다.print $5
awk '$5'
$5
awk '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