[완료] [질문] perl - vmstat 결과의 평균 (array의 칼럼별 평균)

김규태의 이미지

안녕하세요.

vmstat 의 결과가 보통 아래와 같은 형식으로 나옵니다.
procs memory page faults cpu
r b avm free re pi po fr sr cy in sy cs us sy wa id

8 0 26 12 0 0 0 0 0 0 12614 294612 53600 32 8 22 38
5 0 26 12 0 0 0 0 0 0 14542 259303 47595 37 8 26 29
6 0 26 12 0 0 0 0 0 0 12291 164999 49580 36 7 25 31
4 0 26 12 0 0 0 0 0 0 10830 151400 42955 28 6 19 47
6 0 26 12 0 0 0 0 0 0 12799 118963 44968 34 7 28 32

이 결과를 string으로 받아서
행렬 계산하듯이 하면 각 항목별 평균을 구할 수 있는데
혹시 보다 쉬운 방법으로 각 항목별 평균을 구하는 방법이 있으면 알려주세요.

$ret = `vmstat 1 6 | tail -5 ` ;

감사합니다.

aero의 이미지

일반적인 방법

#!/usr/bin/env perl
use strict;
use warnings;
 
my @sum;
my $row_cnt = 0;
while (<DATA>) {
    my $col_cnt = 0;
    foreach my $num ( split /\s+/, $_ ) {
        $sum[$col_cnt] += $num;
        $col_cnt++;
    }
    $row_cnt++;
}
 
my @average = map { $_ / $row_cnt } @sum;
print "@average\n";
 
__DATA__
8 0 26 12 0 0 0 0 0 0 12614 294612 53600 32 8 22 38
5 0 26 12 0 0 0 0 0 0 14542 259303 47595 37 8 26 29
6 0 26 12 0 0 0 0 0 0 12291 164999 49580 36 7 25 31
4 0 26 12 0 0 0 0 0 0 10830 151400 42955 28 6 19 47
6 0 26 12 0 0 0 0 0 0 12799 118963 44968 34 7 28 32

결과

5.8 0 26 12 0 0 0 0 0 0 12615.2 197855.4 47739.6 33.4 7.2 24 35.4
김규태의 이미지

먼저 답변에 감사드립니다.

질문이 있습니다.
my @average = map { $_ / $row_cnt } @sum;
구문에 대해서 설명을 부탁드려도 될까요?

그리고 vmstat 결과를 string 변수에 담아서 처리하므로
아래와 같이 구현했습니다.

# 평균을 구한다.
$row_cnt = 0 ;
# $ret = `vmstat 1 $vmstat_cnt | tail -($vmstat_cnt -1) ` ;
$ret = " 8 0 26 12 0 0 0 0 0 0 12614 294612 53600 32 8 22 38
5 0 26 12 0 0 0 0 0 0 14542 259303 47595 37 8 26 29
6 0 26 12 0 0 0 0 0 0 12291 164999 49580 36 7 25 31
4 0 26 12 0 0 0 0 0 0 10830 151400 42955 28 6 19 47
6 0 26 12 0 0 0 0 0 0 12799 118963 44968 34 7 28 32" ;

@vm_sum = "" ;
@vmstats = "" ;
foreach $line ( split /\n/, $ret ) {
$line =~ s/^\s*//g ;
# chomp($line) ;
$col_cnt = 0;
foreach $value ( split /\s+/, $line ) {
# @vmstats = split / +/, $line ;
$vm_sum[$col_cnt] += $value ;
$col_cnt++;
}
$row_cnt++;
}
@vmstats = map { $_ / $row_cnt } @vm_sum ;
print "row_cnt : ", "$row_cnt\n";
print "col_cnt : ", "$col_cnt\n";
print "@vm_sum\n";
print "@vmstats\n";

aero의 이미지

my @average = map { $_ / $row_cnt } @sum; 에서

우선 map 함수의 용도는 http://perldoc.perl.org/functions/map.html 을 보시면 되며
map은 함수형언어의 특징을 가져온 것이죠.
map은 다음과 같은 두가지 형태로 쓸 수 있으며

1. map 표현식,리스트

my @a = map $_*2, (1,2,3,4);
#@a는 (2,4,6,8)

2. map 블럭 리스트 (,가 없음을 주의, 블럭안에는 구문(statement)가 올 수 있다.)

my @b = (2,4,6,8)
my @a = map { $_/2 } @b;
#@a는 (1,2,3,4)

뒤의 리스트에서 하나씩 가져와서 표현식 혹은 블럭의 결과를 적용한 결과를 다시 리스트로 리턴합니다.

perl의 grep함수도 map이랑 비슷한 성격의 함수죠.

my @average = map { $_ / $row_cnt } @sum;

를 foreach를 사용해서 바꿔보면

my @average
foreach (@sum) {
    push @average, $_ / $row_cnt;
}

