코드 정보:

코드 정보:

이 bash 스크립트가 있습니다.

gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz | awk '/ath_bstuck_tasklet/ { print $4 }' | sort | uniq -c > /tmp/netgear_beacon.txt
echo "There are  `wc -l /tmp/netgear_beacon.txt | awk '{print $1}'` Stuck beacon; resetting" >> /tmp/netgear_beacon.txt

gunzip -c /var/log/cisco/cisco.log-`date +%Y%m%d`.gz | awk '/Virtual device ath0 asks to queue packet/ { print $4 }' | sort | uniq -c > /tmp/netgear_buffer_queue.txt
echo "There are  `wc -l /tmp/netgear_buffer_queue.txt | awk '{print $1}'`  routers with 'Virtual device ath0 asks to queue packet' errors" >> /tmp/netgear_buffer_queue.txt

gunzip -c /var/log/cisco/cisco.log-`date +%Y%m%d`.gz | awk '/CMS_MSG_DNSPROXY_RELOAD/ { print $4 }' | sort | uniq -c > /tmp/netgear_dns.txt
echo "There are  `wc -l /tmp/netgear_dns.txt | awk '{print $1}'`  routers with 'DNS Proxy Issue' errors" >> /tmp/netgear_dns.txt

gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz | awk '/beacon/ { print $4 }' | sort | uniq -c > /tmp/netgear_beacon_frame.txt
echo "There are  `wc -l /tmp/netgear_beacon_frame.txt | awk '{print $1}'` routers with beacon frame errors" >> /tmp/netgear_beacon_frame.txt

gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz | awk '/ACK/ { print $4 }' | sort | uniq -c | awk -v x=50 '$1 >= x' > /tmp/netgear_ACK.txt
echo "There are  `wc -l /tmp/netgear_ACK.txt | awk '{print $1}'` routers with more than 50 ACK" >> /tmp/netgear_ACK.txt

gunzip나는 명령을 매번 반복 하지 않으려고 노력했습니다 . 한 번만 실행하고 모든 단계에서 사용하겠습니다. 변수를 고려하고 있는데 이것이 모범 사례입니까?

답변1

"모범 사례"는 없습니다. 이해가 되고 일을 더 쉽게 만드는 일을 하세요.

공통 부분을 추출하고 나머지 부분을 매개변수화하는 것은 다음과 같은 문제입니다.

lines="`gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz`"
#gunzip would always output the same thing on the same day, so 
#just run it once and store the results in a variable
grepAndLog(){
  local regex="$1" file="$2" msg="$3" filter="${4:-cat}"
  #^names for positional parameters

  printf "%s\n" "$lines" | grep "$regex" | cut -d' ' -f4 | sort | uniq -c | eval "$filter"  > "/tmp/$file"
  local count=`wc -l < "/tmp/$file"`   
  echo "There are $count "" $msg" >> "/tmp/$file"
}
grepAndLog ath_bstuck_tasklet netgear_bacon.txt \
 'Stuck beacon; resetting'
grepAndLog netgear_buffer_queue netgear_buffer_queue.txt \
 "routers with 'Virtual device ath0 asks to queue packet' errors"
grepAndLog CMS_MSG_DNSPROXY_RELOAD netgear_dns.txt \
 " routers with 'DNS Proxy Issue' errors"
grepAndLog ath_bstuck_tasklet netgear_bacon.txt \
 " routers with beacon frame errors"
grepAndLog ACK netgear_ACK.txt \
 " routers with more than 50 ACK" 'awk -v x=50 "\$1 >= x"'

여전히 주로 쉘 솔루션입니다. 하지만 IMO에서는 더 읽기 쉽고 길이도 40% 이상 짧습니다.

코드 정보:

대신 awk 표현식을 사용하고 있습니다 grep "$regex" | cut -d' ' -f4. 그 외에도 이 grepAndLog함수는 스크립트의 각 줄에서 수행하는 작업을 일반화한 것입니다. 몇 가지 입력(gunzip의 출력)이 있고, 이를 표현식(인수 $regex)에 대해 grep하고, 결과 줄을 출력하고, 정렬하고, add 접두사는 로 계산됩니다 . 그런 다음 처음에는 일정하고 끝에서는 달라지는 메시지에 행 $file수(대신 추가 wc -l < "$file") 를 추가합니다( ).wc -l "$file" | awk ...$msg

마지막 줄에서는 단순히 grep을 사용하는 것이 아니라 그 위에 또 다른 필터를 사용하고 있습니다. if함수에서 이에 대한 분기를 생성하는 대신 cat네 번째 인수가 없는 일반적인 경우에 이를 암시적 기본 추가 필터로 사용합니다. local filter="${4:-cat}"즉, 네 번째 인수에 내용이 제공되는 함수 지역 변수 필터를 생성한다는 의미입니다. , 또는 cat네 번째 인수가 제공되지 않은 경우). cat네 번째 인수가 제공되면 재정의됩니다 grepAndLog.

답변2

여기서 가장 좋은 방법은 다음과 awk유사한 .

gunzip -c /var/log/cisco/cisco.log-$(date +%Y%m%d).gz | awk '
/ath_bstuck_tasklet/ { netgear_beakon[$4] = 1 }
/Virtual device ath0 asks to queue packet/ { netgear_buffer_queue[$4] = 1 }
...
/ACK/ { netgear_ACK[$4] ++ }
END {
  n=0; for(k in netgear_beakon) n++; print n,"Stuck beacon; resetting";
  n=0; for(k in netgear_buffer_queue) n++; print n,"routers with Virtual device ath0 asks to queue packet";
  ...
  n=0; for(k in netgear_ACK) n+=(netgear_ACK[k]>=50); print n,"routers with more than 50 ACK"
}'

파일을 여러 번 읽는 것 외에도 sort여러 번 실행할 필요도 없습니다. uniq이는 배열의 각 고유 항목을 저장(또는 계산)한 다음 각 배열의 키를 반복하여 항목 수를 계산합니다.

관련 정보