처럼 되겠죠.
김규태의 이미지

친절한 설명 정말 감사드립니다.
최종적으로 아래와 같이 만들었습니다. (제 목적은 완료했습니다.)
혹시 시간이 되시면 보시고 추가적인 조언 부탁드립니다. ^^

#!/usr/bin/env perl
#!/usr/bin/perl
#!/opt/perl/bin/perl
################################################################################
# vmstat.pl
#
# Developed 05/01/2006 by KueTae Kim
#   <a href="mailto:ktkim87@empal.com" rel="nofollow">ktkim87@empal.com</a>   <a href="mailto:kuetae.kim@gmail.com" rel="nofollow">kuetae.kim@gmail.com</a>
#
# * 목적
#   - DB 모니터링시 시스템 리소스(특히 CPU, Memory)를 같이 모니터링함.
#   - 가끔 DB 내부 리소스 경합보다는 시스템 리소스 부족으로 성능저하/장애발생함.
#   - 툴에서 제공하는 5분 주기의 평균값으로는 분석이 어려운 경우 존재함.
#
# * 용도
#   - DB 장애시점 시스템 리소스 점검
#   - DB 진단시 시스템 CPU, 메모리 관련 사용 추이 그래프 (Excel 활용)
#
# * 사용방법
#   $ vmstat.pl 5 1000000
#
# HISTORY:
#   Date       Developer Description
#   ---------- --------- ---------------------------
#   2006.05.01 ktkim     HP-UX
#   2007.12.15 ktkim     AIX 추가
#   2009.04.05 ktkim     Sun OS 추가
#   2009.09.20 ktkim     평균값으로 대체
################################################################################
 
use strict;
use warnings;
# use DBI;
use IO::Handle;
use Time::HiRes qw(gettimeofday usleep tv_interval);
 
my $ret ;
my @vmstat_sum ;
my @vmstat_avg ;
 
my $run_cnt = 0 ;
my $max_cnt = 17280 ;
my $sleep_time = 5 ;
 
my $vmstat_cnt = $sleep_time ;
my $row_cnt ;
my $col_cnt ;
 
my $osname ;
my $hostname ;
my $curr_date = "1" ;
my $tmp_date = "0" ;
my $curr_datetime ;
my $fname ;
my $line ;
my $value ;
my $header_print = "N" ;
my $header_count = 20  ;
my $vmheader_SunOS ;
my $vmheader_HPUX  ;
my $vmheader_AIX  ;
 
 
$vmheader_SunOS = qq{
                        kthr     memory(GB)               page                              faults            cpu
   DateTime           r   b   w  swap free    re    mf    pi    po    fr  de  sr       in     sy     cs    us  sy  id 
} ;
 
$vmheader_HPUX = qq{
                        procs     memory(GB)              page                              faults            cpu
   DateTime           r   b   w   avm free    re    at    pi    po    fr  de  sr       in     sy     cs    us  sy  id 
 
} ;
 
 
$vmheader_AIX = qq{
                      kthr    memory(GB)               page                             faults            cpu
   DateTime           r   b   avm free    re    pi    po     fr     sr     cy       in     sy     cs    us  sy  wa  id 
 
} ;
 
################################################################################
# Command Line Input
################################################################################
if ( $#ARGV == 0 ) {
  $sleep_time = $ARGV[0] ;
} elsif ( $#ARGV == 1 ) {
  $sleep_time = $ARGV[0] ;
  $max_cnt    = $ARGV[1] ;
} else {
  print "Usage: $0  sleep  count \n" ;
}
$vmstat_cnt = $sleep_time ;
 
################################################################################
# Main
################################################################################
 
$osname   = `uname -s` ;
chomp($osname) ;
$hostname = `hostname` ;
chomp($hostname) ;
$curr_date = currdate() ;
$fname = "vmstat_" . $hostname . "_" . $curr_date . ".log" ;
 
open( FH,  "+>>" . $fname  ) || die "Can't open log file $fname." ;
FH->autoflush(1);
 
while ( $max_cnt > $run_cnt ) {
  #-----------------------------------------------------------------------------
  #
  $tmp_date = currdate() ;
  if ( $curr_date ne $tmp_date  ) {
     close( FH ) ;
     $curr_date = $tmp_date ;
     $fname = "vmstat_" . $hostname . "_" . $curr_date . ".log" ;
     open( FH,  "+>>" . $fname  ) || die "Can't open log file $fname." ;
     FH->autoflush(1);
     print $fname , "\n" ;
  }
 
  $ret = `vmstat 1 $vmstat_cnt  | tail -($vmstat_cnt -1) ` ;
 
  # 평균을 구한다.
  @vmstat_sum = () ;
  @vmstat_avg = () ;
  $row_cnt = 0 ;
  foreach $line ( split /\n/, $ret ) {
    $line =~ s/^\s*//g ;
    # chomp($line) ;
    $col_cnt = 0;
    foreach $value ( split /\s+/, $line ) {
      # @vmstat_avg = split / +/,  $line ;
      $vmstat_sum[$col_cnt] += $value ;
      $col_cnt++;
    }
    $row_cnt++;
  }
  @vmstat_avg = map { $_ / $row_cnt } @vmstat_sum ;
 
  if ( ( $run_cnt % $header_count ) == 0 ) {
    $header_print = "Y"
  } else {
    $header_print = "N"
  }
 
  if ( $osname eq "SunOS" ) {
    printf(FH  $vmheader_SunOS ) if $header_print eq "Y" ;
    printf(FH "%s%4d%4d%4d  %4.0f%4.0f %6d%6d%6d%6d  %4d%4d%4d  %7d%7d%7d  %4d%4d%4d\n",
      currdatetime(), $vmstat_avg[0], $vmstat_avg[1],$vmstat_avg[2],
      $vmstat_avg[3]/1024/1024,$vmstat_avg[4]/1024/1024,
      $vmstat_avg[5],$vmstat_avg[6],$vmstat_avg[7],$vmstat_avg[8],$vmstat_avg[9],$vmstat_avg[10],$vmstat_avg[11],
      $vmstat_avg[16],$vmstat_avg[17],$vmstat_avg[18],
      $vmstat_avg[19],$vmstat_avg[20],$vmstat_avg[21] ) ;
  } elsif ( $osname eq "HP-UX" ) {
    printf(FH  $vmheader_HPUX ) if $header_print eq "Y" ;
    printf(FH "%s%4d%4d%4d  %4.0f%4.0f %6d%6d%6d%6d  %4d%4d%4d  %7d%7d%7d  %4d%4d%4d\n",
      currdatetime(), $vmstat_avg[0], $vmstat_avg[1],$vmstat_avg[2],
      $vmstat_avg[3]/1024/1024,$vmstat_avg[4]/1024/1024,
      $vmstat_avg[5],$vmstat_avg[6],$vmstat_avg[7],$vmstat_avg[8],$vmstat_avg[9],$vmstat_avg[10],$vmstat_avg[11],
      $vmstat_avg[12],$vmstat_avg[13],$vmstat_avg[14],
      $vmstat_avg[15],$vmstat_avg[16],$vmstat_avg[17] ) ;
  } elsif ( $osname eq "AIX" ) {
    printf(FH  $vmheader_AIX ) if $header_print eq "Y" ;
    printf(FH "%s%4d%4d  %4.0f%4.0f %6d%6d%6d%7d%7d%7d  %7d%7d%7d  %4d%4d%4d%4d\n",
      currdatetime(), $vmstat_avg[0], $vmstat_avg[1],
      $vmstat_avg[2*4.0/1024/1024.0],$vmstat_avg[3]*4.0/1024/1024.0,
      $vmstat_avg[4],$vmstat_avg[5],$vmstat_avg[6],   $vmstat_avg[7],$vmstat_avg[8],$vmstat_avg[9],
      $vmstat_avg[10],$vmstat_avg[11],$vmstat_avg[12],
      $vmstat_avg[13],$vmstat_avg[14],$vmstat_avg[16],$vmstat_avg[15] ) ;
  }
  $run_cnt = $run_cnt + 1 ;
  sleep 1 ;
}
 
 
sub currdate
{
  my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime() ;
  return( sprintf("%04d%02d%02d", $year+1900,$mon+1,$mday )  ) ;
}
 
sub currdatetime
{
  my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime() ;
  return( sprintf("%04d-%02d-%02d:%02d:%02d:%02d", $year+1900,$mon+1,$mday, $hour,$min,$sec)  ) ;
}
Tony의 이미지

$ cat data.txt
r b avm free re pi po fr sr cy in sy cs us sy wa id 
8 0 26 12 0 0 0 0 0 0 12614 294612 53600 32 8 22 38
5 0 26 12 0 0 0 0 0 0 14542 259303 47595 37 8 26 29
6 0 26 12 0 0 0 0 0 0 12291 164999 49580 36 7 25 31
4 0 26 12 0 0 0 0 0 0 10830 151400 42955 28 6 19 47
6 0 26 12 0 0 0 0 0 0 12799 118963 44968 34 7 28 32
$ R
> colMeans(read.table("data.txt", header=T))
       r        b      avm     free       re       pi       po       fr 
     5.8      0.0     26.0     12.0      0.0      0.0      0.0      0.0 
      sr       cy      in.       sy       cs       us     sy.1       wa 
     0.0      0.0  12615.2 197855.4  47739.6     33.4      7.2     24.0 
      id 
    35.4 
> q()
Save workspace image? [y/n/c]: n
$

죄송...

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.